diff --git a/.gitmodules b/.gitmodules index 4a136cff1cd..70164d48a30 100644 --- a/.gitmodules +++ b/.gitmodules @@ -5,9 +5,6 @@ [submodule "src/rust-installer"] path = src/tools/rust-installer url = https://github.com/rust-lang/rust-installer.git -[submodule "src/liblibc"] - path = src/liblibc - url = https://github.com/rust-lang/libc.git [submodule "src/doc/nomicon"] path = src/doc/nomicon url = https://github.com/rust-lang-nursery/nomicon.git @@ -23,9 +20,6 @@ [submodule "src/tools/rls"] path = src/tools/rls url = https://github.com/rust-lang-nursery/rls.git -[submodule "src/libcompiler_builtins"] - path = src/libcompiler_builtins - url = https://github.com/rust-lang-nursery/compiler-builtins.git [submodule "src/tools/clippy"] path = src/tools/clippy url = https://github.com/rust-lang-nursery/rust-clippy.git @@ -35,9 +29,6 @@ [submodule "src/tools/miri"] path = src/tools/miri url = https://github.com/solson/miri.git -[submodule "src/dlmalloc"] - path = src/dlmalloc - url = https://github.com/alexcrichton/dlmalloc-rs.git [submodule "src/doc/rust-by-example"] path = src/doc/rust-by-example url = https://github.com/rust-lang/rust-by-example.git @@ -61,7 +52,6 @@ path = src/tools/clang url = https://github.com/rust-lang-nursery/clang.git branch = rust-release-80-v2 - [submodule "src/doc/rustc-guide"] path = src/doc/rustc-guide url = https://github.com/rust-lang/rustc-guide.git diff --git a/.travis.yml b/.travis.yml index 3f2e43ab86d..9e46e6b8ef6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,7 @@ matrix: fast_finish: true include: # Images used in testing PR and try-build should be run first. - - env: IMAGE=x86_64-gnu-llvm-5.0 RUST_BACKTRACE=1 + - env: IMAGE=x86_64-gnu-llvm-6.0 RUST_BACKTRACE=1 if: type = pull_request OR branch = auto - env: IMAGE=dist-x86_64-linux DEPLOY=1 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 137fe613207..65cdfe67b5b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -39,7 +39,7 @@ don't know about, so please report liberally. If you're not sure if something is a bug or not, feel free to file a bug anyway. **If you believe reporting your bug publicly represents a security risk to Rust users, -please follow our [instructions for reporting security vulnerabilities](https://www.rust-lang.org/security.html)**. +please follow our [instructions for reporting security vulnerabilities](https://www.rust-lang.org/policies/security)**. If you have the chance, before reporting a bug, please [search existing issues](https://github.com/rust-lang/rust/search?q=&type=Issues&utf8=%E2%9C%93), diff --git a/Cargo.lock b/Cargo.lock index 69d929e913a..365d14c579b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,18 +1,23 @@ +[[package]] +name = "adler32" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "aho-corasick" -version = "0.6.7" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "alloc" version = "0.0.0" dependencies = [ - "compiler_builtins 0.0.0", + "compiler_builtins 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -20,12 +25,12 @@ name = "ammonia" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "html5ever 0.22.3 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "html5ever 0.22.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -59,9 +64,9 @@ dependencies = [ "colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -69,20 +74,20 @@ name = "atty" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace" -version = "0.3.9" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -92,7 +97,7 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "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)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -125,34 +130,39 @@ dependencies = [ "build_helper 0.1.0", "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)", + "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.5.1 (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)", - "serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "bufstream" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "build-manifest" version = "0.1.0" dependencies = [ - "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)", - "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "build_const" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "build_helper" version = "0.1.0" @@ -167,7 +177,7 @@ dependencies = [ [[package]] name = "byteorder" -version = "1.2.3" +version = "1.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -177,22 +187,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cargo" -version = "0.33.0" +version = "0.34.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)", + "bufstream 0.1.4 (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.21.0", - "crossbeam-utils 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crates-io 0.22.0", + "crossbeam-utils 0.6.2 (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.19 (registry+https://github.com/rust-lang/crates.io-index)", "curl-sys 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.0 (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)", - "flate2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "fwdansi 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "git2 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -200,35 +210,35 @@ dependencies = [ "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "home 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ignore 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ignore 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "im-rc 12.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazycell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "jobserver 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", "libgit2-sys 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "opener 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", - "pretty_env_logger 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "opener 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)", + "pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "proptest 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0", "rustfix 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "same-file 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (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)", + "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tar 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tar 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -239,9 +249,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (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)", - "serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -255,7 +265,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -277,11 +287,11 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -309,14 +319,14 @@ dependencies = [ "clippy_dev 0.0.1", "clippy_lints 0.0.212", "compiletest_rs 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", - "derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0", "rustc_tools_util 0.1.0", "semver 0.9.0 (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)", + "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -329,9 +339,9 @@ version = "0.0.1" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -341,18 +351,18 @@ dependencies = [ "cargo_metadata 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "if_chain 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (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)", - "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -392,15 +402,16 @@ name = "commoncrypto-sys" version = "0.2.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)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "compiler_builtins" -version = "0.0.0" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "core 0.0.0", + "rustc-std-workspace-core 1.0.0", ] [[package]] @@ -408,18 +419,19 @@ name = "compiletest" version = "0.0.0" dependencies = [ "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", - "filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", + "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustfix 0.4.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)", - "serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -429,16 +441,16 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.4 (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)", - "serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -446,39 +458,50 @@ dependencies = [ name = "core" version = "0.0.0" dependencies = [ - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "core-foundation" -version = "0.6.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "core-foundation-sys 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "core-foundation-sys" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "crates-io" -version = "0.21.0" +version = "0.22.0" dependencies = [ "curl 0.4.19 (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)", - "serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "crossbeam" -version = "0.3.2" +name = "crc" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crc32fast" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "crossbeam-channel" @@ -489,7 +512,7 @@ dependencies = [ "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.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)", + "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -507,9 +530,9 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -521,9 +544,9 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -533,7 +556,7 @@ name = "crossbeam-utils" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -543,10 +566,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "crossbeam-utils" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -556,7 +579,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "commoncrypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -567,9 +590,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "curl-sys 0.4.15 (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)", + "libc 0.2.45 (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.38 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.39 (registry+https://github.com/rust-lang/crates.io-index)", "schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -581,10 +604,10 @@ version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "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)", - "libnghttp2-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libz-sys 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.38 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libnghttp2-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.39 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -597,12 +620,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "derive-new" -version = "0.5.4" +version = "0.5.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)", + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -611,9 +634,9 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.21 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -631,16 +654,18 @@ name = "directories" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "dlmalloc" -version = "0.0.0" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "compiler_builtins 0.0.0", - "core 0.0.0", + "compiler_builtins 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-std-workspace-core 1.0.0", ] [[package]] @@ -650,24 +675,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "elasticlunr-rs" -version = "2.3.3" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.4 (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)", - "serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", - "strum 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "strum_macros 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ena" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "strum 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "strum_macros 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -675,19 +692,19 @@ name = "ena" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "env_logger" -version = "0.5.12" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -696,10 +713,10 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -712,7 +729,7 @@ name = "error-chain" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -720,7 +737,7 @@ name = "error-chain" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -732,32 +749,32 @@ dependencies = [ [[package]] name = "failure" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "failure_derive" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "filetime" -version = "0.2.1" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -767,12 +784,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "flate2" -version = "1.0.3" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "libz-sys 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz_oxide_c_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -797,12 +816,21 @@ name = "foreign-types-shared" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "fortanix-sgx-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "compiler_builtins 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-std-workspace-core 1.0.0", +] + [[package]] name = "fs2" version = "0.4.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)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -816,7 +844,7 @@ name = "fst" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -852,8 +880,8 @@ name = "fwdansi" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -867,12 +895,12 @@ version = "0.7.5" 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)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", "libgit2-sys 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (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.38 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.39 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -882,8 +910,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "curl 0.4.19 (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.5 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -893,14 +921,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "globset" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -912,14 +940,22 @@ name = "handlebars" version = "0.32.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "pest_derive 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "pest_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "heck" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -938,20 +974,20 @@ dependencies = [ [[package]] name = "html5ever" -version = "0.22.3" +version = "0.22.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "markup5ever 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "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)", + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "humantime" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -974,19 +1010,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ignore" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "globset 0.4.1 (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.5 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "same-file 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "globset 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -994,7 +1030,7 @@ name = "im-rc" version = "12.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1004,11 +1040,11 @@ version = "0.0.0" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tar 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tar 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "xz2 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1038,17 +1074,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jobserver" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1063,9 +1099,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (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)", - "serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1083,12 +1119,12 @@ version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "num-derive 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.5 (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)", - "serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num-derive 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1099,29 +1135,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lazy_static" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "lazycell" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "libc" -version = "0.0.0" -dependencies = [ - "compiler_builtins 0.0.0", - "core 0.0.0", -] +name = "lazycell" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.43" +version = "0.2.45" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc-std-workspace-core 1.0.0", +] [[package]] name = "libgit2-sys" @@ -1130,19 +1158,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "curl-sys 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (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.24 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.38 (registry+https://github.com/rust-lang/crates.io-index)", + "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.39 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libnghttp2-sys" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1151,20 +1180,20 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "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.24 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.38 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.39 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libz-sys" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "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)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1187,15 +1216,15 @@ name = "log" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "log" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1203,7 +1232,7 @@ name = "log_settings" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1212,8 +1241,8 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "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)", + "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1239,9 +1268,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "phf 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", "phf_codegen 0.7.22 (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)", - "serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_codegen 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1258,34 +1287,36 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ammonia 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "elasticlunr-rs 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", + "elasticlunr-rs 2.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "handlebars 0.32.4 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (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.5 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.11 (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)", - "serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "toml-query 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "memchr" -version = "2.0.2" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1293,7 +1324,7 @@ name = "memmap" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1312,11 +1343,30 @@ dependencies = [ [[package]] name = "miniz-sys" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "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)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "miniz_oxide" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "miniz_oxide_c_api" +version = "0.2.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)", + "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz_oxide 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1332,14 +1382,14 @@ dependencies = [ name = "miri" version = "0.1.0" dependencies = [ - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "cargo_metadata 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "compiletest_rs 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", "directories 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "vergen 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "vergen 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1357,13 +1407,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "num-derive" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1371,12 +1421,12 @@ name = "num-integer" version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-traits" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1384,7 +1434,7 @@ name = "num_cpus" version = "1.8.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)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1394,25 +1444,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "opener" -version = "0.3.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "openssl" -version = "0.10.13" +version = "0.10.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.38 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1422,7 +1472,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl-src" -version = "111.0.1+1.1.1" +version = "111.1.0+1.1.1a" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1430,12 +1480,12 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.38" +version = "0.9.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "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 111.0.1+1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-src 111.1.0+1.1.1a (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1463,16 +1513,16 @@ name = "packed_simd" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "panic_abort" version = "0.0.0" dependencies = [ - "compiler_builtins 0.0.0", + "compiler_builtins 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", - "libc 0.0.0", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1480,9 +1530,9 @@ name = "panic_unwind" version = "0.0.0" dependencies = [ "alloc 0.0.0", - "compiler_builtins 0.0.0", + "compiler_builtins 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", - "libc 0.0.0", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", "unwind 0.0.0", ] @@ -1495,25 +1545,14 @@ dependencies = [ "parking_lot_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "parking_lot_core" -version = "0.2.14" -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.4.3 (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.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "parking_lot_core" 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)", + "libc 0.2.45 (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)", + "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1529,7 +1568,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "pest_derive" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1591,7 +1630,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "datafrog 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1611,13 +1650,12 @@ dependencies = [ [[package]] name = "pretty_env_logger" -version = "0.2.5" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1645,7 +1683,7 @@ name = "profiler_builtins" version = "0.0.0" dependencies = [ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.0.0", + "compiler_builtins 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -1656,14 +1694,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bit-set 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "rusty-fork 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1709,7 +1747,7 @@ dependencies = [ [[package]] name = "quote" -version = "0.6.8" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1717,18 +1755,18 @@ dependencies = [ [[package]] name = "racer" -version = "2.1.13" +version = "2.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", - "humantime 1.1.1 (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.5 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1737,7 +1775,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1748,15 +1786,83 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rand_core" -version = "0.2.1" +name = "rand" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_chacha" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rand_hc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_pcg" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "rayon" @@ -1773,15 +1879,15 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "redox_syscall" -version = "0.1.40" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1789,7 +1895,7 @@ name = "redox_termios" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1797,23 +1903,23 @@ name = "regex" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex" -version = "1.0.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1821,15 +1927,15 @@ name = "regex-syntax" version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1852,23 +1958,23 @@ dependencies = [ name = "rls" version = "1.31.6" dependencies = [ - "cargo 0.33.0", + "cargo 0.34.0", "cargo_metadata 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "clippy_lints 0.0.212", "crossbeam-channel 0.2.6 (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)", + "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "languageserver-types 0.51.1 (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.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "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.13 (registry+https://github.com/rust-lang/crates.io-index)", + "racer 2.1.16 (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)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-analysis 0.16.10 (registry+https://github.com/rust-lang/crates.io-index)", "rls-blacklist 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rls-data 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1878,13 +1984,13 @@ dependencies = [ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0", "rustc_tools_util 0.1.0", - "rustfmt-nightly 1.0.0", - "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)", - "serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustfmt-nightly 1.0.1", + "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1892,11 +1998,11 @@ name = "rls-analysis" version = "0.16.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "fst 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", "json 0.11.13 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rls-data 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1914,8 +2020,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (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)", + "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1929,8 +2035,8 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rustc-serialize 0.3.24 (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)", + "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1938,7 +2044,7 @@ name = "rls-vfs" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1955,16 +2061,16 @@ name = "rustc" version = "0.0.0" dependencies = [ "arena 0.0.0", - "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "chalk-engine 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "fmt_macros 0.0.0", "graphviz 0.0.0", - "jobserver 0.1.11 (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.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jobserver 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "polonius-engine 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1976,130 +2082,133 @@ dependencies = [ "rustc_target 0.0.0", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", - "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", "syntax_pos 0.0.0", - "tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-arena" -version = "297.0.0" +version = "306.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-graphviz" -version = "297.0.0" +version = "306.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-rustc_cratesio_shim" -version = "297.0.0" +version = "306.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)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_data_structures" -version = "297.0.0" +version = "306.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "ena 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-graphviz 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-graphviz 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_errors" -version = "297.0.0" +version = "306.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_target" -version = "297.0.0" +version = "306.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)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "297.0.0" +version = "306.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax" -version = "297.0.0" +version = "306.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)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "297.0.0" +version = "306.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-arena 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-arena 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-demangle" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "compiler_builtins 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-std-workspace-core 1.0.0", +] [[package]] name = "rustc-hash" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2126,8 +2235,8 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2137,13 +2246,22 @@ name = "rustc-serialize" version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rustc-std-workspace-core" +version = "1.0.0" +dependencies = [ + "core 0.0.0", +] + [[package]] name = "rustc-workspace-hack" version = "1.0.0" dependencies = [ + "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2151,12 +2269,12 @@ dependencies = [ name = "rustc_allocator" version = "0.0.0" dependencies = [ - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", "rustc_target 0.0.0", - "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", "syntax_pos 0.0.0", ] @@ -2167,7 +2285,7 @@ version = "0.0.0" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_cratesio_shim 0.0.0", - "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2177,7 +2295,7 @@ dependencies = [ "alloc 0.0.0", "build_helper 0.1.0", "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.0.0", + "compiler_builtins 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -2186,7 +2304,7 @@ name = "rustc_borrowck" version = "0.0.0" dependencies = [ "graphviz 0.0.0", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", @@ -2202,7 +2320,7 @@ dependencies = [ "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)", + "rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_llvm 0.0.0", ] @@ -2212,13 +2330,13 @@ version = "0.0.0" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jobserver 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (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 0.0.0", - "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_allocator 0.0.0", "rustc_apfloat 0.0.0", "rustc_codegen_utils 0.0.0", @@ -2237,8 +2355,8 @@ dependencies = [ name = "rustc_codegen_utils" version = "0.0.0" dependencies = [ - "flate2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_data_structures 0.0.0", "rustc_incremental 0.0.0", @@ -2254,7 +2372,7 @@ name = "rustc_cratesio_shim" version = "0.0.0" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2262,17 +2380,17 @@ dependencies = [ name = "rustc_data_structures" version = "0.0.0" dependencies = [ - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "graphviz 0.0.0", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_cratesio_shim 0.0.0", "serialize 0.0.0", - "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2281,10 +2399,10 @@ name = "rustc_driver" version = "0.0.0" dependencies = [ "arena 0.0.0", - "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", "graphviz 0.0.0", "jemalloc-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_allocator 0.0.0", @@ -2306,7 +2424,7 @@ dependencies = [ "rustc_typeck 0.0.0", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", - "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", "syntax_ext 0.0.0", "syntax_pos 0.0.0", @@ -2317,12 +2435,12 @@ name = "rustc_errors" version = "0.0.0" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (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", "syntax_pos 0.0.0", - "termcolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2335,7 +2453,7 @@ name = "rustc_incremental" version = "0.0.0" dependencies = [ "graphviz 0.0.0", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (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", @@ -2349,10 +2467,9 @@ dependencies = [ name = "rustc_lint" version = "0.0.0" dependencies = [ - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_data_structures 0.0.0", - "rustc_mir 0.0.0", "rustc_target 0.0.0", "syntax 0.0.0", "syntax_pos 0.0.0", @@ -2373,7 +2490,7 @@ dependencies = [ "alloc 0.0.0", "build_helper 0.1.0", "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.0.0", + "compiler_builtins 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -2381,8 +2498,8 @@ dependencies = [ name = "rustc_metadata" version = "0.0.0" dependencies = [ - "flate2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_data_structures 0.0.0", @@ -2401,10 +2518,10 @@ version = "0.0.0" dependencies = [ "arena 0.0.0", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "graphviz 0.0.0", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "log_settings 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "polonius-engine 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", @@ -2413,7 +2530,7 @@ dependencies = [ "rustc_errors 0.0.0", "rustc_target 0.0.0", "serialize 0.0.0", - "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", "syntax_pos 0.0.0", ] @@ -2425,7 +2542,7 @@ dependencies = [ "alloc 0.0.0", "build_helper 0.1.0", "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.0.0", + "compiler_builtins 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -2433,7 +2550,7 @@ dependencies = [ name = "rustc_passes" version = "0.0.0" dependencies = [ - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", @@ -2474,7 +2591,7 @@ version = "0.0.0" dependencies = [ "arena 0.0.0", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", @@ -2487,7 +2604,7 @@ dependencies = [ name = "rustc_save_analysis" version = "0.0.0" dependencies = [ - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rls-data 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", @@ -2505,7 +2622,7 @@ name = "rustc_target" version = "0.0.0" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (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", @@ -2522,11 +2639,11 @@ dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "chalk-engine 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "graphviz 0.0.0", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_data_structures 0.0.0", "rustc_target 0.0.0", - "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", "syntax_pos 0.0.0", ] @@ -2538,7 +2655,7 @@ dependencies = [ "alloc 0.0.0", "build_helper 0.1.0", "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.0.0", + "compiler_builtins 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -2547,20 +2664,20 @@ name = "rustc_typeck" version = "0.0.0" dependencies = [ "arena 0.0.0", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", "rustc_platform_intrinsics 0.0.0", "rustc_target 0.0.0", - "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", "syntax_pos 0.0.0", ] [[package]] name = "rustc_version" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2573,7 +2690,7 @@ dependencies = [ "minifier 0.0.20 (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)", + "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2592,39 +2709,39 @@ name = "rustfix" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (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)", - "serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustfmt-nightly" -version = "1.0.0" +version = "1.0.1" dependencies = [ "assert_cli 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "cargo_metadata 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "diff 0.1.11 (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)", + "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (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.5 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0", - "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)", - "serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2635,18 +2752,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "wait-timeout 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ryu" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "same-file" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2657,7 +2774,7 @@ name = "schannel" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2677,7 +2794,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2687,17 +2804,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.75" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.75" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2705,24 +2822,24 @@ name = "serde_ignored" version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.31" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serialize" version = "0.0.0" dependencies = [ - "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2742,7 +2859,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "smallvec" -version = "0.6.5" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2753,9 +2870,9 @@ name = "socket2" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2771,14 +2888,16 @@ dependencies = [ "alloc 0.0.0", "build_helper 0.1.0", "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.0.0", + "compiler_builtins 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", - "dlmalloc 0.0.0", - "libc 0.0.0", + "dlmalloc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fortanix-sgx-abi 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", "panic_abort 0.0.0", "panic_unwind 0.0.0", "profiler_builtins 0.0.0", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_asan 0.0.0", "rustc_lsan 0.0.0", "rustc_msan 0.0.0", @@ -2791,11 +2910,11 @@ name = "string_cache" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_codegen 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2824,17 +2943,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "strum" -version = "0.9.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "strum_macros" -version = "0.9.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2849,31 +2969,11 @@ dependencies = [ [[package]] name = "syn" -version = "0.13.11" -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)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "syn" -version = "0.14.9" +version = "0.15.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "syn" -version = "0.15.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2887,12 +2987,12 @@ dependencies = [ [[package]] name = "synstructure" -version = "0.9.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2901,13 +3001,13 @@ name = "syntax" version = "0.0.0" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", "rustc_target 0.0.0", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", - "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "syntax_pos 0.0.0", ] @@ -2916,11 +3016,11 @@ name = "syntax_ext" version = "0.0.0" dependencies = [ "fmt_macros 0.0.0", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", "rustc_target 0.0.0", - "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", "syntax_pos 0.0.0", ] @@ -2930,7 +3030,7 @@ name = "syntax_pos" version = "0.0.0" dependencies = [ "arena 0.0.0", - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_data_structures 0.0.0", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", @@ -2939,23 +3039,24 @@ dependencies = [ [[package]] name = "tar" -version = "0.4.19" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "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)", - "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", "xattr 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tempfile" -version = "3.0.3" +version = "3.0.5" 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.5 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.43 (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.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2979,13 +3080,13 @@ name = "term" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "termcolor" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2996,8 +3097,8 @@ name = "termion" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3023,16 +3124,16 @@ name = "thread_local" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tidy" version = "0.1.0" dependencies = [ - "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)", - "serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3040,17 +3141,17 @@ name = "time" version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "toml" -version = "0.4.6" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3060,9 +3161,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "is-match 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3072,7 +3173,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ucd-util" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -3120,7 +3221,7 @@ dependencies = [ name = "unstable-book-gen" version = "0.1.0" dependencies = [ - "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "tidy 0.1.0", ] @@ -3128,14 +3229,14 @@ dependencies = [ name = "unwind" version = "0.0.0" dependencies = [ - "compiler_builtins 0.0.0", + "compiler_builtins 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", - "libc 0.0.0", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "url" -version = "1.7.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3148,8 +3249,8 @@ name = "url_serde" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3159,7 +3260,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "utf8-ranges" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -3174,12 +3275,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "vergen" -version = "3.0.3" +version = "3.0.4" 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)", - "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3197,15 +3298,15 @@ name = "wait-timeout" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "walkdir" -version = "2.2.5" +version = "2.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "same-file 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3261,7 +3362,7 @@ name = "xattr" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3278,71 +3379,76 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] -"checksum aho-corasick 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "7ee94e9463ccb9d681e7b708082687b2c56d2bd420ca8a3d3157d27d59508ec0" +"checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" +"checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" "checksum ammonia 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fd4c682378117e4186a492b2252b9537990e1617f44aed9788b9a1149de45477" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" "checksum assert_cli 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98589b0e465a6c510d95fceebd365bb79bedece7f6e18a480897f2015f85ec51" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" -"checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a" +"checksum backtrace 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "18b65ea1161bfb2dd6da6fade5edd4dbd08fba85012123dd333d2fd1b90b2782" "checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0" "checksum bit-set 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6f1efcc46c18245a69c38fcc5cc650f16d3a59d034f3106e9ed63748f695730a" "checksum bit-vec 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4440d5cb623bb7390ae27fec0bb6c61111969860f8e3ae198bfa0663645e67cf" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "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 bufstream 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8" +"checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" "checksum bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b92204551573580e078dc80017f36a213eb77a0450e4ddd8cfa0f3f2d1f0178f" -"checksum byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "74c0b906e9446b0a2e4f760cdb3fa4b2c48cdc6db8766a845c54b6ff063fd2e9" +"checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" "checksum bytesize 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "716960a18f978640f25101b5cbf1c6f6b0d3192fab36a2d98ca96f0ecbe41010" "checksum cargo_metadata 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d8dfe3adeb30f7938e6c1dd5327f29235d8ada3e898aeb08c343005ec2915a2" "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 cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" "checksum chalk-engine 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6749eb72e7d4355d944a99f15fbaea701b978c18c5e184a025fcde942b0c9779" "checksum chalk-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "295635afd6853aa9f20baeb7f0204862440c0fe994c5a253d5f479dac41d047e" -"checksum chrono 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6962c635d530328acc53ac6a955e83093fedc91c5809dfac1fa60fa470830a37" +"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "704fbf3bb5149daab0afb255dbea24a1f08d2f4099cedb9baab6d470d4c5eefb" "checksum colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0aa3473e85a3161b59845d6096b289bb577874cafeaf75ea1b1beaa6572c7fc" "checksum commoncrypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d056a8586ba25a1e4d61cb090900e495952c7886786fc55f909ab2f819b69007" "checksum commoncrypto-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fed34f46747aa73dfaa578069fd8279d2818ade2b55f38f22a9401c7f4083e2" +"checksum compiler_builtins 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8ad611263b9f31bdb66e66227d3b781600fd1e68d5deee29b23f5e2ac9cb4892" "checksum compiletest_rs 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "89747fe073b7838343bd2c2445e7a7c2e0d415598f8925f0fa9205b9cdfc48cb" -"checksum core-foundation 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cc3532ec724375c7cb7ff0a097b714fde180bb1f6ed2ab27cfcd99ffca873cd2" -"checksum core-foundation-sys 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a3fb15cdbdd9cf8b82d97d0296bb5cd3631bba58d6e31650a002a8e7fb5721f9" -"checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19" +"checksum core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4e2640d6d0bf22e82bed1b73c6aef8d5dd31e5abe6666c57e6d45e2649f4f887" +"checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" +"checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" +"checksum crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e91d5240c6975ef33aeb5f148f35275c25eda8e8a5f95abe421978b05b8bf192" "checksum crossbeam-channel 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7b85741761b7f160bc5e7e0c14986ef685b7f8bf9b7ad081c60c604bb4649827" "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" "checksum crossbeam-epoch 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c90f1474584f38e270b5b613e898c8c328aa4f3dea85e0a27ac2e642f009416" "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" "checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015" -"checksum crossbeam-utils 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c55913cc2799171a550e307918c0a360e8c16004820291bf3b638969b4a01816" +"checksum crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e07fc155212827475223f0bcfae57e945e694fc90950ddf3f6695bbfd5555c72" "checksum crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "09de9ee0fc255ace04c7fa0763c9395a945c37c8292bb554f8d48361d1dcf1b4" "checksum curl 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)" = "c7c9d851c825e0c033979d4516c9173bc19a78a96eb4d6ae51d4045440eafa16" "checksum curl-sys 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)" = "721c204978be2143fab0a84b708c49d79d1f6100b8785610f456043a90708870" "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-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6ca414e896ae072546f4d789f452daaecf60ddee4c9df5dc6d5936d769e3d87c" "checksum derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f57d78cf3bd45270dad4e70c21ec77a960b36c7a841ff9db76aaa775a8fb871" "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" "checksum directories 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72d337a64190607d4fcca2cb78982c5dd57f4916e19696b48a575fa746b6cb0f" +"checksum dlmalloc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c46c65de42b063004b31c67a98abe071089b289ff0919c660ed7ff4f59317f8" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" -"checksum elasticlunr-rs 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4837d77a1e157489a3933b743fd774ae75074e0e390b2b7f071530048a0d87ee" +"checksum elasticlunr-rs 2.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a99a310cd1f9770e7bf8e48810c7bcbb0e078c8fb23a8c7bcf0da4c2bf61a455" "checksum ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f56c93cc076508c549d9bb747f79aa9b4eb098be7b8cad8830c3137ef52d1e00" -"checksum ena 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "88dc8393b3c7352f94092497f6b52019643e493b6b890eb417cdb7c46117e621" -"checksum env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)" = "f4d7e69c283751083d53d01eac767407343b8b69c4bd70058e08adc2637cb257" +"checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" "checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" "checksum environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f4b14e20978669064c33b4c1e0fb4083412e40fe56cbea2eae80fd7591503ee" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" -"checksum failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7efb22686e4a466b1ec1a15c2898f91fa9cb340452496dca654032de20ff95b9" -"checksum failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "946d0e98a50d9831f5d589038d2ca7f8f455b1c21028c0db0e84116a12696426" -"checksum filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "da4b9849e77b13195302c174324b5ba73eec9b236b24c221a61000daefb95c5f" +"checksum failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6dd377bcc1b1b7ce911967e3ec24fa19c3224394ec05b54aa7b083d498341ac7" +"checksum failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "64c2d913fe8ed3b6c6518eedf4538255b989945c14c2a7d5cbff62a5e2120596" +"checksum filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a2df5c1a8c4be27e7707789dc42ae65976e60b394afd293d1419ab915833e646" "checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" -"checksum flate2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4af030962d89d62aa52cd9492083b1cd9b2d1a77764878102a6c0f86b4d5444d" +"checksum flate2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2291c165c8e703ee54ef3055ad6188e3d51108e2ded18e9f2476e774fc5ad3d4" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +"checksum fortanix-sgx-abi 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "26105e20b4c3f7a319db1376b54ac9a46e5761e949405553375095d05a0cee4d" "checksum fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" "checksum fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f2a4a2034423744d2cc7ca2068453168dcdb82c438419e639a26bd87839c674" "checksum fst 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d94485a00b1827b861dd9d1a2cc9764f9044d4c535514c0760a5a2012ef3399f" @@ -3355,36 +3461,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum git2 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "591f8be1674b421644b6c030969520bc3fa12114d2eb467471982ed3e9584e71" "checksum git2-curl 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0173e317f8ba21f3fff0f71549fead5e42e67961dbd402bf69f42775f3cc78b4" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" -"checksum globset 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8e49edbcc9c7fc5beb8c0a54e7319ff8bed353a2b55e85811c6281188c2a6c84" +"checksum globset 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4743617a7464bbda3c8aec8558ff2f9429047e025771037df561d383337ff865" "checksum handlebars 0.32.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d89ec99d1594f285d4590fc32bac5f75cdab383f1123d504d27862c644a807dd" +"checksum heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea04fa3ead4e05e51a7c806fc07271fdbde4e246a6c6d1efd52e72230b771b82" "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" "checksum home 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "80dff82fb58cfbbc617fb9a9184b010be0529201553cda50ad04372bc2333aff" -"checksum html5ever 0.22.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b04478cf718862650a0bf66acaf8f2f8c906fbc703f35c916c1f4211b069a364" -"checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e" +"checksum html5ever 0.22.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c213fa6a618dc1da552f54f85cba74b05d8e883c92ec4e89067736938084c26e" +"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum if_chain 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4bac95d9aa0624e7b78187d6fb8ab012b41d9f6f54b1bcb61e61c4845f8357ec" -"checksum ignore 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3e9faa7c84064f07b40da27044af629f578bc7994b650d3e458d0c29183c1d91" +"checksum ignore 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "36ecfc5ad80f0b1226df948c562e2cddd446096be3f644c95106400eae8a5e01" "checksum im-rc 12.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4591152fd573cf453a890b5f9fdc5c328a751a0785539316739d5f85e5c468c" "checksum is-match 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7e5b386aef33a1c677be65237cb9d32c3f3ef56bd035949710c4bb13083eb053" "checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum jemalloc-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "bfc62c8e50e381768ce8ee0428ee53741929f7ebd73e4d83f669bcf7693e00ae" -"checksum jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "60af5f849e1981434e4a31d3d782c4774ae9b434ce55b101a96ecfd09147e8be" +"checksum jobserver 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "dd80e58f77e0cdea53ba96acc5e04479e5ffc5d869626a6beafe50fed867eace" "checksum json 0.11.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9ad0485404155f45cce53a40d4b2d6ac356418300daed05273d9e26f91c390be" "checksum jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ddf83704f4e79979a424d1082dd2c1e52683058056c9280efa19ac5f6bc9033c" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum languageserver-types 0.51.1 (registry+https://github.com/rust-lang/crates.io-index)" = "68de833188ada4e175d04a028f03f244f6370eedbcc75a05604d47d925933f69" "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" -"checksum lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7" -"checksum lazycell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddba4c30a78328befecec92fc94970e53b3ae385827d28620f0f5bb2493081e0" -"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" +"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" +"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" +"checksum libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)" = "2d2857ec59fadc0773853c664d2d18e7198e83883e7060b63c924cb077bd5c74" "checksum libgit2-sys 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4916b5addc78ec36cc309acfcdf0b9f9d97ab7b84083118b248709c5b7029356" -"checksum libnghttp2-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ffbfb81475cc9f625e44f3a8f8b9cf7173815ae1c7cc2fa91853ec009e38198" +"checksum libnghttp2-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d75d7966bda4730b722d1eab8e668df445368a24394bae9fc1e8dc0ab3dbe4f4" "checksum libssh2-sys 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "126a1f4078368b163bfdee65fbab072af08a1b374a5551b21e87ade27b1fbf9d" -"checksum libz-sys 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)" = "4401fe74560a0d46fce3464625ac8aa7a79d291dd28cee021d18852d5191c280" +"checksum libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe" "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.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fcce5fa49cc693c312001daf1d13411c4a5283796bac1084299ea3e567113f" +"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum log_settings 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19af41f0565d7c19b2058153ad0b42d4d5ce89ec4dbf06ed6741114a8b63e7cd" "checksum lzma-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d1eaa027402541975218bb0eec67d6b0412f6233af96e0d096d31dbdfd22e614" "checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" @@ -3393,34 +3500,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum markup5ever 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfedc97d5a503e96816d10fedcd5b42f760b2e525ce2f7ec71f6a41780548475" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum mdbook 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "90b5a8d7e341ceee5db3882a06078d42661ddcfa2b3687319cc5da76ec4e782f" -"checksum memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a3b4142ab8738a78c51896f704f83c11df047ff1bda9a92a661aa6361552d93d" +"checksum memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0a3eb002f0535929f1199681417029ebea04aadc0c7a4224b46be99c7f5d6a16" "checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum minifier 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "96c269bb45c39b333392b2b18ad71760b34ac65666591386b0e959ed58b3f474" -"checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4" +"checksum miniz-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0300eafb20369952951699b68243ab4334f4b10a88f411c221d444b36c40e649" +"checksum miniz_oxide 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ad30a47319c16cde58d0314f5d98202a80c9083b5f61178457403dfb14e509c" +"checksum miniz_oxide_c_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "28edaef377517fd9fe3e085c37d892ce7acd1fbeab9239c5a36eec352d8a8b7e" "checksum miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "396aa0f2003d7df8395cb93e09871561ccc3e785f0acb369170e8cc74ddf9226" "checksum new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0cdc457076c78ab54d5e0d6fa7c47981757f1e34dc39ff92787f217dede586c4" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" -"checksum num-derive 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d2c31b75c36a993d30c7a13d70513cb93f02acafdd5b7ba250f9b0e18615de7" +"checksum num-derive 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8af1847c907c2f04d7bfd572fb25bbb4385c637fe5be163cf2f8c5d778fe1e7d" "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" -"checksum num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "630de1ef5cc79d0cdd78b7e33b81f083cbfe90de0f4b2b2f07f905867c70e9fe" +"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" "checksum open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c281318d992e4432cfa799969467003d05921582a7489a8325e37f8a450d5113" -"checksum opener 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "176cd8eadff5ef9fa5c6d19452535662c02c6bf29b3d594a3fc01f749bb24c94" -"checksum openssl 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)" = "5af9e83eb3c51ee806387d26a43056f3246d865844caa6dd704d2ba7e831c264" +"checksum opener 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "04b1d6b086d9b3009550f9b6f81b10ad9428cf14f404b8e1a3a06f6f012c8ec9" +"checksum openssl 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)" = "5e1309181cdcbdb51bc3b6bedb33dfac2a83b3d585033d3f6d9e22e8c1928613" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-src 111.0.1+1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d1edaed888fd85a54a2646bf02992931ddefdda3b1a748fc79f088a8db27fcbe" -"checksum openssl-sys 0.9.38 (registry+https://github.com/rust-lang/crates.io-index)" = "ff3d1b390ab1b9700f682ad95a30dc9c0f40dd212ca57266012cfc678b0e365a" +"checksum openssl-src 111.1.0+1.1.1a (registry+https://github.com/rust-lang/crates.io-index)" = "26bb632127731bf4ac49bf86a5dde12d2ca0918c2234fc39d79d4da2ccbc6da7" +"checksum openssl-sys 0.9.39 (registry+https://github.com/rust-lang/crates.io-index)" = "278c1ad40a89aa1e741a1eed089a2f60b18fab8089c3139b542140fc7d674106" "checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063" "checksum ordslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dd20eec3dbe4376829cb7d80ae6ac45e0a766831dca50202ff2d40db46a8a024" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" "checksum packed_simd 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "25d36de864f7218ec5633572a800109bbe5a1cc8d9d95a967f3daf93ea7e6ddc" "checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5" -"checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa" "checksum parking_lot_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "06a2b6aae052309c2fd2161ef58f5067bc17bb758377a0de9d4b279d603fdd8a" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0fce5d8b5cc33983fc74f78ad552b5522ab41442c4ca91606e4236eb4b5ceefc" -"checksum pest_derive 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ab94faafeb93f4c5e3ce81ca0e5a779529a602ad5d09ae6d21996bfb8b6a52bf" +"checksum pest_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3294f437119209b084c797604295f40227cffa35c57220b1e99a6ff3bf8ee4" "checksum petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f" "checksum phf 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "7d37a244c75a9748e049225155f56dbcb98fe71b192fd25fd23cb914b5ad62f2" "checksum phf_codegen 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "4e4048fe7dd7a06b8127ecd6d3803149126e9b33c7558879846da3a63f734f2b" @@ -3430,7 +3538,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum polonius-engine 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b6b0a7f5f4278b991ffd14abce1d01b013121ad297460237ef0a2f08d43201" "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" "checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6" -"checksum pretty_env_logger 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ed8d1e63042e889b85228620629b51c011d380eed2c7e0015f8a644def280c28" +"checksum pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df8b3f4e0475def7d9c2e5de8e5a1306949849761e107b360d03e98eafaffd61" "checksum proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1b06e2f335f48d24442b35a19df506a835fb3547bc3c06ef27340da9acf5cae7" "checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09" "checksum proptest 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "926d0604475349f463fe44130aae73f2294b5309ab2ca0310b998bd334ef191f" @@ -3440,19 +3548,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" -"checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5" -"checksum racer 2.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "344a53b68d889ab5f44d0617f2bbe1f696abe6a730bd41fa619cfc6fa83a6078" +"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c" +"checksum racer 2.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "fbfcf2686b50f75a279cb42d9c6d253a1e68a475b415ea4baf7fb177ce94839a" "checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" "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 rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae9d223d52ae411a33cf7e54ec6034ec165df296ccd23533d671a28252b6f66a" +"checksum rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "771b009e3a508cb67e8823dda454aaa5368c7bc1c16829fb77d3e980440dd34a" +"checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" +"checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" +"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +"checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" +"checksum rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effa3fcaa47e18db002bdde6060944b6d2f9cfd8db471c30e873448ad9187be3" "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" -"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" +"checksum redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "679da7508e9a6390aeaf7fbd02a800fdc64b73fe2204dd2c8ae66d22d9d5ad5d" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384" -"checksum regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "67d0301b0c6804eca7e3c275119d0b01ff3b7ab9258a65709e608a66312a1025" +"checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f" "checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" -"checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d" +"checksum regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4e47a2ed29da7a9e1960e1639e7a982e6edc6d49be308a3b02daf511504a16d1" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" "checksum rls-analysis 0.16.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2de1187cceaf16d7642cc78835a2890b55b35ed9e8a8e3c6348a6297d8dd0fb1" "checksum rls-blacklist 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ce1fdac03e138c4617ff87b194e1ff57a39bb985a044ccbd8673d30701e411" @@ -3460,65 +3575,63 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rls-rustc 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9dba7390427aefa953608429701e3665192ca810ba8ae09301e001b7c7bed0" "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a" "checksum rls-vfs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "72d56425bd5aa86d9d4372b76f0381d3b4bda9c0220e71956c9fcc929f45c1f1" -"checksum rustc-ap-arena 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b69fd4a0e8a3ecd99b497965d05f6f04dd2e4601a6146a841dbe4c8e77c2b30c" -"checksum rustc-ap-graphviz 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8136418dbc491bab74aa0565eaa2086754a7a81a5e74a1d84d6168d18e889e7" -"checksum rustc-ap-rustc_cratesio_shim 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a972feda82332d1d05b1ba5a097e915cd9c9c8f1af2bd7b08af09fb88c753d5f" -"checksum rustc-ap-rustc_data_structures 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "582584c6c48b0ece4b8aef3f9bb59d94d17c5665612bc87a71f509e45a3113b5" -"checksum rustc-ap-rustc_errors 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cd852096944d0ac6af1aefa9639a2ae6dede217606ce97f88ff0dcc8c86d6ff6" -"checksum rustc-ap-rustc_target 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98301a272ecfeec29d2d4e97b07238707c2b89d86fc3a4a5f31a00728f14e288" -"checksum rustc-ap-serialize 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f13510e617e2e322e3297038fd6a7346f2297124af9e10e33a627c5d544e9d" -"checksum rustc-ap-syntax 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0792f5a9ccfc5ec13bb5b0472fa49e145481029c39f6bf5b1a36decc99c3328f" -"checksum rustc-ap-syntax_pos 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0df9f97f41650d23b14f92f7267f8c61089655efb4533d82bf8991f99245198d" -"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" +"checksum rustc-ap-arena 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cbfb540c1347a3993060896b18e0d64084203fa37aaffdc5e5c31264f275d476" +"checksum rustc-ap-graphviz 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "790ac657d5bf69be9ef56f6810e8a0238b07e8460a88526e11d41f8214eb6c4e" +"checksum rustc-ap-rustc_cratesio_shim 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b721cf32b543f3ee90240d7b757ca4a45930fe9981458a50678b4ccd75c472e2" +"checksum rustc-ap-rustc_data_structures 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4fa11df199d45ce948b07792ca593f59c1d19d2cb05d35c6b0a02271e772a416" +"checksum rustc-ap-rustc_errors 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b7ead3163ef995bbba520b88739e1d60f9ccf74fdacdda985067644c8134e827" +"checksum rustc-ap-rustc_target 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "688fef9cc27837755019b72b4f13e7a3d3e5012473475f377b75dbb1f07beb5f" +"checksum rustc-ap-serialize 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b2c0e8161e956647592a737074736e6ce05ea36b70c770ea8cca3eb9cb33737" +"checksum rustc-ap-syntax 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1adc189e5e4500a4167b9afa04e67067f40d0039e0e05870c977bebb561f065a" +"checksum rustc-ap-syntax_pos 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4d42c430dbb0be4377bfe6aa5099074c63ac8796b24098562c2e2154aecc5652" +"checksum rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "82ae957aa1b3055d8e086486723c0ccd3d7b8fa190ae8fa2e35543b6171c810e" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c6d5a683c6ba4ed37959097e88d71c9e8e26659a3cb5be8b389078e7ad45306" "checksum rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40f06724db71e18d68b3b946fdf890ca8c921d9edccc1404fdfdb537b0d12649" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" -"checksum rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a54aa04a10c68c1c4eacb4337fd883b435997ede17a9385784b990777686b09a" +"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum rustfix 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "756567f00f7d89c9f89a5c401b8b1caaa122e27240b9eaadd0bb52ee0b680b1b" "checksum rusty-fork 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9591f190d2852720b679c21f66ad929f9f1d7bb09d1193c26167586029d8489c" -"checksum ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7153dd96dade874ab973e098cb62fcdbb89a03682e46b144fd09550998d4a4a7" -"checksum same-file 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "10f7794e2fda7f594866840e95f5c5962e886e228e68b6505885811a94dd728c" +"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" +"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" "checksum schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "0e1a231dc10abf6749cfa5d7767f25888d484201accbd919b66ab5413c502d56" "checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)" = "22d340507cea0b7e6632900a176101fea959c7065d93ba555072da90aaaafc87" -"checksum serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)" = "234fc8b737737b148ccd625175fc6390f5e4dacfdaa543cb93a3430d984a9119" +"checksum serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)" = "c91eb5b0190ae87b4e2e39cbba6e3bed3ac6186935fe265f0426156c4c49961b" +"checksum serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)" = "477b13b646f5b5b56fc95bedfc3b550d12141ce84f466f6c44b9a17589923885" "checksum serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "190e9765dcedb56be63b6e0993a006c7e3b071a016a304736e4a315dc01fb142" -"checksum serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)" = "bb47a3d5c84320222f66d7db21157c4a7407755de41798f9b4c1c40593397b1a" +"checksum serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "c37ccd6be3ed1fdf419ee848f7c758eb31b054d7cd3ae3600e3bae0adf569811" "checksum shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "170a13e64f2a51b77a45702ba77287f5c6829375b04a69cf2222acd17d0cfab9" "checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" -"checksum smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "153ffa32fd170e9944f7e0838edf824a754ec4c1fc64746fcc9fe1f8fa602e5d" +"checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db" "checksum socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d11a52082057d87cb5caa31ad812f4504b97ab44732cd8359df2e9ff9f48e7" "checksum stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffbc596e092fe5f598b12ef46cc03754085ac2f4d8c739ad61c4ae266cc3b3fa" "checksum string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423" "checksum string_cache_codegen 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "35293b05cf1494e8ddd042a7df6756bf18d07f42d234f32e71dce8a7aabb0191" "checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" -"checksum strum 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "099e21b5dd6dd07b5adcf8c4b723a7c0b7efd7a9359bf963d58c0caae8532545" -"checksum strum_macros 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1292d85e688e4696ecb69b2db2648994fb8af266974e89be53cefdf003861a5d" +"checksum strum 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c3a2071519ab6a48f465808c4c1ffdd00dfc8e93111d02b4fc5abab177676e" +"checksum strum_macros 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8baacebd7b7c9b864d83a6ba7a246232983e277b86fa5cdec77f565715a4b136" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" -"checksum syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)" = "14f9bf6292f3a61d2c716723fdb789a41bbe104168e6f496dc6497e531ea1b9b" -"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" -"checksum syn 0.15.21 (registry+https://github.com/rust-lang/crates.io-index)" = "816b7af21405b011a23554ea2dc3f6576dc86ca557047c34098c1d741f10f823" +"checksum syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)" = "ae8b29eb5210bc5cf63ed6149cbf9adfc82ac0be023d8735c176ee74a2db4da7" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" -"checksum synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85bb9b7550d063ea184027c9b8c20ac167cd36d3e06b3a40bceb9d746dc1a7b7" -"checksum tar 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)" = "69e16840a1e0a1f1a880b739ef1cc6a4b85496c99b8aa786ccffce6e0c15624c" -"checksum tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c4b103c6d08d323b92ff42c8ce62abcd83ca8efa7fd5bf7927efefec75f58c76" +"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" +"checksum tar 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)" = "a303ba60a099fcd2aaa646b14d2724591a96a75283e4b7ed3d1a1658909d9ae2" +"checksum tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7e91405c14320e5c79b3d148e1c86f40749a36e490642202a31689cb1a3452b2" "checksum tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9de21546595a0873061940d994bbbc5c35f024ae4fd61ec5c5b159115684f508" "checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561" -"checksum termcolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3390f44f1f706d8870297b6a2c4f92d9ab65a37c265fbbc6ac4ee72bcc2f3698" +"checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" -"checksum toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a0263c6c02c4db6c8f7681f9fd35e90de799ebd4cfdeab77a38f4ff6b3d8c0d9" +"checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" "checksum toml-query 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6854664bfc6df0360c695480836ee90e2d0c965f06db291d10be9344792d43e8" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" -"checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" +"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25" "checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" @@ -3526,17 +3639,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" -"checksum url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2a321979c09843d272956e73700d12c4e7d3d92b2ee112b31548aef0d4efc5a6" +"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" "checksum url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e7d099f1ee52f823d4bdd60c93c3602043c728f5db3b97bdb548467f7bddea" "checksum utf-8 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1262dfab4c30d5cb7c07026be00ee343a6cf5027fdc0104a9160f354e5db75c" -"checksum utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd70f467df6810094968e2fce0ee1bd0e87157aceb026a8c083bcf5e25b9efe4" +"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" "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 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1b9696d96ec5d68984d060af80d7ba0ed4eb533978a0efb05ed4b8465f20d04f" +"checksum vergen 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6aba5e34f93dc7051dfad05b98a18e9156f27e7b431fe1d2398cb6061c0a1dba" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum wait-timeout 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b9f3bf741a801531993db6478b95682117471f76916f5e690dd8d45395b09349" -"checksum walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "af464bc7be7b785c7ac72e266a6b67c4c9070155606f51655a650a6686204e35" +"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/Cargo.toml b/Cargo.toml index b763caa97d7..667c55791bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -65,6 +65,10 @@ rustfmt-nightly = { path = "src/tools/rustfmt" } # here rustc-workspace-hack = { path = 'src/tools/rustc-workspace-hack' } +# See comments in `tools/rustc-std-workspace-core/README.md` for what's going on +# here +rustc-std-workspace-core = { path = 'src/tools/rustc-std-workspace-core' } + [patch."https://github.com/rust-lang/rust-clippy"] clippy_lints = { path = "src/tools/clippy/clippy_lints" } rustc_tools_util = { path = "src/tools/clippy/rustc_tools_util" } diff --git a/README.md b/README.md index 37442661bcb..dc013a1ad2b 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ standard library, and documentation. Read ["Installation"] from [The Book]. -["Installation"]: https://doc.rust-lang.org/book/second-edition/ch01-01-installation.html +["Installation"]: https://doc.rust-lang.org/book/ch01-01-installation.html [The Book]: https://doc.rust-lang.org/book/index.html ## Building from Source diff --git a/RELEASES.md b/RELEASES.md index da09af3edfe..7022a86a45c 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,14 @@ +Version 1.31.1 (2018-12-20) +=========================== + +- [Fix Rust failing to build on `powerpc-unknown-netbsd`][56562] +- [Fix broken go-to-definition in RLS][rls/1171] +- [Fix infinite loop on hover in RLS][rls/1170] + +[56562]: https://github.com/rust-lang/rust/pull/56562 +[rls/1171]: https://github.com/rust-lang/rls/issues/1171 +[rls/1170]: https://github.com/rust-lang/rls/pull/1170 + Version 1.31.0 (2018-12-06) ========================== diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 3e91c2b3e86..0f7b6c22e1c 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -2,6 +2,7 @@ authors = ["The Rust Project Developers"] name = "bootstrap" version = "0.0.0" +edition = "2018" [lib] name = "bootstrap" diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index d143dffb24b..09c87fdd1a8 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -678,10 +678,10 @@ class RustBuild(object): print("Updating submodule", module) - run(["git", "submodule", "-q", "sync", module], + run(["git", "submodule", "-q", "sync", "--progress", module], cwd=self.rust_root, verbose=self.verbose) run(["git", "submodule", "update", - "--init", "--recursive", module], + "--init", "--recursive", "--progress", module], cwd=self.rust_root, verbose=self.verbose) run(["git", "reset", "-q", "--hard"], cwd=module_path, verbose=self.verbose) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 98005f93961..405fc871eef 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -21,20 +21,20 @@ use std::path::{Path, PathBuf}; use std::process::Command; use std::time::{Duration, Instant}; -use cache::{Cache, Interned, INTERNER}; -use check; -use compile; -use dist; -use doc; -use flags::Subcommand; -use install; -use native; -use test; -use tool; -use util::{add_lib_path, exe, libdir}; -use {Build, DocTests, Mode, GitRepo}; +use crate::cache::{Cache, Interned, INTERNER}; +use crate::check; +use crate::compile; +use crate::dist; +use crate::doc; +use crate::flags::Subcommand; +use crate::install; +use crate::native; +use crate::test; +use crate::tool; +use crate::util::{add_lib_path, exe, libdir}; +use crate::{Build, DocTests, Mode, GitRepo}; -pub use Compiler; +pub use crate::Compiler; use petgraph::graph::NodeIndex; use petgraph::Graph; @@ -389,7 +389,6 @@ impl<'a> Builder<'a> { test::UiFullDeps, test::RunPassFullDeps, test::RunFailFullDeps, - test::CompileFailFullDeps, test::Rustdoc, test::Pretty, test::RunPassPretty, @@ -417,6 +416,7 @@ impl<'a> Builder<'a> { test::Rustfmt, test::Miri, test::Clippy, + test::CompiletestTest, test::RustdocJS, test::RustdocTheme, // Run bootstrap close to the end as it's unlikely to fail @@ -685,6 +685,11 @@ impl<'a> Builder<'a> { .env("RUSTDOC_REAL", self.rustdoc(host)) .env("RUSTDOC_CRATE_VERSION", self.rust_version()) .env("RUSTC_BOOTSTRAP", "1"); + + // Remove make-related flags that can cause jobserver problems. + cmd.env_remove("MAKEFLAGS"); + cmd.env_remove("MFLAGS"); + if let Some(linker) = self.linker(host) { cmd.env("RUSTC_TARGET_LINKER", linker); } @@ -793,7 +798,7 @@ impl<'a> Builder<'a> { } // Set a flag for `check` so that certain build scripts can do less work - // (e.g. not building/requiring LLVM). + // (e.g., not building/requiring LLVM). if cmd == "check" { cargo.env("RUST_CHECK", "1"); } @@ -923,12 +928,12 @@ impl<'a> Builder<'a> { cargo.env("RUSTC_FORCE_UNSTABLE", "1"); // Currently the compiler depends on crates from crates.io, and - // then other crates can depend on the compiler (e.g. proc-macro + // then other crates can depend on the compiler (e.g., proc-macro // crates). Let's say, for example that rustc itself depends on the // bitflags crate. If an external crate then depends on the // bitflags crate as well, we need to make sure they don't // conflict, even if they pick the same version of bitflags. We'll - // want to make sure that e.g. a plugin and rustc each get their + // want to make sure that e.g., a plugin and rustc each get their // own copy of bitflags. // Cargo ensures that this works in general through the -C metadata @@ -1247,7 +1252,7 @@ impl<'a> Builder<'a> { #[cfg(test)] mod __test { use super::*; - use config::Config; + use crate::config::Config; use std::thread; fn configure(host: &[&str], target: &[&str]) -> Config { diff --git a/src/bootstrap/cache.rs b/src/bootstrap/cache.rs index 0b561a3523f..165cffa4587 100644 --- a/src/bootstrap/cache.rs +++ b/src/bootstrap/cache.rs @@ -23,7 +23,7 @@ use std::path::{Path, PathBuf}; use std::sync::Mutex; use std::cmp::{PartialOrd, Ord, Ordering}; -use builder::Step; +use crate::builder::Step; pub struct Interned(usize, PhantomData<*const T>); diff --git a/src/bootstrap/cc_detect.rs b/src/bootstrap/cc_detect.rs index d5da0cabec8..3307d9d3573 100644 --- a/src/bootstrap/cc_detect.rs +++ b/src/bootstrap/cc_detect.rs @@ -39,9 +39,9 @@ use std::process::Command; use build_helper::output; use cc; -use {Build, GitRepo}; -use config::Target; -use cache::Interned; +use crate::{Build, GitRepo}; +use crate::config::Target; +use crate::cache::Interned; // The `cc` crate doesn't provide a way to obtain a path to the detected archiver, // so use some simplified logic here. First we respect the environment variable `AR`, then @@ -143,7 +143,10 @@ fn set_compiler(cfg: &mut cc::Build, // compiler already takes into account the triple in question. t if t.contains("android") => { if let Some(ndk) = config.and_then(|c| c.ndk.as_ref()) { - let target = target.replace("armv7", "arm"); + let target = target.replace("armv7neon", "arm") + .replace("armv7", "arm") + .replace("thumbv7neon", "arm") + .replace("thumbv7", "arm"); let compiler = format!("{}-{}", target, compiler.clang()); cfg.compiler(ndk.join("bin").join(compiler)); } diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs index 88b6925b2b1..8756ec944c2 100644 --- a/src/bootstrap/channel.rs +++ b/src/bootstrap/channel.rs @@ -20,11 +20,11 @@ use std::process::Command; use build_helper::output; -use Build; -use config::Config; +use crate::Build; +use crate::config::Config; // The version number -pub const CFG_RELEASE_NUM: &str = "1.32.0"; +pub const CFG_RELEASE_NUM: &str = "1.33.0"; pub struct GitInfo { inner: Option, diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 0c6dbb06bb8..84e7c40e455 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -10,11 +10,12 @@ //! Implementation of compiling the compiler and standard library, in "check" mode. -use compile::{run_cargo, std_cargo, test_cargo, rustc_cargo, rustc_cargo_env, add_to_sysroot}; -use builder::{RunConfig, Builder, ShouldRun, Step}; -use tool::{prepare_tool_cargo, SourceType}; -use {Compiler, Mode}; -use cache::{INTERNER, Interned}; +use crate::compile::{run_cargo, std_cargo, test_cargo, rustc_cargo, rustc_cargo_env, + add_to_sysroot}; +use crate::builder::{RunConfig, Builder, ShouldRun, Step}; +use crate::tool::{prepare_tool_cargo, SourceType}; +use crate::{Compiler, Mode}; +use crate::cache::{INTERNER, Interned}; use std::path::PathBuf; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs index 87f194fb7d2..dc42159d068 100644 --- a/src/bootstrap/clean.rs +++ b/src/bootstrap/clean.rs @@ -19,7 +19,7 @@ use std::fs; use std::io::{self, ErrorKind}; use std::path::Path; -use Build; +use crate::Build; pub fn clean(build: &Build, all: bool) { rm_rf("tmp".as_ref()); diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index b6bb11d07ef..61a04b97206 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -18,7 +18,7 @@ use std::borrow::Cow; use std::env; -use std::fs::{self, File}; +use std::fs; use std::io::BufReader; use std::io::prelude::*; use std::path::{Path, PathBuf}; @@ -29,12 +29,12 @@ use build_helper::{output, mtime, up_to_date}; use filetime::FileTime; use serde_json; -use util::{exe, libdir, is_dylib}; -use {Compiler, Mode, GitRepo}; -use native; +use crate::util::{exe, libdir, is_dylib}; +use crate::{Compiler, Mode, GitRepo}; +use crate::native; -use cache::{INTERNER, Interned}; -use builder::{Step, RunConfig, ShouldRun, Builder}; +use crate::cache::{INTERNER, Interned}; +use crate::builder::{Step, RunConfig, ShouldRun, Builder}; #[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)] pub struct Std { @@ -152,11 +152,12 @@ pub fn std_cargo(builder: &Builder, if builder.no_std(target) == Some(true) { // for no-std targets we only compile a few no_std crates - cargo.arg("--features").arg("c mem") + cargo .args(&["-p", "alloc"]) - .args(&["-p", "compiler_builtins"]) .arg("--manifest-path") - .arg(builder.src.join("src/rustc/compiler_builtins_shim/Cargo.toml")); + .arg(builder.src.join("src/liballoc/Cargo.toml")) + .arg("--features") + .arg("compiler-builtins-mem"); } else { let features = builder.std_features(); @@ -707,7 +708,7 @@ impl Step for CodegenBackend { } let stamp = codegen_backend_stamp(builder, compiler, target, backend); let codegen_backend = codegen_backend.to_str().unwrap(); - t!(t!(File::create(&stamp)).write_all(codegen_backend.as_bytes())); + t!(fs::write(&stamp, &codegen_backend)); } } @@ -796,8 +797,7 @@ fn copy_codegen_backends_to_sysroot(builder: &Builder, for backend in builder.config.rust_codegen_backends.iter() { let stamp = codegen_backend_stamp(builder, compiler, target, *backend); - let mut dylib = String::new(); - t!(t!(File::open(&stamp)).read_to_string(&mut dylib)); + let dylib = t!(fs::read_to_string(&stamp)); let file = Path::new(&dylib); let filename = file.file_name().unwrap().to_str().unwrap(); // change `librustc_codegen_llvm-xxxxxx.so` to `librustc_codegen_llvm-llvm.so` @@ -1137,10 +1137,7 @@ pub fn run_cargo(builder: &Builder, // contents (the list of files to copy) is different or if any dep's mtime // is newer then we rewrite the stamp file. deps.sort(); - let mut stamp_contents = Vec::new(); - if let Ok(mut f) = File::open(stamp) { - t!(f.read_to_end(&mut stamp_contents)); - } + let stamp_contents = fs::read(stamp); let stamp_mtime = mtime(&stamp); let mut new_contents = Vec::new(); let mut max = None; @@ -1156,7 +1153,10 @@ pub fn run_cargo(builder: &Builder, } let max = max.unwrap(); let max_path = max_path.unwrap(); - if stamp_contents == new_contents && max <= stamp_mtime { + let contents_equal = stamp_contents + .map(|contents| contents == new_contents) + .unwrap_or_default(); + if contents_equal && max <= stamp_mtime { builder.verbose(&format!("not updating {:?}; contents equal and {:?} <= {:?}", stamp, max, stamp_mtime)); return deps @@ -1166,7 +1166,7 @@ pub fn run_cargo(builder: &Builder, } else { builder.verbose(&format!("updating {:?} as deps changed", stamp)); } - t!(t!(File::create(stamp)).write_all(&new_contents)); + t!(fs::write(&stamp, &new_contents)); deps } diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 8fc2d5787cb..2ae9da9c085 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -15,17 +15,16 @@ use std::collections::{HashMap, HashSet}; use std::env; -use std::fs::{self, File}; -use std::io::prelude::*; +use std::fs; use std::path::{Path, PathBuf}; use std::process; use std::cmp; use num_cpus; use toml; -use cache::{INTERNER, Interned}; -use flags::Flags; -pub use flags::Subcommand; +use crate::cache::{INTERNER, Interned}; +use crate::flags::Flags; +pub use crate::flags::Subcommand; /// Global configuration for the entire build and/or bootstrap. /// @@ -416,9 +415,7 @@ impl Config { config.run_host_only = !(flags.host.is_empty() && !flags.target.is_empty()); let toml = file.map(|file| { - let mut f = t!(File::open(&file)); - let mut contents = String::new(); - t!(f.read_to_string(&mut contents)); + let contents = t!(fs::read_to_string(&file)); match toml::from_str(&contents) { Ok(table) => table, Err(err) => { diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 5467c9f9d5b..f2473cb9eda 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -107,6 +107,8 @@ v("arm-linux-androideabi-ndk", "target.arm-linux-androideabi.android-ndk", "arm-linux-androideabi NDK standalone path") v("armv7-linux-androideabi-ndk", "target.armv7-linux-androideabi.android-ndk", "armv7-linux-androideabi NDK standalone path") +v("thumbv7neon-linux-androideabi-ndk", "target.thumbv7neon-linux-androideabi.android-ndk", + "thumbv7neon-linux-androideabi NDK standalone path") v("aarch64-linux-android-ndk", "target.aarch64-linux-android.android-ndk", "aarch64-linux-android NDK standalone path") v("x86_64-linux-android-ndk", "target.x86_64-linux-android.android-ndk", diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index cd8d5642b25..927f9bf8ddb 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -19,20 +19,20 @@ //! pieces of `rustup.rs`! use std::env; -use std::fs::{self, File}; -use std::io::{Read, Write}; +use std::fs; +use std::io::Write; use std::path::{PathBuf, Path}; use std::process::{Command, Stdio}; use build_helper::output; -use {Compiler, Mode, LLVM_TOOLS}; -use channel; -use util::{libdir, is_dylib, exe}; -use builder::{Builder, RunConfig, ShouldRun, Step}; -use compile; -use tool::{self, Tool}; -use cache::{INTERNER, Interned}; +use crate::{Compiler, Mode, LLVM_TOOLS}; +use crate::channel; +use crate::util::{libdir, is_dylib, exe}; +use crate::builder::{Builder, RunConfig, ShouldRun, Step}; +use crate::compile; +use crate::tool::{self, Tool}; +use crate::cache::{INTERNER, Interned}; use time; pub fn pkgname(builder: &Builder, component: &str) -> String { @@ -353,7 +353,7 @@ impl Step for Mingw { /// Build the `rust-mingw` installer component. /// /// This contains all the bits and pieces to run the MinGW Windows targets - /// without any extra installed software (e.g. we bundle gcc, libraries, etc). + /// without any extra installed software (e.g., we bundle gcc, libraries, etc). fn run(self, builder: &Builder) -> Option { let host = self.host; @@ -857,12 +857,9 @@ impl Step for Src { // (essentially libstd and all of its path dependencies) let std_src_dirs = [ "src/build_helper", - "src/dlmalloc", "src/liballoc", "src/libbacktrace", - "src/libcompiler_builtins", "src/libcore", - "src/liblibc", "src/libpanic_abort", "src/libpanic_unwind", "src/librustc_asan", @@ -871,20 +868,15 @@ impl Step for Src { "src/librustc_tsan", "src/libstd", "src/libunwind", - "src/rustc/compiler_builtins_shim", - "src/rustc/libc_shim", - "src/rustc/dlmalloc_shim", "src/libtest", "src/libterm", "src/libprofiler_builtins", "src/stdsimd", "src/libproc_macro", - ]; - let std_src_dirs_exclude = [ - "src/libcompiler_builtins/compiler-rt/test", + "src/tools/rustc-std-workspace-core", ]; - copy_src_dirs(builder, &std_src_dirs[..], &std_src_dirs_exclude[..], &dst_src); + copy_src_dirs(builder, &std_src_dirs[..], &[], &dst_src); for file in src_files.iter() { builder.copy(&builder.src.join(file), &dst_src.join(file)); } @@ -908,7 +900,7 @@ impl Step for Src { } } -const CARGO_VENDOR_VERSION: &str = "0.1.19"; +const CARGO_VENDOR_VERSION: &str = "0.1.22"; #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct PlainSourceTarball; @@ -1510,8 +1502,7 @@ impl Step for Extended { } let xform = |p: &Path| { - let mut contents = String::new(); - t!(t!(File::open(p)).read_to_string(&mut contents)); + let mut contents = t!(fs::read_to_string(p)); if rls_installer.is_none() { contents = filter(&contents, "rls"); } @@ -1522,8 +1513,8 @@ impl Step for Extended { contents = filter(&contents, "rustfmt"); } let ret = tmp.join(p.file_name().unwrap()); - t!(t!(File::create(&ret)).write_all(contents.as_bytes())); - return ret + t!(fs::write(&ret, &contents)); + ret }; if target.contains("apple-darwin") { @@ -1868,8 +1859,7 @@ impl Step for HashSign { let file = builder.config.dist_gpg_password_file.as_ref().unwrap_or_else(|| { panic!("\n\nfailed to specify `dist.gpg-password-file` in `config.toml`\n\n") }); - let mut pass = String::new(); - t!(t!(File::open(&file)).read_to_string(&mut pass)); + let pass = t!(fs::read_to_string(&file)); let today = output(Command::new("date").arg("+%Y-%m-%d")); diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 201129b92df..217328adfbf 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -18,20 +18,19 @@ //! `rustdoc`. use std::collections::HashSet; -use std::fs::{self, File}; -use std::io::prelude::*; +use std::fs; use std::io; use std::path::{PathBuf, Path}; -use Mode; +use crate::Mode; use build_helper::up_to_date; -use util::symlink_dir; -use builder::{Builder, Compiler, RunConfig, ShouldRun, Step}; -use tool::{self, prepare_tool_cargo, Tool, SourceType}; -use compile; -use cache::{INTERNER, Interned}; -use config::Config; +use crate::util::symlink_dir; +use crate::builder::{Builder, Compiler, RunConfig, ShouldRun, Step}; +use crate::tool::{self, prepare_tool_cargo, Tool, SourceType}; +use crate::compile; +use crate::cache::{INTERNER, Interned}; +use crate::config::Config; macro_rules! book { ($($name:ident, $path:expr, $book_name:expr;)+) => { @@ -379,12 +378,11 @@ impl Step for Standalone { let version_info = out.join("version_info.html"); if !builder.config.dry_run && !up_to_date(&version_input, &version_info) { - let mut info = String::new(); - t!(t!(File::open(&version_input)).read_to_string(&mut info)); - let info = info.replace("VERSION", &builder.rust_release()) - .replace("SHORT_HASH", builder.rust_info.sha_short().unwrap_or("")) - .replace("STAMP", builder.rust_info.sha().unwrap_or("")); - t!(t!(File::create(&version_info)).write_all(info.as_bytes())); + let info = t!(fs::read_to_string(&version_input)) + .replace("VERSION", &builder.rust_release()) + .replace("SHORT_HASH", builder.rust_info.sha_short().unwrap_or("")) + .replace("STAMP", builder.rust_info.sha().unwrap_or("")); + t!(fs::write(&version_info, &info)); } for file in t!(fs::read_dir(builder.src.join("src/doc"))) { @@ -697,9 +695,6 @@ impl Step for Rustc { return; } - // Build libstd docs so that we generate relative links. - builder.ensure(Std { stage, target }); - // Build rustc. builder.ensure(compile::Rustc { compiler, target }); @@ -718,12 +713,16 @@ impl Step for Rustc { // Find dependencies for top level crates. let mut compiler_crates = HashSet::new(); - for root_crate in &["rustc", "rustc_driver", "rustc_codegen_llvm"] { + for root_crate in &["rustc_driver", "rustc_codegen_llvm", "rustc_codegen_ssa"] { let interned_root_crate = INTERNER.intern_str(root_crate); find_compiler_crates(builder, &interned_root_crate, &mut compiler_crates); } for krate in &compiler_crates { + // Create all crate output directories first to make sure rustdoc uses + // relative links. + // FIXME: Cargo should probably do this itself. + t!(fs::create_dir_all(out_dir.join(krate))); cargo.arg("-p").arg(krate); } @@ -797,8 +796,8 @@ impl Step for Rustdoc { return; } - // Build libstd docs so that we generate relative links. - builder.ensure(Std { stage, target }); + // Build rustc docs so that we generate relative links. + builder.ensure(Rustc { stage, target }); // Build rustdoc. builder.ensure(tool::Rustdoc { host: compiler.host }); @@ -822,6 +821,10 @@ impl Step for Rustdoc { &[] ); + // Only include compiler crates, no dependencies of those, such as `libc`. + cargo.arg("--no-deps"); + cargo.arg("-p").arg("rustdoc"); + cargo.env("RUSTDOCFLAGS", "--document-private-items"); builder.run(&mut cargo); } diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 1211d485d1c..14e2f69432d 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -19,12 +19,12 @@ use std::process; use getopts::Options; -use builder::Builder; -use config::Config; -use metadata; -use {Build, DocTests}; +use crate::builder::Builder; +use crate::config::Config; +use crate::metadata; +use crate::{Build, DocTests}; -use cache::{Interned, INTERNER}; +use crate::cache::{Interned, INTERNER}; /// Deserialized version of all flags for this compile. pub struct Flags { @@ -121,11 +121,11 @@ To learn more about a subcommand, run `./x.py -h`" opts.optopt("", "on-fail", "command to run on failure", "CMD"); opts.optflag("", "dry-run", "dry run; don't build anything"); opts.optopt("", "stage", - "stage to build (indicates compiler to use/test, e.g. stage 0 uses the \ + "stage to build (indicates compiler to use/test, e.g., stage 0 uses the \ bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)", "N"); opts.optmulti("", "keep-stage", "stage(s) to keep without recompiling \ - (pass multiple times to keep e.g. both stages 0 and 1)", "N"); + (pass multiple times to keep e.g., both stages 0 and 1)", "N"); opts.optopt("", "src", "path to the root of the rust checkout", "DIR"); opts.optopt("j", "jobs", "number of jobs to run in parallel", "JOBS"); opts.optflag("h", "help", "print this help message"); diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index cb28698aa3d..aebcfb45195 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -18,11 +18,11 @@ use std::fs; use std::path::{Path, PathBuf, Component}; use std::process::Command; -use dist::{self, pkgname, sanitize_sh, tmpdir}; +use crate::dist::{self, pkgname, sanitize_sh, tmpdir}; -use builder::{Builder, RunConfig, ShouldRun, Step}; -use cache::Interned; -use config::Config; +use crate::builder::{Builder, RunConfig, ShouldRun, Step}; +use crate::cache::Interned; +use crate::config::Config; pub fn install_docs(builder: &Builder, stage: u32, host: Interned) { install_sh(builder, "docs", "rust-docs", stage, Some(host)); diff --git a/src/bootstrap/job.rs b/src/bootstrap/job.rs index e6ee525ca2e..a9da2c491da 100644 --- a/src/bootstrap/job.rs +++ b/src/bootstrap/job.rs @@ -10,7 +10,7 @@ //! Job management on Windows for bootstrapping //! -//! Most of the time when you're running a build system (e.g. make) you expect +//! Most of the time when you're running a build system (e.g., make) you expect //! Ctrl-C or abnormal termination to actually terminate the entire tree of //! process in play, not just the one at the top. This currently works "by //! default" on Unix platforms because Ctrl-C actually sends a signal to the @@ -42,7 +42,7 @@ use std::env; use std::io; use std::mem; -use Build; +use crate::Build; type HANDLE = *mut u8; type BOOL = i32; @@ -162,11 +162,11 @@ pub unsafe fn setup(build: &mut Build) { return } - // If we've got a parent process (e.g. the python script that called us) + // If we've got a parent process (e.g., the python script that called us) // then move ownership of this job object up to them. That way if the python - // script is killed (e.g. via ctrl-c) then we'll all be torn down. + // script is killed (e.g., via ctrl-c) then we'll all be torn down. // - // If we don't have a parent (e.g. this was run directly) then we + // If we don't have a parent (e.g., this was run directly) then we // intentionally leak the job object handle. When our process exits // (normally or abnormally) it will close the handle implicitly, causing all // processes in the job to be cleaned up. @@ -184,7 +184,7 @@ pub unsafe fn setup(build: &mut Build) { // If this failed, well at least we tried! An example of DuplicateHandle // failing in the past has been when the wrong python2 package spawned this - // build system (e.g. the `python2` package in MSYS instead of + // build system (e.g., the `python2` package in MSYS instead of // `mingw-w64-x86_64-python2`. Not sure why it failed, but the "failure // mode" here is that we only clean everything up when the build system // dies, not when the python parent does, so not too bad. diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 2832f5bebdd..c5b8f19eee6 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -38,7 +38,7 @@ //! However, compiletest itself tries to avoid running tests when the artifacts //! that are involved (mainly the compiler) haven't changed. //! -//! When you execute `x.py build`, the steps which are executed are: +//! When you execute `x.py build`, the steps executed are: //! //! * First, the python script is run. This will automatically download the //! stage0 rustc and cargo according to `src/stage0.txt`, or use the cached @@ -159,7 +159,7 @@ use std::os::windows::fs::symlink_file; use build_helper::{run_silent, run_suppressed, try_run_silent, try_run_suppressed, output, mtime}; use filetime::FileTime; -use util::{exe, libdir, OutputFolder, CiEnv}; +use crate::util::{exe, libdir, OutputFolder, CiEnv}; mod cc_detect; mod channel; @@ -188,7 +188,7 @@ mod job; mod job { use libc; - pub unsafe fn setup(build: &mut ::Build) { + pub unsafe fn setup(build: &mut crate::Build) { if build.config.low_priority { libc::setpriority(libc::PRIO_PGRP as _, 0, 10); } @@ -197,14 +197,14 @@ mod job { #[cfg(any(target_os = "haiku", not(any(unix, windows))))] mod job { - pub unsafe fn setup(_build: &mut ::Build) { + pub unsafe fn setup(_build: &mut crate::Build) { } } -pub use config::Config; -use flags::Subcommand; -use cache::{Interned, INTERNER}; -use toolstate::ToolState; +pub use crate::config::Config; +use crate::flags::Subcommand; +use crate::cache::{Interned, INTERNER}; +use crate::toolstate::ToolState; const LLVM_TOOLS: &[&str] = &[ "llvm-nm", // used to inspect binaries; it shows symbol names, their sizes and visibility @@ -1067,9 +1067,8 @@ impl Build { /// Returns the `a.b.c` version that the given package is at. fn release_num(&self, package: &str) -> String { - let mut toml = String::new(); let toml_file_name = self.src.join(&format!("src/tools/{}/Cargo.toml", package)); - t!(t!(File::open(toml_file_name)).read_to_string(&mut toml)); + let toml = t!(fs::read_to_string(&toml_file_name)); for line in toml.lines() { let prefix = "version = \""; let suffix = "\""; @@ -1135,10 +1134,10 @@ impl Build { let krate = &self.crates[&krate]; if krate.is_local(self) { ret.push(krate); - for dep in &krate.deps { - if visited.insert(dep) && dep != "build_helper" { - list.push(*dep); - } + } + for dep in &krate.deps { + if visited.insert(dep) && dep != "build_helper" { + list.push(*dep); } } } @@ -1151,8 +1150,7 @@ impl Build { } let mut paths = Vec::new(); - let mut contents = Vec::new(); - t!(t!(File::open(stamp)).read_to_end(&mut contents)); + let contents = t!(fs::read(stamp)); // This is the method we use for extracting paths from the stamp file passed to us. See // run_cargo for more information (in compile.rs). for part in contents.split(|b| *b == 0) { diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/metadata.rs index fa0b1983510..bb503e8b8d3 100644 --- a/src/bootstrap/metadata.rs +++ b/src/bootstrap/metadata.rs @@ -16,8 +16,8 @@ use std::collections::HashSet; use build_helper::output; use serde_json; -use {Build, Crate}; -use cache::INTERNER; +use crate::{Build, Crate}; +use crate::cache::INTERNER; #[derive(Deserialize)] struct Output { diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 448967ef0c2..d9f51f6fd3d 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -21,7 +21,6 @@ use std::env; use std::ffi::OsString; use std::fs::{self, File}; -use std::io::{Read, Write}; use std::path::{Path, PathBuf}; use std::process::Command; @@ -29,11 +28,11 @@ use build_helper::output; use cmake; use cc; -use util::{self, exe}; +use crate::util::{self, exe}; use build_helper::up_to_date; -use builder::{Builder, RunConfig, ShouldRun, Step}; -use cache::Interned; -use GitRepo; +use crate::builder::{Builder, RunConfig, ShouldRun, Step}; +use crate::cache::Interned; +use crate::GitRepo; #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Llvm { @@ -75,8 +74,7 @@ impl Step for Llvm { } let rebuild_trigger = builder.src.join("src/rustllvm/llvm-rebuild-trigger"); - let mut rebuild_trigger_contents = String::new(); - t!(t!(File::open(&rebuild_trigger)).read_to_string(&mut rebuild_trigger_contents)); + let rebuild_trigger_contents = t!(fs::read_to_string(&rebuild_trigger)); let (out_dir, llvm_config_ret_dir) = if emscripten { let dir = builder.emscripten_llvm_out(target); @@ -93,8 +91,7 @@ impl Step for Llvm { let build_llvm_config = llvm_config_ret_dir .join(exe("llvm-config", &*builder.config.build)); if done_stamp.exists() { - let mut done_contents = String::new(); - t!(t!(File::open(&done_stamp)).read_to_string(&mut done_contents)); + let done_contents = t!(fs::read_to_string(&done_stamp)); // If LLVM was already built previously and contents of the rebuild-trigger file // didn't change from the previous build, then no action is required. @@ -251,7 +248,7 @@ impl Step for Llvm { configure_cmake(builder, target, &mut cfg, false); // FIXME: we don't actually need to build all LLVM tools and all LLVM - // libraries here, e.g. we just want a few components and a few + // libraries here, e.g., we just want a few components and a few // tools. Figure out how to filter them down and only build the right // tools and libs on all platforms. @@ -261,7 +258,7 @@ impl Step for Llvm { cfg.build(); - t!(t!(File::create(&done_stamp)).write_all(rebuild_trigger_contents.as_bytes())); + t!(fs::write(&done_stamp, &rebuild_trigger_contents)); build_llvm_config } @@ -281,11 +278,11 @@ fn check_llvm_version(builder: &Builder, llvm_config: &Path) { let mut parts = version.split('.').take(2) .filter_map(|s| s.parse::().ok()); if let (Some(major), Some(_minor)) = (parts.next(), parts.next()) { - if major >= 5 { + if major >= 6 { return } } - panic!("\n\nbad LLVM version: {}, need >=5.0\n\n", version) + panic!("\n\nbad LLVM version: {}, need >=6.0\n\n", version) } fn configure_cmake(builder: &Builder, diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 15d3bccba09..f585495b0aa 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -21,14 +21,13 @@ use std::collections::HashMap; use std::env; use std::ffi::{OsString, OsStr}; -use std::fs::{self, File}; -use std::io::Read; +use std::fs; use std::path::PathBuf; use std::process::Command; use build_helper::output; -use Build; +use crate::Build; struct Finder { cache: HashMap>, @@ -235,9 +234,7 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake } if build.config.channel == "stable" { - let mut stage0 = String::new(); - t!(t!(File::open(build.src.join("src/stage0.txt"))) - .read_to_string(&mut stage0)); + let stage0 = t!(fs::read_to_string(build.src.join("src/stage0.txt"))); if stage0.contains("\ndev:") { panic!("bootstrapping from a dev compiler in a stable release, but \ should only be bootstrapping from a released compiler!"); diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index da827356800..11932d58cea 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -16,25 +16,24 @@ use std::env; use std::ffi::OsString; use std::fmt; -use std::fs::{self, File}; -use std::io::Read; +use std::fs; use std::iter; use std::path::{Path, PathBuf}; use std::process::Command; use build_helper::{self, output}; -use builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; -use cache::{Interned, INTERNER}; -use compile; -use dist; -use flags::Subcommand; -use native; -use tool::{self, Tool, SourceType}; -use toolstate::ToolState; -use util::{self, dylib_path, dylib_path_var}; -use Crate as CargoCrate; -use {DocTests, Mode, GitRepo}; +use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; +use crate::cache::{Interned, INTERNER}; +use crate::compile; +use crate::dist; +use crate::flags::Subcommand; +use crate::native; +use crate::tool::{self, Tool, SourceType}; +use crate::toolstate::ToolState; +use crate::util::{self, dylib_path, dylib_path_var}; +use crate::Crate as CargoCrate; +use crate::{DocTests, Mode, GitRepo}; const ADB_TEST_DIR: &str = "/data/tmp/work"; @@ -430,6 +429,45 @@ impl Step for Miri { } } +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct CompiletestTest { + stage: u32, + host: Interned, +} + +impl Step for CompiletestTest { + type Output = (); + + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/tools/compiletest") + } + + fn make_run(run: RunConfig) { + run.builder.ensure(CompiletestTest { + stage: run.builder.top_stage, + host: run.target, + }); + } + + /// Runs `cargo test` for compiletest. + fn run(self, builder: &Builder) { + let stage = self.stage; + let host = self.host; + let compiler = builder.compiler(stage, host); + + let mut cargo = tool::prepare_tool_cargo(builder, + compiler, + Mode::ToolBootstrap, + host, + "test", + "src/tools/compiletest", + SourceType::InTree, + &[]); + + try_run(builder, &mut cargo); + } +} + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Clippy { stage: u32, @@ -578,7 +616,7 @@ impl Step for RustdocJS { if let Some(ref nodejs) = builder.config.nodejs { let mut command = Command::new(nodejs); command.args(&["src/tools/rustdoc-js/tester.js", &*self.host]); - builder.ensure(::doc::Std { + builder.ensure(crate::doc::Std { target: self.target, stage: builder.top_stage, }); @@ -833,12 +871,6 @@ host_test!(RunFailFullDeps { suite: "run-fail-fulldeps" }); -host_test!(CompileFailFullDeps { - path: "src/test/compile-fail-fulldeps", - mode: "compile-fail", - suite: "compile-fail-fulldeps" -}); - host_test!(Rustdoc { path: "src/test/rustdoc", mode: "rustdoc", @@ -971,7 +1003,7 @@ impl Step for Compiletest { } if builder.no_std(target) == Some(true) { - // for no_std run-make (e.g. thumb*), + // for no_std run-make (e.g., thumb*), // we need a host compiler which is called by cargo. builder.ensure(compile::Std { compiler, target: compiler.host }); } @@ -1277,7 +1309,7 @@ impl Step for DocTest { /// Run `rustdoc --test` for all documentation in `src/doc`. /// - /// This will run all tests in our markdown documentation (e.g. the book) + /// This will run all tests in our markdown documentation (e.g., the book) /// located in `src/doc`. The `rustdoc` that's run is the one that sits next to /// `compiler`. fn run(self, builder: &Builder) { @@ -1427,10 +1459,8 @@ impl Step for ErrorIndex { } fn markdown_test(builder: &Builder, compiler: Compiler, markdown: &Path) -> bool { - match File::open(markdown) { - Ok(mut file) => { - let mut contents = String::new(); - t!(file.read_to_string(&mut contents)); + match fs::read_to_string(markdown) { + Ok(contents) => { if !contents.contains("```") { return true; } @@ -1567,10 +1597,7 @@ impl Step for Crate { let builder = run.builder; run = run.krate("test"); for krate in run.builder.in_tree_crates("std") { - if krate.is_local(&run.builder) - && !(krate.name.starts_with("rustc_") && krate.name.ends_with("san")) - && krate.name != "dlmalloc" - { + if !(krate.name.starts_with("rustc_") && krate.name.ends_with("san")) { run = run.path(krate.local_path(&builder).to_str().unwrap()); } } diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 58c5296beb3..4335359e115 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -15,16 +15,16 @@ use std::path::PathBuf; use std::process::{Command, exit}; use std::collections::HashSet; -use Mode; -use Compiler; -use builder::{Step, RunConfig, ShouldRun, Builder}; -use util::{exe, add_lib_path}; -use compile; -use native; -use channel::GitInfo; -use channel; -use cache::Interned; -use toolstate::ToolState; +use crate::Mode; +use crate::Compiler; +use crate::builder::{Step, RunConfig, ShouldRun, Builder}; +use crate::util::{exe, add_lib_path}; +use crate::compile; +use crate::native; +use crate::channel::GitInfo; +use crate::channel; +use crate::cache::Interned; +use crate::toolstate::ToolState; #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub enum SourceType { @@ -646,7 +646,7 @@ impl<'a> Builder<'a> { self.cargo_out(compiler, tool.get_mode(), *host).join("deps"), ]; - // On MSVC a tool may invoke a C compiler (e.g. compiletest in run-make + // On MSVC a tool may invoke a C compiler (e.g., compiletest in run-make // mode) and that C compiler may need some extra PATH modification. Do // so here. if compiler.host.contains("msvc") { diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index be24ae0ce66..b18e38e471e 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -21,8 +21,8 @@ use std::path::{Path, PathBuf}; use std::process::Command; use std::time::{SystemTime, Instant}; -use config::Config; -use builder::Builder; +use crate::config::Config; +use crate::builder::Builder; /// Returns the `name` as the filename of a static library for `target`. pub fn staticlib(name: &str, target: &str) -> String { diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs index 0cbb0802361..a580a874b33 100644 --- a/src/build_helper/lib.rs +++ b/src/build_helper/lib.rs @@ -224,14 +224,12 @@ impl Drop for NativeLibBoilerplate { // Timestamps are created automatically when the result of `native_lib_boilerplate` goes out // of scope, so all the build actions should be completed until then. pub fn native_lib_boilerplate( - src_name: &str, + src_dir: &Path, out_name: &str, link_name: &str, search_subdir: &str, ) -> Result { - let current_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); - let src_dir = current_dir.join("..").join(src_name); - rerun_if_changed_anything_in_dir(&src_dir); + rerun_if_changed_anything_in_dir(src_dir); let out_dir = env::var_os("RUSTBUILD_NATIVE_DIR").unwrap_or_else(|| env::var_os("OUT_DIR").unwrap()); @@ -248,9 +246,9 @@ pub fn native_lib_boilerplate( ); let timestamp = out_dir.join("rustbuild.timestamp"); - if !up_to_date(Path::new("build.rs"), ×tamp) || !up_to_date(&src_dir, ×tamp) { + if !up_to_date(Path::new("build.rs"), ×tamp) || !up_to_date(src_dir, ×tamp) { Ok(NativeLibBoilerplate { - src_dir: src_dir, + src_dir: src_dir.to_path_buf(), out_dir: out_dir, }) } else { @@ -279,8 +277,11 @@ pub fn sanitizer_lib_boilerplate(sanitizer_name: &str) } else { format!("static={}", link_name) }; + // The source for `compiler-rt` comes from the `compiler-builtins` crate, so + // load our env var set by cargo to find the source code. + let dir = env::var_os("DEP_COMPILER_RT_COMPILER_RT").unwrap(); let lib = native_lib_boilerplate( - "libcompiler_builtins/compiler-rt", + dir.as_ref(), sanitizer_name, &to_link, search_path, diff --git a/src/ci/docker/dist-android/Dockerfile b/src/ci/docker/dist-android/Dockerfile index e00c23dac89..a54a2d003b6 100644 --- a/src/ci/docker/dist-android/Dockerfile +++ b/src/ci/docker/dist-android/Dockerfile @@ -16,6 +16,7 @@ RUN . /scripts/android-ndk.sh && \ # env ENV TARGETS=arm-linux-androideabi ENV TARGETS=$TARGETS,armv7-linux-androideabi +ENV TARGETS=$TARGETS,thumbv7neon-linux-androideabi ENV TARGETS=$TARGETS,i686-linux-android ENV TARGETS=$TARGETS,aarch64-linux-android ENV TARGETS=$TARGETS,x86_64-linux-android @@ -24,6 +25,7 @@ ENV RUST_CONFIGURE_ARGS \ --enable-extended \ --arm-linux-androideabi-ndk=/android/ndk/arm-14 \ --armv7-linux-androideabi-ndk=/android/ndk/arm-14 \ + --thumbv7neon-linux-androideabi-ndk=/android/ndk/arm-14 \ --i686-linux-android-ndk=/android/ndk/x86-14 \ --aarch64-linux-android-ndk=/android/ndk/arm64-21 \ --x86_64-linux-android-ndk=/android/ndk/x86_64-21 \ diff --git a/src/ci/docker/dist-various-1/Dockerfile b/src/ci/docker/dist-various-1/Dockerfile index c7e6af28f9d..4f8a3c0240e 100644 --- a/src/ci/docker/dist-various-1/Dockerfile +++ b/src/ci/docker/dist-various-1/Dockerfile @@ -52,8 +52,8 @@ RUN env \ CXX=arm-linux-gnueabi-g++ CXXFLAGS="-march=armv6 -marm" \ bash musl.sh arm && \ env \ - CC=arm-linux-gnueabihf-gcc CFLAGS="-march=armv6 -marm" \ - CXX=arm-linux-gnueabihf-g++ CXXFLAGS="-march=armv6 -marm" \ + CC=arm-linux-gnueabihf-gcc CFLAGS="-march=armv6 -marm -mfpu=vfp" \ + CXX=arm-linux-gnueabihf-g++ CXXFLAGS="-march=armv6 -marm -mfpu=vfp" \ bash musl.sh armhf && \ env \ CC=arm-linux-gnueabihf-gcc CFLAGS="-march=armv7-a" \ diff --git a/src/ci/docker/dist-x86_64-linux/build-clang.sh b/src/ci/docker/dist-x86_64-linux/build-clang.sh index 2762f0bf7ec..a7a8719b535 100755 --- a/src/ci/docker/dist-x86_64-linux/build-clang.sh +++ b/src/ci/docker/dist-x86_64-linux/build-clang.sh @@ -13,31 +13,28 @@ set -ex source shared.sh -LLVM=7.0.0 +# Currently these commits are all tip-of-tree as of 2018-12-16, used to pick up +# a fix for rust-lang/rust#56849 +LLVM=032b00a5404865765cda7db3039f39d54964d8b0 +LLD=3e4aa4e8671523321af51449e0569f455ef3ad43 +CLANG=a6b9739069763243020f4ea6fe586bc135fde1f9 mkdir clang cd clang -curl https://releases.llvm.org/$LLVM/llvm-$LLVM.src.tar.xz | \ - xz -d | \ - tar xf - - -cd llvm-$LLVM.src +curl -L https://github.com/llvm-mirror/llvm/archive/$LLVM.tar.gz | \ + tar xzf - --strip-components=1 mkdir -p tools/clang - -curl https://releases.llvm.org/$LLVM/cfe-$LLVM.src.tar.xz | \ - xz -d | \ - tar xf - -C tools/clang --strip-components=1 +curl -L https://github.com/llvm-mirror/clang/archive/$CLANG.tar.gz | \ + tar xzf - --strip-components=1 -C tools/clang mkdir -p tools/lld +curl -L https://github.com/llvm-mirror/lld/archive/$LLD.tar.gz | \ + tar zxf - --strip-components=1 -C tools/lld -curl https://releases.llvm.org/$LLVM/lld-$LLVM.src.tar.xz | \ - xz -d | \ - tar xf - -C tools/lld --strip-components=1 - -mkdir ../clang-build -cd ../clang-build +mkdir clang-build +cd clang-build # For whatever reason the default set of include paths for clang is different # than that of gcc. As a result we need to manually include our sysroot's @@ -55,7 +52,7 @@ INC="$INC:/rustroot/lib/gcc/x86_64-unknown-linux-gnu/4.8.5/include-fixed" INC="$INC:/usr/include" hide_output \ - cmake ../llvm-$LLVM.src \ + cmake .. \ -DCMAKE_C_COMPILER=/rustroot/bin/gcc \ -DCMAKE_CXX_COMPILER=/rustroot/bin/g++ \ -DCMAKE_BUILD_TYPE=Release \ diff --git a/src/ci/docker/mingw-check/Dockerfile b/src/ci/docker/mingw-check/Dockerfile index aab339f399c..10aedf6a60e 100644 --- a/src/ci/docker/mingw-check/Dockerfile +++ b/src/ci/docker/mingw-check/Dockerfile @@ -20,4 +20,5 @@ COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1 -ENV SCRIPT python2.7 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu +ENV SCRIPT python2.7 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \ + python2.7 ../x.py build --stage 0 src/tools/build-manifest diff --git a/src/ci/docker/x86_64-gnu-llvm-5.0/Dockerfile b/src/ci/docker/x86_64-gnu-llvm-6.0/Dockerfile similarity index 89% rename from src/ci/docker/x86_64-gnu-llvm-5.0/Dockerfile rename to src/ci/docker/x86_64-gnu-llvm-6.0/Dockerfile index 4f90c509726..160b23e0b00 100644 --- a/src/ci/docker/x86_64-gnu-llvm-5.0/Dockerfile +++ b/src/ci/docker/x86_64-gnu-llvm-6.0/Dockerfile @@ -11,7 +11,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ cmake \ sudo \ gdb \ - llvm-5.0-tools \ + llvm-6.0-tools \ libedit-dev \ zlib1g-dev \ xz-utils @@ -22,6 +22,6 @@ RUN sh /scripts/sccache.sh # using llvm-link-shared due to libffi issues -- see #34486 ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ - --llvm-root=/usr/lib/llvm-5.0 \ + --llvm-root=/usr/lib/llvm-6.0 \ --enable-llvm-link-shared ENV RUST_CHECK_TARGET check diff --git a/src/dlmalloc b/src/dlmalloc deleted file mode 160000 index c99638dc2ec..00000000000 --- a/src/dlmalloc +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c99638dc2ecfc750cc1656f6edb2bd062c1e0981 diff --git a/src/doc/book b/src/doc/book index 616fe4172b6..74d81d80052 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 616fe4172b688393aeee5f34935cc25733c9c062 +Subproject commit 74d81d80052cb88925f0e73b12fbd0b73ab7b5a0 diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index 4fc5f42dd55..94f21042c8f 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -22,6 +22,13 @@ This flag lets you append a single extra argument to the linker invocation. This flag lets you append multiple extra arguments to the linker invocation. The options should be separated by spaces. +## linker-flavor + +This flag lets you control the linker flavor used by `rustc`. If a linker is given with the +`-C linker` flag described above then the linker flavor is inferred from the value provided. If no +linker is given then the linker flavor is used to determine the linker to use. Every `rustc` target +defaults to some linker flavor. + ## link-dead-code Normally, the linker will remove dead code. This flag disables this behavior. diff --git a/src/doc/rustc/src/targets/built-in.md b/src/doc/rustc/src/targets/built-in.md index 8620346e5b7..2e94ebe345a 100644 --- a/src/doc/rustc/src/targets/built-in.md +++ b/src/doc/rustc/src/targets/built-in.md @@ -6,5 +6,5 @@ the team is supporting directly. To see the list of built-in targets, you can run `rustc --print target-list`, or look at [the API -docs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_back/target/#modules). +docs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_target/spec/index.html#modules). Each module there defines a builder for a particular target. \ No newline at end of file diff --git a/src/doc/rustc/src/targets/index.md b/src/doc/rustc/src/targets/index.md index 07e3a79471f..3d63d072bef 100644 --- a/src/doc/rustc/src/targets/index.md +++ b/src/doc/rustc/src/targets/index.md @@ -4,7 +4,7 @@ architecture. The list of *targets* are the possible architectures that you can build for. To see all the options that you can set with a target, see the docs -[here](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_back/target/struct.Target.html). +[here](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_target/spec/struct.Target.html). To compile to a particular target, use the `--target` flag: diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 43cdab27e9d..905b0646534 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -402,3 +402,18 @@ Using `index-page` option enables `enable-index-page` option as well. ### `--enable-index-page`: generate a default index page for docs This feature allows the generation of a default index-page which lists the generated crates. + +### `--static-root-path`: control how static files are loaded in HTML output + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs -Z unstable-options --static-root-path '/cache/' +``` + +This flag controls how rustdoc links to its static files on HTML pages. If you're hosting a lot of +crates' docs generated by the same version of rustdoc, you can use this flag to cache rustdoc's CSS, +JavaScript, and font files in a single location, rather than duplicating it once per "doc root" +(grouping of crate docs generated into the same output directory, like with `cargo doc`). Per-crate +files like the search index will still load from the documentation root, but anything that gets +renamed with `--resource-suffix` will load from the given path. diff --git a/src/doc/unstable-book/src/compiler-flags/linker-flavor.md b/src/doc/unstable-book/src/compiler-flags/linker-flavor.md deleted file mode 100644 index 39659602e01..00000000000 --- a/src/doc/unstable-book/src/compiler-flags/linker-flavor.md +++ /dev/null @@ -1,61 +0,0 @@ -# `linker-flavor` - -The tracking issue for this feature is: None - ------------------------- - -Every `rustc` target defaults to some linker. For example, Linux targets default -to gcc. In some cases, you may want to override the default; you can do that -with the unstable CLI argument: `-Z linker-flavor`. - -Here how you would use this flag to link a Rust binary for the -`thumbv7m-none-eabi` using LLD instead of GCC. - -``` text -$ xargo rustc --target thumbv7m-none-eabi -- \ - -C linker=ld.lld \ - -Z linker-flavor=ld \ - -Z print-link-args | tr ' ' '\n' -"ld.lld" -"-L" -"$SYSROOT/lib/rustlib/thumbv7m-none-eabi/lib" -"$PWD/target/thumbv7m-none-eabi/debug/deps/app-512e9dbf385f233c.0.o" -"-o" -"$PWD/target/thumbv7m-none-eabi/debug/deps/app-512e9dbf385f233c" -"--gc-sections" -"-L" -"$PWD/target/thumbv7m-none-eabi/debug/deps" -"-L" -"$PWD/target/debug/deps" -"-L" -"$SYSROOT/lib/rustlib/thumbv7m-none-eabi/lib" -"-Bstatic" -"$SYSROOT/lib/rustlib/thumbv7m-none-eabi/lib/libcore-e1ccb7dfb1cb9ebb.rlib" -"-Bdynamic" -``` - -Whereas the default is: - -``` text -$ xargo rustc --target thumbv7m-none-eabi -- \ - -C link-arg=-nostartfiles \ - -Z print-link-args | tr ' ' '\n' -"arm-none-eabi-gcc" -"-L" -"$SYSROOT/lib/rustlib/thumbv7m-none-eabi/lib" -"$PWD/target/thumbv7m-none-eabi/debug/deps/app-961e39416baa38d9.0.o" -"-o" -"$PWD/target/thumbv7m-none-eabi/debug/deps/app-961e39416baa38d9" -"-Wl,--gc-sections" -"-nodefaultlibs" -"-L" -"$PWD/target/thumbv7m-none-eabi/debug/deps" -"-L" -"$PWD/target/debug/deps" -"-L" -"$SYSROOT/lib/rustlib/thumbv7m-none-eabi/lib" -"-Wl,-Bstatic" -"$SYSROOT/lib/rustlib/thumbv7m-none-eabi/lib/libcore-e1ccb7dfb1cb9ebb.rlib" -"-nostartfiles" -"-Wl,-Bdynamic" -``` diff --git a/src/doc/unstable-book/src/language-features/generators.md b/src/doc/unstable-book/src/language-features/generators.md index 8e888de90a9..968534e58bd 100644 --- a/src/doc/unstable-book/src/language-features/generators.md +++ b/src/doc/unstable-book/src/language-features/generators.md @@ -149,7 +149,7 @@ closure-like semantics. Namely: * Whenever a generator is dropped it will drop all captured environment variables. -Note that unlike closures generators at this time cannot take any arguments. +Note that unlike closures, generators at this time cannot take any arguments. That is, generators must always look like `|| { ... }`. This restriction may be lifted at a future date, the design is ongoing! diff --git a/src/doc/unstable-book/src/language-features/repr-packed.md b/src/doc/unstable-book/src/language-features/repr-packed.md deleted file mode 100644 index 2dd763d04b0..00000000000 --- a/src/doc/unstable-book/src/language-features/repr-packed.md +++ /dev/null @@ -1,8 +0,0 @@ -# `repr_packed` - -The tracking issue for this feature is [#33158] - -[#33158]: https://github.com/rust-lang/rust/issues/33158 - ------------------------- - diff --git a/src/doc/unstable-book/src/language-features/unsized-locals.md b/src/doc/unstable-book/src/language-features/unsized-locals.md index 1165ab93a14..edc039f896b 100644 --- a/src/doc/unstable-book/src/language-features/unsized-locals.md +++ b/src/doc/unstable-book/src/language-features/unsized-locals.md @@ -8,7 +8,7 @@ The tracking issue for this feature is: [#48055] This implements [RFC1909]. When turned on, you can have unsized arguments and locals: -[RFC1909]: https://github.com/rust-lang/rfcs/blob/master/text/1909-coercions.md +[RFC1909]: https://github.com/rust-lang/rfcs/blob/master/text/1909-unsized-rvalues.md ```rust #![feature(unsized_locals)] diff --git a/src/etc/gdb_rust_pretty_printing.py b/src/etc/gdb_rust_pretty_printing.py index a376c8593f4..f02c7d87590 100755 --- a/src/etc/gdb_rust_pretty_printing.py +++ b/src/etc/gdb_rust_pretty_printing.py @@ -9,6 +9,7 @@ # except according to those terms. import gdb +import re import sys import debugger_pretty_printers_common as rustpp @@ -20,6 +21,16 @@ if sys.version_info[0] >= 3: rust_enabled = 'set language rust' in gdb.execute('complete set language ru', to_string = True) +# The btree pretty-printers fail in a confusing way unless +# https://sourceware.org/bugzilla/show_bug.cgi?id=21763 is fixed. +# This fix went in 8.1, so check for that. +# See https://github.com/rust-lang/rust/issues/56730 +gdb_81 = False +_match = re.match('([0-9]+)\\.([0-9]+)', gdb.VERSION) +if _match: + if int(_match.group(1)) > 8 or (int(_match.group(1)) == 8 and int(_match.group(2)) >= 1): + gdb_81 = True + #=============================================================================== # GDB Pretty Printing Module for Rust #=============================================================================== @@ -110,10 +121,10 @@ def rust_pretty_printer_lookup_function(gdb_val): if type_kind == rustpp.TYPE_KIND_STD_VECDEQUE: return RustStdVecDequePrinter(val) - if type_kind == rustpp.TYPE_KIND_STD_BTREESET: + if type_kind == rustpp.TYPE_KIND_STD_BTREESET and gdb_81: return RustStdBTreeSetPrinter(val) - if type_kind == rustpp.TYPE_KIND_STD_BTREEMAP: + if type_kind == rustpp.TYPE_KIND_STD_BTREEMAP and gdb_81: return RustStdBTreeMapPrinter(val) if type_kind == rustpp.TYPE_KIND_STD_STRING: diff --git a/src/grammar/parser-lalr.y b/src/grammar/parser-lalr.y index a7da69f65fa..8ea1cb26dc0 100644 --- a/src/grammar/parser-lalr.y +++ b/src/grammar/parser-lalr.y @@ -741,14 +741,14 @@ fn_anon_params ; fn_params_with_self -: '(' maybe_mut SELF maybe_ty_ascription maybe_comma_params ')' { $$ = mk_node("SelfValue", 3, $2, $4, $5); } +: '(' maybe_mut SELF maybe_ty_ascription maybe_comma_params ')' { $$ = mk_node("SelfLower", 3, $2, $4, $5); } | '(' '&' maybe_mut SELF maybe_ty_ascription maybe_comma_params ')' { $$ = mk_node("SelfRegion", 3, $3, $5, $6); } | '(' '&' lifetime maybe_mut SELF maybe_ty_ascription maybe_comma_params ')' { $$ = mk_node("SelfRegion", 4, $3, $4, $6, $7); } | '(' maybe_params ')' { $$ = mk_node("SelfStatic", 1, $2); } ; fn_anon_params_with_self -: '(' maybe_mut SELF maybe_ty_ascription maybe_comma_anon_params ')' { $$ = mk_node("SelfValue", 3, $2, $4, $5); } +: '(' maybe_mut SELF maybe_ty_ascription maybe_comma_anon_params ')' { $$ = mk_node("SelfLower", 3, $2, $4, $5); } | '(' '&' maybe_mut SELF maybe_ty_ascription maybe_comma_anon_params ')' { $$ = mk_node("SelfRegion", 3, $3, $5, $6); } | '(' '&' lifetime maybe_mut SELF maybe_ty_ascription maybe_comma_anon_params ')' { $$ = mk_node("SelfRegion", 4, $3, $4, $6, $7); } | '(' maybe_anon_params ')' { $$ = mk_node("SelfStatic", 1, $2); } diff --git a/src/liballoc/Cargo.toml b/src/liballoc/Cargo.toml index 642a43d4d9c..b2eb3566c04 100644 --- a/src/liballoc/Cargo.toml +++ b/src/liballoc/Cargo.toml @@ -11,10 +11,10 @@ path = "lib.rs" [dependencies] core = { path = "../libcore" } -compiler_builtins = { path = "../rustc/compiler_builtins_shim" } +compiler_builtins = { version = "0.1.0", features = ['rustc-dep-of-std'] } [dev-dependencies] -rand = "0.5" +rand = "0.6" [[test]] name = "collectionstests" @@ -28,3 +28,6 @@ path = "../liballoc/benches/lib.rs" name = "vec_deque_append_bench" path = "../liballoc/benches/vec_deque_append.rs" harness = false + +[features] +compiler-builtins-mem = ['compiler_builtins/mem'] diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index c3a84bf778d..f1581310b48 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -77,7 +77,9 @@ use core::iter::{Iterator, FromIterator, FusedIterator}; use core::marker::{Unpin, Unsize}; use core::mem; use core::pin::Pin; -use core::ops::{CoerceUnsized, DispatchFromDyn, Deref, DerefMut, Generator, GeneratorState}; +use core::ops::{ + CoerceUnsized, DispatchFromDyn, Deref, DerefMut, Receiver, Generator, GeneratorState +}; use core::ptr::{self, NonNull, Unique}; use core::task::{LocalWaker, Poll}; @@ -583,6 +585,9 @@ impl DerefMut for Box { } } +#[unstable(feature = "receiver_trait", issue = "0")] +impl Receiver for Box {} + #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for Box { type Item = I::Item; @@ -801,7 +806,7 @@ impl AsMut for Box { * safe.) * - It is in practice very useful to have Box be unconditionally * Unpin because of trait objects, for which the structural auto - * trait functionality does not apply (e.g. Box would + * trait functionality does not apply (e.g., Box would * otherwise not be Unpin). * * Another type with the same semantics as Box but only a conditional diff --git a/src/liballoc/collections/binary_heap.rs b/src/liballoc/collections/binary_heap.rs index 8c36962a299..5dd0ea7d431 100644 --- a/src/liballoc/collections/binary_heap.rs +++ b/src/liballoc/collections/binary_heap.rs @@ -858,7 +858,7 @@ impl BinaryHeap { } } -/// Hole represents a hole in a slice i.e. an index without valid value +/// Hole represents a hole in a slice i.e., an index without valid value /// (because it was moved from or duplicated). /// In drop, `Hole` will restore the slice by filling the hole /// position with the value that was originally removed. diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs index 215689dfc48..a2d2d3c74be 100644 --- a/src/liballoc/collections/btree/node.rs +++ b/src/liballoc/collections/btree/node.rs @@ -58,9 +58,34 @@ pub const CAPACITY: usize = 2 * B - 1; /// these should always be put behind pointers, and specifically behind `BoxedNode` in the owned /// case. /// -/// We put the metadata first so that its position is the same for every `K` and `V`, in order -/// to statically allocate a single dummy node to avoid allocations. This struct is `repr(C)` to -/// prevent them from being reordered. +/// We have a separate type for the header and rely on it matching the prefix of `LeafNode`, in +/// order to statically allocate a single dummy node to avoid allocations. This struct is +/// `repr(C)` to prevent them from being reordered. `LeafNode` does not just contain a +/// `NodeHeader` because we do not want unnecessary padding between `len` and the keys. +/// Crucially, `NodeHeader` can be safely transmuted to different K and V. (This is exploited +/// by `as_header`.) +/// See `into_key_slice` for an explanation of K2. K2 cannot be safely transmuted around +/// because the size of `NodeHeader` depends on its alignment! +#[repr(C)] +struct NodeHeader { + /// We use `*const` as opposed to `*mut` so as to be covariant in `K` and `V`. + /// This either points to an actual node or is null. + parent: *const InternalNode, + + /// This node's index into the parent node's `edges` array. + /// `*node.parent.edges[node.parent_idx]` should be the same thing as `node`. + /// This is only guaranteed to be initialized when `parent` is non-null. + parent_idx: MaybeUninit, + + /// The number of keys and values this node stores. + /// + /// This next to `parent_idx` to encourage the compiler to join `len` and + /// `parent_idx` into the same 32-bit word, reducing space overhead. + len: u16, + + /// See `into_key_slice`. + keys_start: [K2; 0], +} #[repr(C)] struct LeafNode { /// We use `*const` as opposed to `*mut` so as to be covariant in `K` and `V`. @@ -98,24 +123,25 @@ impl LeafNode { len: 0 } } +} +impl NodeHeader { fn is_shared_root(&self) -> bool { ptr::eq(self, &EMPTY_ROOT_NODE as *const _ as *const _) } } // We need to implement Sync here in order to make a static instance. -unsafe impl Sync for LeafNode<(), ()> {} +unsafe impl Sync for NodeHeader<(), ()> {} // An empty node used as a placeholder for the root node, to avoid allocations. -// We use () in order to save space, since no operation on an empty tree will +// We use just a header in order to save space, since no operation on an empty tree will // ever take a pointer past the first key. -static EMPTY_ROOT_NODE: LeafNode<(), ()> = LeafNode { +static EMPTY_ROOT_NODE: NodeHeader<(), ()> = NodeHeader { parent: ptr::null(), parent_idx: MaybeUninit::uninitialized(), len: 0, - keys: MaybeUninit::uninitialized(), - vals: MaybeUninit::uninitialized(), + keys_start: [], }; /// The underlying representation of internal nodes. As with `LeafNode`s, these should be hidden @@ -281,7 +307,7 @@ impl Root { .node) }; self.height -= 1; - self.as_mut().as_leaf_mut().parent = ptr::null(); + unsafe { (*self.as_mut().as_leaf_mut()).parent = ptr::null(); } unsafe { Global.dealloc(NonNull::from(top).cast(), Layout::new::>()); @@ -306,6 +332,11 @@ impl Root { /// `Leaf`, the `NodeRef` points to a leaf node, when this is `Internal` the /// `NodeRef` points to an internal node, and when this is `LeafOrInternal` the /// `NodeRef` could be pointing to either type of node. +/// Note that in case of a leaf node, this might still be the shared root! Only turn +/// this into a `LeafNode` reference if you know it is not a root! Shared references +/// must be dereferencable *for the entire size of their pointee*, so `&InternalNode` +/// pointing to the shared root is UB. +/// Turning this into a `NodeHeader` is always safe. pub struct NodeRef { height: usize, node: NonNull>, @@ -352,7 +383,7 @@ impl NodeRef { /// Finds the length of the node. This is the number of keys or values. In an /// internal node, the number of edges is `len() + 1`. pub fn len(&self) -> usize { - self.as_leaf().len as usize + self.as_header().len as usize } /// Returns the height of this node in the whole tree. Zero height denotes the @@ -382,14 +413,19 @@ impl NodeRef { } } - fn as_leaf(&self) -> &LeafNode { + /// Assert that this is indeed a proper leaf node, and not the shared root. + unsafe fn as_leaf(&self) -> &LeafNode { + self.node.as_ref() + } + + fn as_header(&self) -> &NodeHeader { unsafe { - self.node.as_ref() + &*(self.node.as_ptr() as *const NodeHeader) } } pub fn is_shared_root(&self) -> bool { - self.as_leaf().is_shared_root() + self.as_header().is_shared_root() } pub fn keys(&self) -> &[K] { @@ -418,7 +454,7 @@ impl NodeRef { >, Self > { - let parent_as_leaf = self.as_leaf().parent as *const LeafNode; + let parent_as_leaf = self.as_header().parent as *const LeafNode; if let Some(non_zero) = NonNull::new(parent_as_leaf as *mut _) { Ok(Handle { node: NodeRef { @@ -427,7 +463,7 @@ impl NodeRef { root: self.root, _marker: PhantomData }, - idx: unsafe { usize::from(*self.as_leaf().parent_idx.get_ref()) }, + idx: unsafe { usize::from(*self.as_header().parent_idx.get_ref()) }, _marker: PhantomData }) } else { @@ -534,10 +570,10 @@ impl<'a, K, V, Type> NodeRef, K, V, Type> { } } - fn as_leaf_mut(&mut self) -> &mut LeafNode { - unsafe { - self.node.as_mut() - } + /// Returns a raw ptr to avoid asserting exclusive access to the entire node. + fn as_leaf_mut(&mut self) -> *mut LeafNode { + // We are mutable, so we cannot be the root, so accessing this as a leaf is okay. + self.node.as_ptr() } fn keys_mut(&mut self) -> &mut [K] { @@ -551,28 +587,50 @@ impl<'a, K, V, Type> NodeRef, K, V, Type> { impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { fn into_key_slice(self) -> &'a [K] { - // When taking a pointer to the keys, if our key has a stricter - // alignment requirement than the shared root does, then the pointer - // would be out of bounds, which LLVM assumes will not happen. If the - // alignment is more strict, we need to make an empty slice that doesn't - // use an out of bounds pointer. + // We have to be careful here because we might be pointing to the shared root. + // In that case, we must not create an `&LeafNode`. We could just return + // an empty slice whenever the length is 0 (this includes the shared root), + // but we want to avoid that run-time check. + // Instead, we create a slice pointing into the node whenever possible. + // We can sometimes do this even for the shared root, as the slice will be + // empty. We cannot *always* do this because if the type is too highly + // aligned, the offset of `keys` in a "full node" might be outside the bounds + // of the header! So we do an alignment check first, that will be + // evaluated at compile-time, and only do any run-time check in the rare case + // that the alignment is very big. if mem::align_of::() > mem::align_of::>() && self.is_shared_root() { &[] } else { - // Here either it's not the root, or the alignment is less strict, - // in which case the keys pointer will point "one-past-the-end" of - // the node, which is allowed by LLVM. + // Thanks to the alignment check above, we know that `keys` will be + // in-bounds of some allocation even if this is the shared root! + // (We might be one-past-the-end, but that is allowed by LLVM.) + // Getting the pointer is tricky though. `NodeHeader` does not have a `keys` + // field because we want its size to not depend on the alignment of `K` + // (needed becuase `as_header` should be safe). We cannot call `as_leaf` + // because we might be the shared root. + // For this reason, `NodeHeader` has this `K2` parameter (that's usually `()` + // and hence just adds a size-0-align-1 field, not affecting layout). + // We know that we can transmute `NodeHeader` to `NodeHeader` + // because we did the alignment check above, and hence `NodeHeader` + // is not bigger than `NodeHeader`! Then we can use `NodeHeader` + // to compute the pointer where the keys start. + // This entire hack will become unnecessary once + // lands, then we can just take a raw + // pointer to the `keys` field of `*const InternalNode`. + + // This is a non-debug-assert because it can be completely compile-time evaluated. + assert!(mem::size_of::>() == mem::size_of::>()); + let header = self.as_header() as *const _ as *const NodeHeader; + let keys = unsafe { &(*header).keys_start as *const _ as *const K }; unsafe { - slice::from_raw_parts( - self.as_leaf().keys.as_ptr() as *const K, - self.len() - ) + slice::from_raw_parts(keys, self.len()) } } } fn into_val_slice(self) -> &'a [V] { debug_assert!(!self.is_shared_root()); + // We cannot be the root, so `as_leaf` is okay unsafe { slice::from_raw_parts( self.as_leaf().vals.as_ptr() as *const V, @@ -602,7 +660,7 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { } else { unsafe { slice::from_raw_parts_mut( - self.as_leaf_mut().keys.as_mut_ptr() as *mut K, + (*self.as_leaf_mut()).keys.as_mut_ptr() as *mut K, self.len() ) } @@ -613,7 +671,7 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { debug_assert!(!self.is_shared_root()); unsafe { slice::from_raw_parts_mut( - self.as_leaf_mut().vals.as_mut_ptr() as *mut V, + (*self.as_leaf_mut()).vals.as_mut_ptr() as *mut V, self.len() ) } @@ -637,9 +695,9 @@ impl<'a, K, V> NodeRef, K, V, marker::Leaf> { unsafe { ptr::write(self.keys_mut().get_unchecked_mut(idx), key); ptr::write(self.vals_mut().get_unchecked_mut(idx), val); - } - self.as_leaf_mut().len += 1; + (*self.as_leaf_mut()).len += 1; + } } /// Adds a key/value pair to the beginning of the node. @@ -651,9 +709,9 @@ impl<'a, K, V> NodeRef, K, V, marker::Leaf> { unsafe { slice_insert(self.keys_mut(), 0, key); slice_insert(self.vals_mut(), 0, val); - } - self.as_leaf_mut().len += 1; + (*self.as_leaf_mut()).len += 1; + } } } @@ -672,7 +730,7 @@ impl<'a, K, V> NodeRef, K, V, marker::Internal> { ptr::write(self.vals_mut().get_unchecked_mut(idx), val); ptr::write(self.as_internal_mut().edges.get_unchecked_mut(idx + 1), edge.node); - self.as_leaf_mut().len += 1; + (*self.as_leaf_mut()).len += 1; Handle::new_edge(self.reborrow_mut(), idx + 1).correct_parent_link(); } @@ -708,7 +766,7 @@ impl<'a, K, V> NodeRef, K, V, marker::Internal> { edge.node ); - self.as_leaf_mut().len += 1; + (*self.as_leaf_mut()).len += 1; self.correct_all_childrens_parent_links(); } @@ -732,12 +790,12 @@ impl<'a, K, V> NodeRef, K, V, marker::LeafOrInternal> { ForceResult::Internal(internal) => { let edge = ptr::read(internal.as_internal().edges.get_unchecked(idx + 1)); let mut new_root = Root { node: edge, height: internal.height - 1 }; - new_root.as_mut().as_leaf_mut().parent = ptr::null(); + (*new_root.as_mut().as_leaf_mut()).parent = ptr::null(); Some(new_root) } }; - self.as_leaf_mut().len -= 1; + (*self.as_leaf_mut()).len -= 1; (key, val, edge) } } @@ -765,7 +823,7 @@ impl<'a, K, V> NodeRef, K, V, marker::LeafOrInternal> { ); let mut new_root = Root { node: edge, height: internal.height - 1 }; - new_root.as_mut().as_leaf_mut().parent = ptr::null(); + (*new_root.as_mut().as_leaf_mut()).parent = ptr::null(); for i in 0..old_len { Handle::new_edge(internal.reborrow_mut(), i).correct_parent_link(); @@ -775,7 +833,7 @@ impl<'a, K, V> NodeRef, K, V, marker::LeafOrInternal> { } }; - self.as_leaf_mut().len -= 1; + (*self.as_leaf_mut()).len -= 1; (key, val, edge) } @@ -966,7 +1024,7 @@ impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::Edge slice_insert(self.node.keys_mut(), self.idx, key); slice_insert(self.node.vals_mut(), self.idx, val); - self.node.as_leaf_mut().len += 1; + (*self.node.as_leaf_mut()).len += 1; self.node.vals_mut().get_unchecked_mut(self.idx) } @@ -1009,8 +1067,10 @@ impl<'a, K, V> Handle, K, V, marker::Internal>, marker:: let idx = self.idx as u16; let ptr = self.node.as_internal_mut() as *mut _; let mut child = self.descend(); - child.as_leaf_mut().parent = ptr; - child.as_leaf_mut().parent_idx.set(idx); + unsafe { + (*child.as_leaf_mut()).parent = ptr; + (*child.as_leaf_mut()).parent_idx.set(idx); + } } /// Unsafely asserts to the compiler some static information about whether the underlying @@ -1158,7 +1218,7 @@ impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::KV> new_len ); - self.node.as_leaf_mut().len = self.idx as u16; + (*self.node.as_leaf_mut()).len = self.idx as u16; new_node.len = new_len as u16; ( @@ -1180,7 +1240,7 @@ impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::KV> unsafe { let k = slice_remove(self.node.keys_mut(), self.idx); let v = slice_remove(self.node.vals_mut(), self.idx); - self.node.as_leaf_mut().len -= 1; + (*self.node.as_leaf_mut()).len -= 1; (self.left_edge(), k, v) } } @@ -1221,7 +1281,7 @@ impl<'a, K, V> Handle, K, V, marker::Internal>, marker:: new_len + 1 ); - self.node.as_leaf_mut().len = self.idx as u16; + (*self.node.as_leaf_mut()).len = self.idx as u16; new_node.data.len = new_len as u16; let mut new_root = Root { @@ -1295,9 +1355,9 @@ impl<'a, K, V> Handle, K, V, marker::Internal>, marker:: for i in self.idx+1..self.node.len() { Handle::new_edge(self.node.reborrow_mut(), i).correct_parent_link(); } - self.node.as_leaf_mut().len -= 1; + (*self.node.as_leaf_mut()).len -= 1; - left_node.as_leaf_mut().len += right_len as u16 + 1; + (*left_node.as_leaf_mut()).len += right_len as u16 + 1; if self.node.height > 1 { ptr::copy_nonoverlapping( @@ -1407,8 +1467,8 @@ impl<'a, K, V> Handle, K, V, marker::Internal>, marker:: move_kv(left_kv, new_left_len, parent_kv, 0, 1); } - left_node.reborrow_mut().as_leaf_mut().len -= count as u16; - right_node.reborrow_mut().as_leaf_mut().len += count as u16; + (*left_node.reborrow_mut().as_leaf_mut()).len -= count as u16; + (*right_node.reborrow_mut().as_leaf_mut()).len += count as u16; match (left_node.force(), right_node.force()) { (ForceResult::Internal(left), ForceResult::Internal(mut right)) => { @@ -1468,8 +1528,8 @@ impl<'a, K, V> Handle, K, V, marker::Internal>, marker:: new_right_len); } - left_node.reborrow_mut().as_leaf_mut().len += count as u16; - right_node.reborrow_mut().as_leaf_mut().len -= count as u16; + (*left_node.reborrow_mut().as_leaf_mut()).len += count as u16; + (*right_node.reborrow_mut().as_leaf_mut()).len -= count as u16; match (left_node.force(), right_node.force()) { (ForceResult::Internal(left), ForceResult::Internal(mut right)) => { @@ -1560,8 +1620,8 @@ impl<'a, K, V> Handle, K, V, marker::LeafOrInternal>, ma move_kv(left_kv, left_new_len, right_kv, 0, right_new_len); - left_node.reborrow_mut().as_leaf_mut().len = left_new_len as u16; - right_node.reborrow_mut().as_leaf_mut().len = right_new_len as u16; + (*left_node.reborrow_mut().as_leaf_mut()).len = left_new_len as u16; + (*right_node.reborrow_mut().as_leaf_mut()).len = right_new_len as u16; match (left_node.force(), right_node.force()) { (ForceResult::Internal(left), ForceResult::Internal(right)) => { diff --git a/src/liballoc/collections/btree/set.rs b/src/liballoc/collections/btree/set.rs index af9a7074e4a..fa74dce2f1f 100644 --- a/src/liballoc/collections/btree/set.rs +++ b/src/liballoc/collections/btree/set.rs @@ -258,7 +258,7 @@ impl BTreeSet { } /// Visits the values representing the difference, - /// i.e. the values that are in `self` but not in `other`, + /// i.e., the values that are in `self` but not in `other`, /// in ascending order. /// /// # Examples @@ -286,7 +286,7 @@ impl BTreeSet { } /// Visits the values representing the symmetric difference, - /// i.e. the values that are in `self` or in `other` but not in both, + /// i.e., the values that are in `self` or in `other` but not in both, /// in ascending order. /// /// # Examples @@ -316,7 +316,7 @@ impl BTreeSet { } /// Visits the values representing the intersection, - /// i.e. the values that are both in `self` and `other`, + /// i.e., the values that are both in `self` and `other`, /// in ascending order. /// /// # Examples @@ -344,7 +344,7 @@ impl BTreeSet { } /// Visits the values representing the union, - /// i.e. all the values in `self` or `other`, without duplicates, + /// i.e., all the values in `self` or `other`, without duplicates, /// in ascending order. /// /// # Examples @@ -455,7 +455,7 @@ impl BTreeSet { } /// Returns `true` if the set is a subset of another, - /// i.e. `other` contains at least all the values in `self`. + /// i.e., `other` contains at least all the values in `self`. /// /// # Examples /// @@ -498,7 +498,7 @@ impl BTreeSet { } /// Returns `true` if the set is a superset of another, - /// i.e. `self` contains at least all the values in `other`. + /// i.e., `self` contains at least all the values in `other`. /// /// # Examples /// diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs index 2ef84dbade0..ba46fafaf16 100644 --- a/src/liballoc/collections/linked_list.rs +++ b/src/liballoc/collections/linked_list.rs @@ -627,7 +627,9 @@ impl LinkedList { self.pop_front_node().map(Node::into_element) } - /// Appends an element to the back of a list + /// Appends an element to the back of a list. + /// + /// This operation should compute in O(1) time. /// /// # Examples /// @@ -647,6 +649,8 @@ impl LinkedList { /// Removes the last element from a list and returns it, or `None` if /// it is empty. /// + /// This operation should compute in O(1) time. + /// /// # Examples /// /// ``` diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index c8ee40f3d27..553c6d7291a 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -1026,7 +1026,10 @@ impl VecDeque { iter: Iter { tail: drain_tail, head: drain_head, - ring: unsafe { self.buffer_as_mut_slice() }, + // Crucially, we only create shared references from `self` here and read from + // it. We do not write to `self` nor reborrow to a mutable reference. + // Hence the raw pointer we created above, for `deque`, remains valid. + ring: unsafe { self.buffer_as_slice() }, }, } } @@ -1894,8 +1897,6 @@ impl VecDeque { /// # Examples /// /// ``` - /// #![feature(vec_resize_with)] - /// /// use std::collections::VecDeque; /// /// let mut buf = VecDeque::new(); @@ -1914,7 +1915,7 @@ impl VecDeque { /// buf.resize_with(5, || { state += 1; state }); /// assert_eq!(buf, [5, 10, 101, 102, 103]); /// ``` - #[unstable(feature = "vec_resize_with", issue = "41758")] + #[stable(feature = "vec_resize_with", since = "1.33.0")] pub fn resize_with(&mut self, new_len: usize, generator: impl FnMut()->T) { let len = self.len(); @@ -1924,6 +1925,118 @@ impl VecDeque { self.truncate(new_len); } } + + /// Rotates the double-ended queue `mid` places to the left. + /// + /// Equivalently, + /// - Rotates item `mid` into the first position. + /// - Pops the first `mid` items and pushes them to the end. + /// - Rotates `len() - mid` places to the right. + /// + /// # Panics + /// + /// If `mid` is greater than `len()`. Note that `mid == len()` + /// does _not_ panic and is a no-op rotation. + /// + /// # Complexity + /// + /// Takes `O(min(mid, len() - mid))` time and no extra space. + /// + /// # Examples + /// + /// ``` + /// #![feature(vecdeque_rotate)] + /// + /// use std::collections::VecDeque; + /// + /// let mut buf: VecDeque<_> = (0..10).collect(); + /// + /// buf.rotate_left(3); + /// assert_eq!(buf, [3, 4, 5, 6, 7, 8, 9, 0, 1, 2]); + /// + /// for i in 1..10 { + /// assert_eq!(i * 3 % 10, buf[0]); + /// buf.rotate_left(3); + /// } + /// assert_eq!(buf, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + /// ``` + #[unstable(feature = "vecdeque_rotate", issue = "56686")] + pub fn rotate_left(&mut self, mid: usize) { + assert!(mid <= self.len()); + let k = self.len() - mid; + if mid <= k { + unsafe { self.rotate_left_inner(mid) } + } else { + unsafe { self.rotate_right_inner(k) } + } + } + + /// Rotates the double-ended queue `k` places to the right. + /// + /// Equivalently, + /// - Rotates the first item into position `k`. + /// - Pops the last `k` items and pushes them to the front. + /// - Rotates `len() - k` places to the left. + /// + /// # Panics + /// + /// If `k` is greater than `len()`. Note that `k == len()` + /// does _not_ panic and is a no-op rotation. + /// + /// # Complexity + /// + /// Takes `O(min(k, len() - k))` time and no extra space. + /// + /// # Examples + /// + /// ``` + /// #![feature(vecdeque_rotate)] + /// + /// use std::collections::VecDeque; + /// + /// let mut buf: VecDeque<_> = (0..10).collect(); + /// + /// buf.rotate_right(3); + /// assert_eq!(buf, [7, 8, 9, 0, 1, 2, 3, 4, 5, 6]); + /// + /// for i in 1..10 { + /// assert_eq!(0, buf[i * 3 % 10]); + /// buf.rotate_right(3); + /// } + /// assert_eq!(buf, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + /// ``` + #[unstable(feature = "vecdeque_rotate", issue = "56686")] + pub fn rotate_right(&mut self, k: usize) { + assert!(k <= self.len()); + let mid = self.len() - k; + if k <= mid { + unsafe { self.rotate_right_inner(k) } + } else { + unsafe { self.rotate_left_inner(mid) } + } + } + + // Safety: the following two methods require that the rotation amount + // be less than half the length of the deque. + // + // `wrap_copy` requres that `min(x, cap() - x) + copy_len <= cap()`, + // but than `min` is never more than half the capacity, regardless of x, + // so it's sound to call here because we're calling with something + // less than half the length, which is never above half the capacity. + + unsafe fn rotate_left_inner(&mut self, mid: usize) { + debug_assert!(mid * 2 <= self.len()); + self.wrap_copy(self.head, self.tail, mid); + self.head = self.wrap_add(self.head, mid); + self.tail = self.wrap_add(self.tail, mid); + } + + unsafe fn rotate_right_inner(&mut self, k: usize) { + debug_assert!(k * 2 <= self.len()); + self.head = self.wrap_sub(self.head, k); + self.tail = self.wrap_sub(self.tail, k); + self.wrap_copy(self.tail, self.head, k); + } } impl VecDeque { @@ -2795,7 +2908,7 @@ mod tests { // 0, 1, 2, .., len - 1 let expected = (0..).take(len).collect::>(); for tail_pos in 0..cap { - for to_remove in 0..len + 1 { + for to_remove in 0..=len { tester.tail = tail_pos; tester.head = tail_pos; for i in 0..len { @@ -2821,10 +2934,10 @@ mod tests { let mut tester: VecDeque = VecDeque::with_capacity(7); let cap = tester.capacity(); - for len in 0..cap + 1 { - for tail in 0..cap + 1 { - for drain_start in 0..len + 1 { - for drain_end in drain_start..len + 1 { + for len in 0..=cap { + for tail in 0..=cap { + for drain_start in 0..=len { + for drain_end in drain_start..=len { tester.tail = tail; tester.head = tail; for i in 0..len { @@ -2866,10 +2979,10 @@ mod tests { tester.reserve(63); let max_cap = tester.capacity(); - for len in 0..cap + 1 { + for len in 0..=cap { // 0, 1, 2, .., len - 1 let expected = (0..).take(len).collect::>(); - for tail_pos in 0..max_cap + 1 { + for tail_pos in 0..=max_cap { tester.tail = tail_pos; tester.head = tail_pos; tester.reserve(63); @@ -2899,7 +3012,7 @@ mod tests { // len is the length *before* splitting for len in 0..cap { // index to split at - for at in 0..len + 1 { + for at in 0..=len { // 0, 1, 2, .., at - 1 (may be empty) let expected_self = (0..).take(at).collect::>(); // at, at + 1, .., len - 1 (may be empty) @@ -2927,7 +3040,7 @@ mod tests { fn test_from_vec() { use vec::Vec; for cap in 0..35 { - for len in 0..cap + 1 { + for len in 0..=cap { let mut vec = Vec::with_capacity(cap); vec.extend(0..len); diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index abacc62c856..afa7a6f919d 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -72,6 +72,8 @@ test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))] #![no_std] #![needs_allocator] + +#![deny(intra_doc_link_resolution_failure)] #![deny(missing_debug_implementations)] #![cfg_attr(not(test), feature(fn_traits))] @@ -104,6 +106,7 @@ #![feature(ptr_internals)] #![feature(ptr_offset_from)] #![feature(rustc_attrs)] +#![feature(receiver_trait)] #![feature(specialization)] #![feature(split_ascii_whitespace)] #![feature(staged_api)] diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index e87bf78561c..f4674b32769 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -739,7 +739,7 @@ unsafe impl<#[may_dangle] T, A: Alloc> Drop for RawVec { // On 64-bit we just need to check for overflow since trying to allocate // `> isize::MAX` bytes will surely fail. On 32-bit and 16-bit we need to add // an extra guard for this in case we're running on a platform which can use -// all 4GB in user-space. e.g. PAE or x32 +// all 4GB in user-space. e.g., PAE or x32 #[inline] fn alloc_guard(alloc_size: usize) -> Result<(), CollectionAllocErr> { diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 3ca6de191de..65a610b9d1e 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -253,7 +253,7 @@ use core::intrinsics::abort; use core::marker; use core::marker::{Unpin, Unsize, PhantomData}; use core::mem::{self, align_of_val, forget, size_of_val}; -use core::ops::Deref; +use core::ops::{Deref, Receiver}; use core::ops::{CoerceUnsized, DispatchFromDyn}; use core::pin::Pin; use core::ptr::{self, NonNull}; @@ -276,7 +276,7 @@ struct RcBox { /// See the [module-level documentation](./index.html) for more details. /// /// The inherent methods of `Rc` are all associated functions, which means -/// that you have to call them as e.g. [`Rc::get_mut(&mut value)`][get_mut] instead of +/// that you have to call them as e.g., [`Rc::get_mut(&mut value)`][get_mut] instead of /// `value.get_mut()`. This avoids conflicts with methods of the inner /// type `T`. /// @@ -813,6 +813,9 @@ impl Deref for Rc { } } +#[unstable(feature = "receiver_trait", issue = "0")] +impl Receiver for Rc {} + #[stable(feature = "rust1", since = "1.0.0")] unsafe impl<#[may_dangle] T: ?Sized> Drop for Rc { /// Drops the `Rc`. @@ -840,6 +843,8 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Rc { /// drop(foo); // Doesn't print anything /// drop(foo2); // Prints "dropped!" /// ``` + /// + /// [`Weak`]: ../../std/rc/struct.Weak.html fn drop(&mut self) { unsafe { self.dec_strong(); @@ -900,12 +905,47 @@ impl Default for Rc { } } +#[stable(feature = "rust1", since = "1.0.0")] +trait RcEqIdent { + fn eq(&self, other: &Rc) -> bool; + fn ne(&self, other: &Rc) -> bool; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl RcEqIdent for Rc { + #[inline] + default fn eq(&self, other: &Rc) -> bool { + **self == **other + } + + #[inline] + default fn ne(&self, other: &Rc) -> bool { + **self != **other + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl RcEqIdent for Rc { + #[inline] + fn eq(&self, other: &Rc) -> bool { + Rc::ptr_eq(self, other) || **self == **other + } + + #[inline] + fn ne(&self, other: &Rc) -> bool { + !Rc::ptr_eq(self, other) && **self != **other + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for Rc { /// Equality for two `Rc`s. /// /// Two `Rc`s are equal if their inner values are equal. /// + /// If `T` also implements `Eq`, two `Rc`s that point to the same value are + /// always equal. + /// /// # Examples /// /// ``` @@ -915,15 +955,18 @@ impl PartialEq for Rc { /// /// assert!(five == Rc::new(5)); /// ``` - #[inline(always)] + #[inline] fn eq(&self, other: &Rc) -> bool { - **self == **other + RcEqIdent::eq(self, other) } /// Inequality for two `Rc`s. /// /// Two `Rc`s are unequal if their inner values are unequal. /// + /// If `T` also implements `Eq`, two `Rc`s that point to the same value are + /// never unequal. + /// /// # Examples /// /// ``` @@ -933,9 +976,9 @@ impl PartialEq for Rc { /// /// assert!(five != Rc::new(6)); /// ``` - #[inline(always)] + #[inline] fn ne(&self, other: &Rc) -> bool { - **self != **other + RcEqIdent::ne(self, other) } } @@ -1187,8 +1230,9 @@ impl, U: ?Sized> DispatchFromDyn> for Weak {} impl Weak { /// Constructs a new `Weak`, without allocating any memory. - /// Calling [`upgrade`][Weak::upgrade] on the return value always gives [`None`]. + /// Calling [`upgrade`] on the return value always gives [`None`]. /// + /// [`upgrade`]: #method.upgrade /// [`None`]: ../../std/option/enum.Option.html /// /// # Examples @@ -1251,7 +1295,7 @@ impl Weak { } /// Return `None` when the pointer is dangling and there is no allocated `RcBox`, - /// i.e. this `Weak` was created by `Weak::new` + /// i.e., this `Weak` was created by `Weak::new` #[inline] fn inner(&self) -> Option<&RcBox> { if is_dangling(self.ptr) { @@ -1260,6 +1304,52 @@ impl Weak { Some(unsafe { self.ptr.as_ref() }) } } + + /// Returns true if the two `Weak`s point to the same value (not just values + /// that compare as equal). + /// + /// # Notes + /// + /// Since this compares pointers it means that `Weak::new()` will equal each + /// other, even though they don't point to any value. + /// + /// # Examples + /// + /// ``` + /// #![feature(weak_ptr_eq)] + /// use std::rc::{Rc, Weak}; + /// + /// let first_rc = Rc::new(5); + /// let first = Rc::downgrade(&first_rc); + /// let second = Rc::downgrade(&first_rc); + /// + /// assert!(Weak::ptr_eq(&first, &second)); + /// + /// let third_rc = Rc::new(5); + /// let third = Rc::downgrade(&third_rc); + /// + /// assert!(!Weak::ptr_eq(&first, &third)); + /// ``` + /// + /// Comparing `Weak::new`. + /// + /// ``` + /// #![feature(weak_ptr_eq)] + /// use std::rc::{Rc, Weak}; + /// + /// let first = Weak::new(); + /// let second = Weak::new(); + /// assert!(Weak::ptr_eq(&first, &second)); + /// + /// let third_rc = Rc::new(()); + /// let third = Rc::downgrade(&third_rc); + /// assert!(!Weak::ptr_eq(&first, &third)); + /// ``` + #[inline] + #[unstable(feature = "weak_ptr_eq", issue = "55981")] + pub fn ptr_eq(this: &Self, other: &Self) -> bool { + this.ptr.as_ptr() == other.ptr.as_ptr() + } } #[stable(feature = "rc_weak", since = "1.4.0")] @@ -1334,9 +1424,10 @@ impl fmt::Debug for Weak { #[stable(feature = "downgraded_weak", since = "1.10.0")] impl Default for Weak { /// Constructs a new `Weak`, allocating memory for `T` without initializing - /// it. Calling [`upgrade`][Weak::upgrade] on the return value always gives [`None`]. + /// it. Calling [`upgrade`] on the return value always gives [`None`]. /// /// [`None`]: ../../std/option/enum.Option.html + /// [`upgrade`]: ../../std/rc/struct.Weak.html#method.upgrade /// /// # Examples /// diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 22da9dd6e96..510b4b06e40 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -177,7 +177,7 @@ mod hack { impl [T] { /// Sorts the slice. /// - /// This sort is stable (i.e. does not reorder equal elements) and `O(n log n)` worst-case. + /// This sort is stable (i.e., does not reorder equal elements) and `O(n log n)` worst-case. /// /// When applicable, unstable sorting is preferred because it is generally faster than stable /// sorting and it doesn't allocate auxiliary memory. @@ -211,7 +211,7 @@ impl [T] { /// Sorts the slice with a comparator function. /// - /// This sort is stable (i.e. does not reorder equal elements) and `O(n log n)` worst-case. + /// This sort is stable (i.e., does not reorder equal elements) and `O(n log n)` worst-case. /// /// The comparator function must define a total ordering for the elements in the slice. If /// the ordering is not total, the order of the elements is unspecified. An order is a @@ -264,7 +264,7 @@ impl [T] { /// Sorts the slice with a key extraction function. /// - /// This sort is stable (i.e. does not reorder equal elements) and `O(m n log(m n))` + /// This sort is stable (i.e., does not reorder equal elements) and `O(m n log(m n))` /// worst-case, where the key function is `O(m)`. /// /// When applicable, unstable sorting is preferred because it is generally faster than stable @@ -301,10 +301,10 @@ impl [T] { /// /// During sorting, the key function is called only once per element. /// - /// This sort is stable (i.e. does not reorder equal elements) and `O(m n + n log n)` + /// This sort is stable (i.e., does not reorder equal elements) and `O(m n + n log n)` /// worst-case, where the key function is `O(m)`. /// - /// For simple key functions (e.g. functions that are property accesses or + /// For simple key functions (e.g., functions that are property accesses or /// basic operations), [`sort_by_key`](#method.sort_by_key) is likely to be /// faster. /// @@ -589,7 +589,7 @@ impl> SliceConcatExt for [V] { type Output = Vec; fn concat(&self) -> Vec { - let size = self.iter().fold(0, |acc, v| acc + v.borrow().len()); + let size = self.iter().map(|slice| slice.borrow().len()).sum(); let mut result = Vec::with_capacity(size); for v in self { result.extend_from_slice(v.borrow()) @@ -603,8 +603,8 @@ impl> SliceConcatExt for [V] { Some(first) => first, None => return vec![], }; - let size = self.iter().fold(0, |acc, v| acc + v.borrow().len()); - let mut result = Vec::with_capacity(size + self.len()); + let size = self.iter().map(|slice| slice.borrow().len()).sum::() + self.len() - 1; + let mut result = Vec::with_capacity(size); result.extend_from_slice(first.borrow()); for v in iter { diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 662f8ae614f..4652c0e7efa 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -577,7 +577,7 @@ impl String { return Cow::Borrowed(""); }; - const REPLACEMENT: &'static str = "\u{FFFD}"; + const REPLACEMENT: &str = "\u{FFFD}"; let mut res = String::with_capacity(v.len()); res.push_str(first_valid); @@ -1732,18 +1732,37 @@ impl<'a> FromIterator<&'a str> for String { #[stable(feature = "extend_string", since = "1.4.0")] impl FromIterator for String { fn from_iter>(iter: I) -> String { - let mut buf = String::new(); - buf.extend(iter); - buf + let mut iterator = iter.into_iter(); + + // Because we're iterating over `String`s, we can avoid at least + // one allocation by getting the first string from the iterator + // and appending to it all the subsequent strings. + match iterator.next() { + None => String::new(), + Some(mut buf) => { + buf.extend(iterator); + buf + } + } } } #[stable(feature = "herd_cows", since = "1.19.0")] impl<'a> FromIterator> for String { fn from_iter>>(iter: I) -> String { - let mut buf = String::new(); - buf.extend(iter); - buf + let mut iterator = iter.into_iter(); + + // Because we're iterating over CoWs, we can (potentially) avoid at least + // one allocation by getting the first item and appending to it all the + // subsequent items. + match iterator.next() { + None => String::new(), + Some(cow) => { + let mut buf = cow.into_owned(); + buf.extend(iterator); + buf + } + } } } @@ -1753,9 +1772,7 @@ impl Extend for String { let iterator = iter.into_iter(); let (lower_bound, _) = iterator.size_hint(); self.reserve(lower_bound); - for ch in iterator { - self.push(ch) - } + iterator.for_each(move |c| self.push(c)); } } @@ -1769,27 +1786,21 @@ impl<'a> Extend<&'a char> for String { #[stable(feature = "rust1", since = "1.0.0")] impl<'a> Extend<&'a str> for String { fn extend>(&mut self, iter: I) { - for s in iter { - self.push_str(s) - } + iter.into_iter().for_each(move |s| self.push_str(s)); } } #[stable(feature = "extend_string", since = "1.4.0")] impl Extend for String { fn extend>(&mut self, iter: I) { - for s in iter { - self.push_str(&s) - } + iter.into_iter().for_each(move |s| self.push_str(&s)); } } #[stable(feature = "herd_cows", since = "1.19.0")] impl<'a> Extend> for String { fn extend>>(&mut self, iter: I) { - for s in iter { - self.push_str(&s) - } + iter.into_iter().for_each(move |s| self.push_str(&s)); } } @@ -2158,7 +2169,7 @@ impl ToString for T { use core::fmt::Write; let mut buf = String::new(); buf.write_fmt(format_args!("{}", self)) - .expect("a Display implementation return an error unexpectedly"); + .expect("a Display implementation returned an error unexpectedly"); buf.shrink_to_fit(); buf } diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 4f4031e3c4e..948c36117a3 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -24,7 +24,7 @@ use core::fmt; use core::cmp::Ordering; use core::intrinsics::abort; use core::mem::{self, align_of_val, size_of_val}; -use core::ops::Deref; +use core::ops::{Deref, Receiver}; use core::ops::{CoerceUnsized, DispatchFromDyn}; use core::pin::Pin; use core::ptr::{self, NonNull}; @@ -767,6 +767,9 @@ impl Deref for Arc { } } +#[unstable(feature = "receiver_trait", issue = "0")] +impl Receiver for Arc {} + impl Arc { /// Makes a mutable reference into the given `Arc`. /// @@ -952,6 +955,8 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Arc { /// drop(foo); // Doesn't print anything /// drop(foo2); // Prints "dropped!" /// ``` + /// + /// [`Weak`]: ../../std/sync/struct.Weak.html #[inline] fn drop(&mut self) { // Because `fetch_sub` is already atomic, we do not need to synchronize @@ -1121,7 +1126,7 @@ impl Weak { } /// Return `None` when the pointer is dangling and there is no allocated `ArcInner`, - /// i.e. this `Weak` was created by `Weak::new` + /// i.e., this `Weak` was created by `Weak::new` #[inline] fn inner(&self) -> Option<&ArcInner> { if is_dangling(self.ptr) { @@ -1130,6 +1135,53 @@ impl Weak { Some(unsafe { self.ptr.as_ref() }) } } + + /// Returns true if the two `Weak`s point to the same value (not just values + /// that compare as equal). + /// + /// # Notes + /// + /// Since this compares pointers it means that `Weak::new()` will equal each + /// other, even though they don't point to any value. + /// + /// + /// # Examples + /// + /// ``` + /// #![feature(weak_ptr_eq)] + /// use std::sync::{Arc, Weak}; + /// + /// let first_rc = Arc::new(5); + /// let first = Arc::downgrade(&first_rc); + /// let second = Arc::downgrade(&first_rc); + /// + /// assert!(Weak::ptr_eq(&first, &second)); + /// + /// let third_rc = Arc::new(5); + /// let third = Arc::downgrade(&third_rc); + /// + /// assert!(!Weak::ptr_eq(&first, &third)); + /// ``` + /// + /// Comparing `Weak::new`. + /// + /// ``` + /// #![feature(weak_ptr_eq)] + /// use std::sync::{Arc, Weak}; + /// + /// let first = Weak::new(); + /// let second = Weak::new(); + /// assert!(Weak::ptr_eq(&first, &second)); + /// + /// let third_rc = Arc::new(()); + /// let third = Arc::downgrade(&third_rc); + /// assert!(!Weak::ptr_eq(&first, &third)); + /// ``` + #[inline] + #[unstable(feature = "weak_ptr_eq", issue = "55981")] + pub fn ptr_eq(this: &Self, other: &Self) -> bool { + this.ptr.as_ptr() == other.ptr.as_ptr() + } } #[stable(feature = "arc_weak", since = "1.4.0")] @@ -1172,10 +1224,11 @@ impl Clone for Weak { #[stable(feature = "downgraded_weak", since = "1.10.0")] impl Default for Weak { /// Constructs a new `Weak`, without allocating memory. - /// Calling [`upgrade`][Weak::upgrade] on the return value always + /// Calling [`upgrade`] on the return value always /// gives [`None`]. /// /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// [`upgrade`]: ../../std/sync/struct.Weak.html#method.upgrade /// /// # Examples /// @@ -1240,12 +1293,46 @@ impl Drop for Weak { } } +#[stable(feature = "rust1", since = "1.0.0")] +trait ArcEqIdent { + fn eq(&self, other: &Arc) -> bool; + fn ne(&self, other: &Arc) -> bool; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ArcEqIdent for Arc { + #[inline] + default fn eq(&self, other: &Arc) -> bool { + **self == **other + } + #[inline] + default fn ne(&self, other: &Arc) -> bool { + **self != **other + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ArcEqIdent for Arc { + #[inline] + fn eq(&self, other: &Arc) -> bool { + Arc::ptr_eq(self, other) || **self == **other + } + + #[inline] + fn ne(&self, other: &Arc) -> bool { + !Arc::ptr_eq(self, other) && **self != **other + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for Arc { /// Equality for two `Arc`s. /// /// Two `Arc`s are equal if their inner values are equal. /// + /// If `T` also implements `Eq`, two `Arc`s that point to the same value are + /// always equal. + /// /// # Examples /// /// ``` @@ -1255,14 +1342,18 @@ impl PartialEq for Arc { /// /// assert!(five == Arc::new(5)); /// ``` + #[inline] fn eq(&self, other: &Arc) -> bool { - *(*self) == *(*other) + ArcEqIdent::eq(self, other) } /// Inequality for two `Arc`s. /// /// Two `Arc`s are unequal if their inner values are unequal. /// + /// If `T` also implements `Eq`, two `Arc`s that point to the same value are + /// never unequal. + /// /// # Examples /// /// ``` @@ -1272,10 +1363,12 @@ impl PartialEq for Arc { /// /// assert!(five != Arc::new(6)); /// ``` + #[inline] fn ne(&self, other: &Arc) -> bool { - *(*self) != *(*other) + ArcEqIdent::ne(self, other) } } + #[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for Arc { /// Partial comparison for two `Arc`s. diff --git a/src/liballoc/tests/arc.rs b/src/liballoc/tests/arc.rs index d90c22a3b18..ec589710216 100644 --- a/src/liballoc/tests/arc.rs +++ b/src/liballoc/tests/arc.rs @@ -10,6 +10,8 @@ use std::any::Any; use std::sync::{Arc, Weak}; +use std::cell::RefCell; +use std::cmp::PartialEq; #[test] fn uninhabited() { @@ -53,3 +55,43 @@ fn trait_object() { b = b.clone(); assert!(b.upgrade().is_none()); } + +#[test] +fn float_nan_ne() { + let x = Arc::new(std::f32::NAN); + assert!(x != x); + assert!(!(x == x)); +} + +#[test] +fn partial_eq() { + struct TestPEq (RefCell); + impl PartialEq for TestPEq { + fn eq(&self, other: &TestPEq) -> bool { + *self.0.borrow_mut() += 1; + *other.0.borrow_mut() += 1; + true + } + } + let x = Arc::new(TestPEq(RefCell::new(0))); + assert!(x == x); + assert!(!(x != x)); + assert_eq!(*x.0.borrow(), 4); +} + +#[test] +fn eq() { + #[derive(Eq)] + struct TestEq (RefCell); + impl PartialEq for TestEq { + fn eq(&self, other: &TestEq) -> bool { + *self.0.borrow_mut() += 1; + *other.0.borrow_mut() += 1; + true + } + } + let x = Arc::new(TestEq(RefCell::new(0))); + assert!(x == x); + assert!(!(x != x)); + assert_eq!(*x.0.borrow(), 0); +} diff --git a/src/liballoc/tests/binary_heap.rs b/src/liballoc/tests/binary_heap.rs index 8494463463c..536291de8f0 100644 --- a/src/liballoc/tests/binary_heap.rs +++ b/src/liballoc/tests/binary_heap.rs @@ -14,7 +14,7 @@ use std::collections::binary_heap::{Drain, PeekMut}; use std::panic::{self, AssertUnwindSafe}; use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; -use rand::{thread_rng, Rng}; +use rand::{thread_rng, seq::SliceRandom}; #[test] fn test_iterator() { @@ -318,11 +318,11 @@ fn panic_safe() { const NTEST: usize = 10; // don't use 0 in the data -- we want to catch the zeroed-out case. - let data = (1..DATASZ + 1).collect::>(); + let data = (1..=DATASZ).collect::>(); // since it's a fuzzy test, run several tries. for _ in 0..NTEST { - for i in 1..DATASZ + 1 { + for i in 1..=DATASZ { DROP_COUNTER.store(0, Ordering::SeqCst); let mut panic_ords: Vec<_> = data.iter() @@ -332,7 +332,7 @@ fn panic_safe() { let panic_item = PanicOrd(i, true); // heapify the sane items - rng.shuffle(&mut panic_ords); + panic_ords.shuffle(&mut rng); let mut heap = BinaryHeap::from(panic_ords); let inner_data; diff --git a/src/liballoc/tests/btree/map.rs b/src/liballoc/tests/btree/map.rs index 6ebdb86cc4a..33ef13ab811 100644 --- a/src/liballoc/tests/btree/map.rs +++ b/src/liballoc/tests/btree/map.rs @@ -302,7 +302,7 @@ fn test_range() { for i in 0..size { for j in i..size { let mut kvs = map.range((Included(&i), Included(&j))).map(|(&k, &v)| (k, v)); - let mut pairs = (i..j + 1).map(|i| (i, i)); + let mut pairs = (i..=j).map(|i| (i, i)); for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) { assert_eq!(kv, pair); @@ -321,7 +321,7 @@ fn test_range_mut() { for i in 0..size { for j in i..size { let mut kvs = map.range_mut((Included(&i), Included(&j))).map(|(&k, &mut v)| (k, v)); - let mut pairs = (i..j + 1).map(|i| (i, i)); + let mut pairs = (i..=j).map(|i| (i, i)); for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) { assert_eq!(kv, pair); diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs index e514a8a69c0..146abd1b750 100644 --- a/src/liballoc/tests/lib.rs +++ b/src/liballoc/tests/lib.rs @@ -13,11 +13,12 @@ #![feature(drain_filter)] #![feature(exact_size_is_empty)] #![feature(pattern)] +#![feature(repeat_generic_slice)] #![feature(slice_sort_by_cached_key)] #![feature(str_escape)] #![feature(try_reserve)] #![feature(unboxed_closures)] -#![feature(repeat_generic_slice)] +#![feature(vecdeque_rotate)] extern crate core; extern crate rand; diff --git a/src/liballoc/tests/rc.rs b/src/liballoc/tests/rc.rs index 9ec7c831444..02e1dfe13bb 100644 --- a/src/liballoc/tests/rc.rs +++ b/src/liballoc/tests/rc.rs @@ -10,6 +10,8 @@ use std::any::Any; use std::rc::{Rc, Weak}; +use std::cell::RefCell; +use std::cmp::PartialEq; #[test] fn uninhabited() { @@ -53,3 +55,43 @@ fn trait_object() { b = b.clone(); assert!(b.upgrade().is_none()); } + +#[test] +fn float_nan_ne() { + let x = Rc::new(std::f32::NAN); + assert!(x != x); + assert!(!(x == x)); +} + +#[test] +fn partial_eq() { + struct TestPEq (RefCell); + impl PartialEq for TestPEq { + fn eq(&self, other: &TestPEq) -> bool { + *self.0.borrow_mut() += 1; + *other.0.borrow_mut() += 1; + true + } + } + let x = Rc::new(TestPEq(RefCell::new(0))); + assert!(x == x); + assert!(!(x != x)); + assert_eq!(*x.0.borrow(), 4); +} + +#[test] +fn eq() { + #[derive(Eq)] + struct TestEq (RefCell); + impl PartialEq for TestEq { + fn eq(&self, other: &TestEq) -> bool { + *self.0.borrow_mut() += 1; + *other.0.borrow_mut() += 1; + true + } + } + let x = Rc::new(TestEq(RefCell::new(0))); + assert!(x == x); + assert!(!(x != x)); + assert_eq!(*x.0.borrow(), 0); +} diff --git a/src/liballoc/tests/slice.rs b/src/liballoc/tests/slice.rs index a50f99b0022..6f31e6ca1a1 100644 --- a/src/liballoc/tests/slice.rs +++ b/src/liballoc/tests/slice.rs @@ -18,7 +18,7 @@ use std::sync::atomic::Ordering::Relaxed; use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize}; use std::thread; -use rand::{Rng, RngCore, thread_rng}; +use rand::{Rng, RngCore, thread_rng, seq::SliceRandom}; use rand::distributions::Standard; fn square(n: usize) -> usize { @@ -459,7 +459,7 @@ fn test_sort() { for i in 0..v.len() { v[i] = i as i32; } - v.sort_by(|_, _| *rng.choose(&[Less, Equal, Greater]).unwrap()); + v.sort_by(|_, _| *[Less, Equal, Greater].choose(&mut rng).unwrap()); v.sort(); for i in 0..v.len() { assert_eq!(v[i], i as i32); @@ -484,7 +484,7 @@ fn test_sort_stability() { // create a vector like [(6, 1), (5, 1), (6, 2), ...], // where the first item of each tuple is random, but // the second item represents which occurrence of that - // number this element is, i.e. the second elements + // number this element is, i.e., the second elements // will occur in sorted order. let mut orig: Vec<_> = (0..len) .map(|_| { @@ -502,7 +502,7 @@ fn test_sort_stability() { // This comparison includes the count (the second item // of the tuple), so elements with equal first items // will need to be ordered with increasing - // counts... i.e. exactly asserting that this sort is + // counts... i.e., exactly asserting that this sort is // stable. assert!(v.windows(2).all(|w| w[0] <= w[1])); @@ -1579,7 +1579,7 @@ macro_rules! test { }).join(); // Check that the number of things dropped is exactly - // what we expect (i.e. the contents of `v`). + // what we expect (i.e., the contents of `v`). for (i, c) in DROP_COUNTS.iter().enumerate().take(len) { let count = c.load(Relaxed); assert!(count == 1, diff --git a/src/liballoc/tests/str.rs b/src/liballoc/tests/str.rs index a5fa7f0c4d9..9ad8ad1fc07 100644 --- a/src/liballoc/tests/str.rs +++ b/src/liballoc/tests/str.rs @@ -1005,7 +1005,7 @@ fn test_escape_debug() { // Note that there are subtleties with the number of backslashes // on the left- and right-hand sides. In particular, Unicode code points // are usually escaped with two backslashes on the right-hand side, as - // they are escaped. However, when the character is unescaped (e.g. for + // they are escaped. However, when the character is unescaped (e.g., for // printable characters), only a single backslash appears (as the character // itself appears in the debug string). assert_eq!("abc".escape_debug(), "abc"); @@ -1378,7 +1378,7 @@ fn test_bool_from_str() { fn check_contains_all_substrings(s: &str) { assert!(s.contains("")); for i in 0..s.len() { - for j in i+1..s.len() + 1 { + for j in i+1..=s.len() { assert!(s.contains(&s[i..j])); } } @@ -1514,9 +1514,9 @@ fn contains_weird_cases() { #[test] fn trim_ws() { - assert_eq!(" \t a \t ".trim_left_matches(|c: char| c.is_whitespace()), + assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()), "a \t "); - assert_eq!(" \t a \t ".trim_right_matches(|c: char| c.is_whitespace()), + assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()), " \t a"); assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()), "a \t "); @@ -1524,9 +1524,9 @@ fn trim_ws() { " \t a"); assert_eq!(" \t a \t ".trim_matches(|c: char| c.is_whitespace()), "a"); - assert_eq!(" \t \t ".trim_left_matches(|c: char| c.is_whitespace()), + assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()), ""); - assert_eq!(" \t \t ".trim_right_matches(|c: char| c.is_whitespace()), + assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()), ""); assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()), ""); diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs index e329b45a617..509195cd047 100644 --- a/src/liballoc/tests/vec.rs +++ b/src/liballoc/tests/vec.rs @@ -79,6 +79,11 @@ fn test_reserve() { assert!(v.capacity() >= 33) } +#[test] +fn test_zst_capacity() { + assert_eq!(Vec::<()>::new().capacity(), usize::max_value()); +} + #[test] fn test_extend() { let mut v = Vec::new(); diff --git a/src/liballoc/tests/vec_deque.rs b/src/liballoc/tests/vec_deque.rs index 3ea6c87a651..c8a6d86413a 100644 --- a/src/liballoc/tests/vec_deque.rs +++ b/src/liballoc/tests/vec_deque.rs @@ -861,7 +861,7 @@ fn test_as_slices() { ring.push_back(i); let (left, right) = ring.as_slices(); - let expected: Vec<_> = (0..i + 1).collect(); + let expected: Vec<_> = (0..=i).collect(); assert_eq!(left, &expected[..]); assert_eq!(right, []); } @@ -869,7 +869,7 @@ fn test_as_slices() { for j in -last..0 { ring.push_front(j); let (left, right) = ring.as_slices(); - let expected_left: Vec<_> = (-last..j + 1).rev().collect(); + let expected_left: Vec<_> = (-last..=j).rev().collect(); let expected_right: Vec<_> = (0..first).collect(); assert_eq!(left, &expected_left[..]); assert_eq!(right, &expected_right[..]); @@ -889,7 +889,7 @@ fn test_as_mut_slices() { ring.push_back(i); let (left, right) = ring.as_mut_slices(); - let expected: Vec<_> = (0..i + 1).collect(); + let expected: Vec<_> = (0..=i).collect(); assert_eq!(left, &expected[..]); assert_eq!(right, []); } @@ -897,7 +897,7 @@ fn test_as_mut_slices() { for j in -last..0 { ring.push_front(j); let (left, right) = ring.as_mut_slices(); - let expected_left: Vec<_> = (-last..j + 1).rev().collect(); + let expected_left: Vec<_> = (-last..=j).rev().collect(); let expected_right: Vec<_> = (0..first).collect(); assert_eq!(left, &expected_left[..]); assert_eq!(right, &expected_right[..]); @@ -1309,3 +1309,137 @@ fn test_try_reserve_exact() { } } + +#[test] +fn test_rotate_nop() { + let mut v: VecDeque<_> = (0..10).collect(); + assert_unchanged(&v); + + v.rotate_left(0); + assert_unchanged(&v); + + v.rotate_left(10); + assert_unchanged(&v); + + v.rotate_right(0); + assert_unchanged(&v); + + v.rotate_right(10); + assert_unchanged(&v); + + v.rotate_left(3); + v.rotate_right(3); + assert_unchanged(&v); + + v.rotate_right(3); + v.rotate_left(3); + assert_unchanged(&v); + + v.rotate_left(6); + v.rotate_right(6); + assert_unchanged(&v); + + v.rotate_right(6); + v.rotate_left(6); + assert_unchanged(&v); + + v.rotate_left(3); + v.rotate_left(7); + assert_unchanged(&v); + + v.rotate_right(4); + v.rotate_right(6); + assert_unchanged(&v); + + v.rotate_left(1); + v.rotate_left(2); + v.rotate_left(3); + v.rotate_left(4); + assert_unchanged(&v); + + v.rotate_right(1); + v.rotate_right(2); + v.rotate_right(3); + v.rotate_right(4); + assert_unchanged(&v); + + fn assert_unchanged(v: &VecDeque) { + assert_eq!(v, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + } +} + +#[test] +fn test_rotate_left_parts() { + let mut v: VecDeque<_> = (1..=7).collect(); + v.rotate_left(2); + assert_eq!(v.as_slices(), (&[3, 4, 5, 6, 7, 1][..], &[2][..])); + v.rotate_left(2); + assert_eq!(v.as_slices(), (&[5, 6, 7, 1][..], &[2, 3, 4][..])); + v.rotate_left(2); + assert_eq!(v.as_slices(), (&[7, 1][..], &[2, 3, 4, 5, 6][..])); + v.rotate_left(2); + assert_eq!(v.as_slices(), (&[2, 3, 4, 5, 6, 7, 1][..], &[][..])); + v.rotate_left(2); + assert_eq!(v.as_slices(), (&[4, 5, 6, 7, 1, 2][..], &[3][..])); + v.rotate_left(2); + assert_eq!(v.as_slices(), (&[6, 7, 1, 2][..], &[3, 4, 5][..])); + v.rotate_left(2); + assert_eq!(v.as_slices(), (&[1, 2][..], &[3, 4, 5, 6, 7][..])); +} + +#[test] +fn test_rotate_right_parts() { + let mut v: VecDeque<_> = (1..=7).collect(); + v.rotate_right(2); + assert_eq!(v.as_slices(), (&[6, 7][..], &[1, 2, 3, 4, 5][..])); + v.rotate_right(2); + assert_eq!(v.as_slices(), (&[4, 5, 6, 7][..], &[1, 2, 3][..])); + v.rotate_right(2); + assert_eq!(v.as_slices(), (&[2, 3, 4, 5, 6, 7][..], &[1][..])); + v.rotate_right(2); + assert_eq!(v.as_slices(), (&[7, 1, 2, 3, 4, 5, 6][..], &[][..])); + v.rotate_right(2); + assert_eq!(v.as_slices(), (&[5, 6][..], &[7, 1, 2, 3, 4][..])); + v.rotate_right(2); + assert_eq!(v.as_slices(), (&[3, 4, 5, 6][..], &[7, 1, 2][..])); + v.rotate_right(2); + assert_eq!(v.as_slices(), (&[1, 2, 3, 4, 5, 6][..], &[7][..])); +} + +#[test] +fn test_rotate_left_random() { + let shifts = [ + 6, 1, 0, 11, 12, 1, 11, 7, 9, 3, 6, 1, + 4, 0, 5, 1, 3, 1, 12, 8, 3, 1, 11, 11, + 9, 4, 12, 3, 12, 9, 11, 1, 7, 9, 7, 2, + ]; + let n = 12; + let mut v: VecDeque<_> = (0..n).collect(); + let mut total_shift = 0; + for shift in shifts.iter().cloned() { + v.rotate_left(shift); + total_shift += shift; + for i in 0..n { + assert_eq!(v[i], (i + total_shift) % n); + } + } +} + +#[test] +fn test_rotate_right_random() { + let shifts = [ + 6, 1, 0, 11, 12, 1, 11, 7, 9, 3, 6, 1, + 4, 0, 5, 1, 3, 1, 12, 8, 3, 1, 11, 11, + 9, 4, 12, 3, 12, 9, 11, 1, 7, 9, 7, 2, + ]; + let n = 12; + let mut v: VecDeque<_> = (0..n).collect(); + let mut total_shift = 0; + for shift in shifts.iter().cloned() { + v.rotate_right(shift); + total_shift += shift; + for i in 0..n { + assert_eq!(v[(i + total_shift) % n], i); + } + } +} diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index ca7c766e413..b78e71331a9 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -213,7 +213,7 @@ use raw_vec::RawVec; /// about its design. This ensures that it's as low-overhead as possible in /// the general case, and can be correctly manipulated in primitive ways /// by unsafe code. Note that these guarantees refer to an unqualified `Vec`. -/// If additional type parameters are added (e.g. to support custom allocators), +/// If additional type parameters are added (e.g., to support custom allocators), /// overriding their defaults may change the behavior. /// /// Most fundamentally, `Vec` is and always will be a (pointer, capacity, length) @@ -1241,8 +1241,6 @@ impl Vec { /// # Examples /// /// ``` - /// #![feature(vec_resize_with)] - /// /// let mut vec = vec![1, 2, 3]; /// vec.resize_with(5, Default::default); /// assert_eq!(vec, [1, 2, 3, 0, 0]); @@ -1255,7 +1253,7 @@ impl Vec { /// /// [`resize`]: #method.resize /// [`Clone`]: ../../std/clone/trait.Clone.html - #[unstable(feature = "vec_resize_with", issue = "41758")] + #[stable(feature = "vec_resize_with", since = "1.33.0")] pub fn resize_with(&mut self, new_len: usize, f: F) where F: FnMut() -> T { diff --git a/src/libcompiler_builtins b/src/libcompiler_builtins deleted file mode 160000 index fe74674f6e4..00000000000 --- a/src/libcompiler_builtins +++ /dev/null @@ -1 +0,0 @@ -Subproject commit fe74674f6e4be76d47b66f67d529ebf4186f4eb1 diff --git a/src/libcore/Cargo.toml b/src/libcore/Cargo.toml index 7fd61f07d5e..fa2ab11243b 100644 --- a/src/libcore/Cargo.toml +++ b/src/libcore/Cargo.toml @@ -20,7 +20,7 @@ name = "corebenches" path = "../libcore/benches/lib.rs" [dev-dependencies] -rand = "0.5" +rand = "0.6" [features] # Make panics and failed asserts immediately abort without formatting any message diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs index 58639808fae..8db7d33bdec 100644 --- a/src/libcore/alloc.rs +++ b/src/libcore/alloc.rs @@ -69,7 +69,7 @@ impl Layout { /// * `align` must be a power of two, /// /// * `size`, when rounded up to the nearest multiple of `align`, - /// must not overflow (i.e. the rounded value must be less than + /// must not overflow (i.e., the rounded value must be less than /// `usize::MAX`). #[stable(feature = "alloc_layout", since = "1.28.0")] #[inline] @@ -177,7 +177,7 @@ impl Layout { /// to ensure that the following address will satisfy `align` /// (measured in bytes). /// - /// E.g. if `self.size()` is 9, then `self.padding_needed_for(4)` + /// e.g., if `self.size()` is 9, then `self.padding_needed_for(4)` /// returns 3, because that is the minimum number of bytes of /// padding required to get a 4-aligned address (assuming that the /// corresponding memory block starts at a 4-aligned address). @@ -455,7 +455,7 @@ pub unsafe trait GlobalAlloc { /// if the caller does not ensure that `layout` has non-zero size. /// /// (Extension subtraits might provide more specific bounds on - /// behavior, e.g. guarantee a sentinel address or a null pointer + /// behavior, e.g., guarantee a sentinel address or a null pointer /// in response to a zero-size allocation request.) /// /// The allocated block of memory may or may not be initialized. @@ -550,10 +550,10 @@ pub unsafe trait GlobalAlloc { /// * `new_size` must be greater than zero. /// /// * `new_size`, when rounded up to the nearest multiple of `layout.align()`, - /// must not overflow (i.e. the rounded value must be less than `usize::MAX`). + /// must not overflow (i.e., the rounded value must be less than `usize::MAX`). /// /// (Extension subtraits might provide more specific bounds on - /// behavior, e.g. guarantee a sentinel address or a null pointer + /// behavior, e.g., guarantee a sentinel address or a null pointer /// in response to a zero-size allocation request.) /// /// # Errors @@ -616,7 +616,7 @@ pub unsafe trait GlobalAlloc { /// whether to return `Err`, or to return `Ok` with some pointer. /// /// * If an `Alloc` implementation chooses to return `Ok` in this -/// case (i.e. the pointer denotes a zero-sized inaccessible block) +/// case (i.e., the pointer denotes a zero-sized inaccessible block) /// then that returned pointer must be considered "currently /// allocated". On such an allocator, *all* methods that take /// currently-allocated pointers as inputs must accept these @@ -651,7 +651,7 @@ pub unsafe trait GlobalAlloc { /// /// * if a layout `k` fits a memory block (denoted by `ptr`) /// currently allocated via an allocator `a`, then it is legal to -/// use that layout to deallocate it, i.e. `a.dealloc(ptr, k);`. +/// use that layout to deallocate it, i.e., `a.dealloc(ptr, k);`. /// /// # Unsafety /// @@ -673,7 +673,7 @@ pub unsafe trait Alloc { // (Note: some existing allocators have unspecified but well-defined // behavior in response to a zero size allocation request ; - // e.g. in C, `malloc` of 0 will either return a null pointer or a + // e.g., in C, `malloc` of 0 will either return a null pointer or a // unique pointer, but will not have arbitrary undefined // behavior. // However in jemalloc for example, @@ -688,7 +688,7 @@ pub unsafe trait Alloc { /// /// The returned block of storage may or may not have its contents /// initialized. (Extension subtraits might restrict this - /// behavior, e.g. to ensure initialization to particular sets of + /// behavior, e.g., to ensure initialization to particular sets of /// bit patterns.) /// /// # Safety @@ -697,7 +697,7 @@ pub unsafe trait Alloc { /// if the caller does not ensure that `layout` has non-zero size. /// /// (Extension subtraits might provide more specific bounds on - /// behavior, e.g. guarantee a sentinel address or a null pointer + /// behavior, e.g., guarantee a sentinel address or a null pointer /// in response to a zero-size allocation request.) /// /// # Errors @@ -803,10 +803,10 @@ pub unsafe trait Alloc { /// * `new_size` must be greater than zero. /// /// * `new_size`, when rounded up to the nearest multiple of `layout.align()`, - /// must not overflow (i.e. the rounded value must be less than `usize::MAX`). + /// must not overflow (i.e., the rounded value must be less than `usize::MAX`). /// /// (Extension subtraits might provide more specific bounds on - /// behavior, e.g. guarantee a sentinel address or a null pointer + /// behavior, e.g., guarantee a sentinel address or a null pointer /// in response to a zero-size allocation request.) /// /// # Errors diff --git a/src/libcore/any.rs b/src/libcore/any.rs index c2113dfd2a0..f521ab994cd 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -126,7 +126,7 @@ impl fmt::Debug for dyn Any { } } -// Ensure that the result of e.g. joining a thread can be printed and +// Ensure that the result of e.g., joining a thread can be printed and // hence used with `unwrap`. May eventually no longer be needed if // dispatch works with upcasting. #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/benches/iter.rs b/src/libcore/benches/iter.rs index 6c597301ac2..b0aca658343 100644 --- a/src/libcore/benches/iter.rs +++ b/src/libcore/benches/iter.rs @@ -282,6 +282,12 @@ bench_sums! { (0i64..1000000).chain(1000000..).take_while(|&x| x < 1111111) } +bench_sums! { + bench_cycle_take_sum, + bench_cycle_take_ref_sum, + (0i64..10000).cycle().take(1000000) +} + // Checks whether Skip> is as fast as Zip, Skip>, from // https://users.rust-lang.org/t/performance-difference-between-iterator-zip-and-skip-order/15743 #[bench] diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index d8d51f53377..0a16c92928d 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -97,7 +97,7 @@ //! ## Implementation details of logically-immutable methods //! //! Occasionally it may be desirable not to expose in an API that there is mutation happening -//! "under the hood". This may be because logically the operation is immutable, but e.g. caching +//! "under the hood". This may be because logically the operation is immutable, but e.g., caching //! forces the implementation to perform mutation; or because you must employ mutation to implement //! a trait method that was originally defined to take `&self`. //! @@ -1227,7 +1227,7 @@ impl fmt::Display for Ref<'_, T> { } impl<'b, T: ?Sized> RefMut<'b, T> { - /// Make a new `RefMut` for a component of the borrowed data, e.g. an enum + /// Make a new `RefMut` for a component of the borrowed data, e.g., an enum /// variant. /// /// The `RefCell` is already mutably borrowed, so this cannot fail. diff --git a/src/libcore/char/mod.rs b/src/libcore/char/mod.rs index 7e1313747ee..e07a0f5d712 100644 --- a/src/libcore/char/mod.rs +++ b/src/libcore/char/mod.rs @@ -131,7 +131,7 @@ pub struct EscapeUnicode { state: EscapeUnicodeState, // The index of the next hex digit to be printed (0 if none), - // i.e. the number of remaining hex digits to be printed; + // i.e., the number of remaining hex digits to be printed; // increasing from the least significant digit: 0x543210 hex_digit_idx: usize, } diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index 46bb580dcdd..225ea3de9cd 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -13,7 +13,7 @@ //! In Rust, some simple types are "implicitly copyable" and when you //! assign them or pass them as arguments, the receiver will get a copy, //! leaving the original value in place. These types do not require -//! allocation to copy and do not have finalizers (i.e. they do not +//! allocation to copy and do not have finalizers (i.e., they do not //! contain owned boxes or implement [`Drop`]), so the compiler considers //! them cheap and safe to copy. For other types copies must be made //! explicitly, by convention implementing the [`Clone`] trait and calling @@ -93,10 +93,10 @@ /// In addition to the [implementors listed below][impls], /// the following types also implement `Clone`: /// -/// * Function item types (i.e. the distinct types defined for each function) -/// * Function pointer types (e.g. `fn() -> i32`) -/// * Array types, for all sizes, if the item type also implements `Clone` (e.g. `[i32; 123456]`) -/// * Tuple types, if each component also implements `Clone` (e.g. `()`, `(i32, bool)`) +/// * Function item types (i.e., the distinct types defined for each function) +/// * Function pointer types (e.g., `fn() -> i32`) +/// * Array types, for all sizes, if the item type also implements `Clone` (e.g., `[i32; 123456]`) +/// * Tuple types, if each component also implements `Clone` (e.g., `()`, `(i32, bool)`) /// * Closure types, if they capture no value from the environment /// or if all such captured values implement `Clone` themselves. /// Note that variables captured by shared reference always implement `Clone` diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index dbc28ef7cf6..2d4813718f4 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -327,7 +327,8 @@ pub trait Into: Sized { /// An example usage for error handling: /// /// ``` -/// use std::io::{self, Read}; +/// use std::fs; +/// use std::io; /// use std::num; /// /// enum CliError { @@ -348,9 +349,7 @@ pub trait Into: Sized { /// } /// /// fn open_and_parse_file(file_name: &str) -> Result { -/// let mut file = std::fs::File::open("test")?; -/// let mut contents = String::new(); -/// file.read_to_string(&mut contents)?; +/// let mut contents = fs::read_to_string(&file_name)?; /// let num: i32 = contents.trim().parse()?; /// Ok(num) /// } diff --git a/src/libcore/ffi.rs b/src/libcore/ffi.rs index edeb3b0d368..899fae90946 100644 --- a/src/libcore/ffi.rs +++ b/src/libcore/ffi.rs @@ -1,7 +1,6 @@ #![stable(feature = "", since = "1.30.0")] #![allow(non_camel_case_types)] -#![cfg_attr(stage0, allow(dead_code))] //! Utilities related to FFI bindings. @@ -18,7 +17,7 @@ use ::fmt; /// /// [`!`]: ../../std/primitive.never.html /// [pointer]: ../../std/primitive.pointer.html -// NB: For LLVM to recognize the void pointer type and by extension +// N.B., 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 @@ -45,6 +44,7 @@ impl fmt::Debug for c_void { /// Basic implementation of a `va_list`. #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")), + all(target_arch = "aarch4", target_os = "ios"), windows))] #[unstable(feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ @@ -122,7 +122,6 @@ struct VaListImpl { all supported platforms", issue = "27745")] #[repr(transparent)] -#[cfg(not(stage0))] pub struct VaList<'a>(&'a mut VaListImpl); // The VaArgSafe trait needs to be used in public interfaces, however, the trait @@ -172,7 +171,6 @@ impl sealed_trait::VaArgSafe for *mut T {} issue = "27745")] impl sealed_trait::VaArgSafe for *const T {} -#[cfg(not(stage0))] impl<'a> VaList<'a> { /// Advance to the next arg. #[unstable(feature = "c_variadic", @@ -192,6 +190,7 @@ impl<'a> VaList<'a> { where F: for<'copy> FnOnce(VaList<'copy>) -> R { #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")), + all(target_arch = "aarch4", target_os = "ios"), windows))] let mut ap = va_copy(self); #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"), @@ -206,7 +205,6 @@ impl<'a> VaList<'a> { } } -#[cfg(not(stage0))] extern "rust-intrinsic" { /// Destroy the arglist `ap` after initialization with `va_start` or /// `va_copy`. diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 75ec0d7d50b..8e0caa5ae33 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -609,10 +609,15 @@ pub trait Debug { /// println!("The origin is: {}", origin); /// ``` #[rustc_on_unimplemented( + on( + _Self="std::path::Path", + label="`{Self}` cannot be formatted with the default formatter; call `.display()` on it", + note="call `.display()` or `.to_string_lossy()` to safely print paths, \ + as they may contain non-Unicode data" + ), message="`{Self}` doesn't implement `{Display}`", label="`{Self}` cannot be formatted with the default formatter", - note="in format strings you may be able to use `{{:?}}` \ - (or {{:#?}} for pretty-print) instead", + note="in format strings you may be able to use `{{:?}}` (or {{:#?}} for pretty-print) instead", )] #[doc(alias = "{}")] #[stable(feature = "rust1", since = "1.0.0")] @@ -1381,7 +1386,7 @@ impl<'a> Formatter<'a> { for part in formatted.parts { match *part { flt2dec::Part::Zero(mut nzeroes) => { - const ZEROES: &'static str = // 64 zeroes + const ZEROES: &str = // 64 zeroes "0000000000000000000000000000000000000000000000000000000000000000"; while nzeroes > ZEROES.len() { self.buf.write_str(ZEROES)?; diff --git a/src/libcore/future/future.rs b/src/libcore/future/future.rs index 0c870f9e404..5dee1d6dd3a 100644 --- a/src/libcore/future/future.rs +++ b/src/libcore/future/future.rs @@ -33,6 +33,7 @@ use task::{Poll, LocalWaker}; /// /// When using a future, you generally won't call `poll` directly, but instead /// `await!` the value. +#[must_use] pub trait Future { /// The result of the `Future`. type Output; diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index bbebadd452a..3e59ee1f8e5 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -408,7 +408,7 @@ impl Hasher for &mut H { /// A trait for creating instances of [`Hasher`]. /// -/// A `BuildHasher` is typically used (e.g. by [`HashMap`]) to create +/// A `BuildHasher` is typically used (e.g., by [`HashMap`]) to create /// [`Hasher`]s for each key such that they are hashed independently of one /// another, since [`Hasher`]s contain state. /// diff --git a/src/libcore/hint.rs b/src/libcore/hint.rs index f4e96e67b2c..0bfdd937abd 100644 --- a/src/libcore/hint.rs +++ b/src/libcore/hint.rs @@ -24,7 +24,7 @@ use intrinsics; /// therefore will eliminate all branches that reach to a call to /// `unreachable_unchecked()`. /// -/// Like all instances of UB, if this assumption turns out to be wrong, i.e. the +/// Like all instances of UB, if this assumption turns out to be wrong, i.e., the /// `unreachable_unchecked()` call is actually reachable among all possible /// control flow, the compiler will apply the wrong optimization strategy, and /// may sometimes even corrupt seemingly unrelated code, causing diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 16f0299c18b..b94d5b4adcf 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -52,7 +52,7 @@ pub use ptr::drop_in_place; extern "rust-intrinsic" { - // NB: These intrinsics take raw pointers because they mutate aliased + // N.B., these intrinsics take raw pointers because they mutate aliased // memory, which is not valid for either `&` or `&mut`. /// Stores a value if the current value is the same as the `old` value. @@ -635,7 +635,7 @@ extern "rust-intrinsic" { /// Tells LLVM that this point in the code is not reachable, enabling /// further optimizations. /// - /// NB: This is very different from the `unreachable!()` macro: Unlike the + /// N.B., this is very different from the `unreachable!()` macro: Unlike the /// macro, which panics when it is executed, it is *undefined behavior* to /// reach code marked with this function. /// @@ -718,7 +718,6 @@ extern "rust-intrinsic" { pub fn uninit() -> T; /// Moves a value out of scope without running drop glue. - #[cfg(not(stage0))] pub fn forget(_: T); /// Reinterprets the bits of a value of one type as another type. @@ -1476,14 +1475,12 @@ extern "rust-intrinsic" { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `rotate_left` method. For example, /// [`std::u32::rotate_left`](../../std/primitive.u32.html#method.rotate_left) - #[cfg(not(stage0))] pub fn rotate_left(x: T, y: T) -> T; /// Performs rotate right. /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `rotate_right` method. For example, /// [`std::u32::rotate_right`](../../std/primitive.u32.html#method.rotate_right) - #[cfg(not(stage0))] pub fn rotate_right(x: T, y: T) -> T; /// Returns (a + b) mod 2N, where N is the width of T in bits. diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 80bd5698c47..d0b0fd1ab31 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -87,7 +87,7 @@ fn _assert_is_object_safe(_: &dyn Iterator) {} on( _Self="[]", label="borrow the array with `&` or call `.iter()` on it to iterate over it", - note="arrays are not an iterators, but slices like the following are: `&[1, 2, 3]`" + note="arrays are not iterators, but slices like the following are: `&[1, 2, 3]`" ), on( _Self="{integral}", @@ -98,6 +98,7 @@ fn _assert_is_object_safe(_: &dyn Iterator) {} message="`{Self}` is not an iterator" )] #[doc(spotlight)] +#[must_use] pub trait Iterator { /// The type of the elements being iterated over. #[stable(feature = "rust1", since = "1.0.0")] @@ -154,7 +155,7 @@ pub trait Iterator { /// /// `size_hint()` is primarily intended to be used for optimizations such as /// reserving space for the elements of the iterator, but must not be - /// trusted to e.g. omit bounds checks in unsafe code. An incorrect + /// trusted to e.g., omit bounds checks in unsafe code. An incorrect /// implementation of `size_hint()` should not lead to memory safety /// violations. /// diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index de1a318cfb2..aa130754f83 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -429,6 +429,9 @@ impl Iterator for Rev where I: DoubleEndedIterator { #[inline] fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } + #[inline] + fn nth(&mut self, n: usize) -> Option<::Item> { self.iter.nth_back(n) } + fn try_fold(&mut self, init: B, f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try { @@ -461,6 +464,9 @@ impl DoubleEndedIterator for Rev where I: DoubleEndedIterator { #[inline] fn next_back(&mut self) -> Option<::Item> { self.iter.next() } + #[inline] + fn nth_back(&mut self, n: usize) -> Option<::Item> { self.iter.nth(n) } + fn try_rfold(&mut self, init: B, f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try { @@ -702,7 +708,9 @@ unsafe impl<'a, I, T: 'a> TrustedRandomAccess for Cloned } #[inline] - fn may_have_side_effect() -> bool { false } + fn may_have_side_effect() -> bool { + I::may_have_side_effect() + } } #[unstable(feature = "trusted_len", issue = "37572")] @@ -1953,18 +1961,11 @@ impl Iterator for Peekable { #[inline] fn nth(&mut self, n: usize) -> Option { - // FIXME(#43234): merge these when borrow-checking gets better. - if n == 0 { - match self.peeked.take() { - Some(v) => v, - None => self.iter.nth(n), - } - } else { - match self.peeked.take() { - Some(None) => None, - Some(Some(_)) => self.iter.nth(n - 1), - None => self.iter.nth(n), - } + match self.peeked.take() { + Some(None) => None, + Some(v @ Some(_)) if n == 0 => v, + Some(Some(_)) => self.iter.nth(n - 1), + None => self.iter.nth(n), } } @@ -2063,14 +2064,8 @@ impl Peekable { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn peek(&mut self) -> Option<&I::Item> { - if self.peeked.is_none() { - self.peeked = Some(self.iter.next()); - } - match self.peeked { - Some(Some(ref value)) => Some(value), - Some(None) => None, - _ => unreachable!(), - } + let iter = &mut self.iter; + self.peeked.get_or_insert_with(|| iter.next()).as_ref() } } @@ -2207,8 +2202,12 @@ impl Iterator for TakeWhile #[inline] fn size_hint(&self) -> (usize, Option) { - let (_, upper) = self.iter.size_hint(); - (0, upper) // can't know a lower bound, due to the predicate + if self.flag { + (0, Some(0)) + } else { + let (_, upper) = self.iter.size_hint(); + (0, upper) // can't know a lower bound, due to the predicate + } } #[inline] @@ -2419,6 +2418,10 @@ impl Iterator for Take where I: Iterator{ #[inline] fn size_hint(&self) -> (usize, Option) { + if self.n == 0 { + return (0, Some(0)); + } + let (lower, upper) = self.iter.size_hint(); let lower = cmp::min(lower, self.n); diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index d2c5a3bed28..727a60e3596 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -427,6 +427,62 @@ pub trait DoubleEndedIterator: Iterator { #[stable(feature = "rust1", since = "1.0.0")] fn next_back(&mut self) -> Option; + /// Returns the `n`th element from the end of the iterator. + /// + /// This is essentially the reversed version of [`nth`]. Although like most indexing + /// operations, the count starts from zero, so `nth_back(0)` returns the first value fro + /// the end, `nth_back(1)` the second, and so on. + /// + /// Note that all elements between the end and the returned element will be + /// consumed, including the returned element. This also means that calling + /// `nth_back(0)` multiple times on the same iterator will return different + /// elements. + /// + /// `nth_back()` will return [`None`] if `n` is greater than or equal to the length of the + /// iterator. + /// + /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// [`nth`]: ../../std/iter/trait.Iterator.html#method.nth + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(iter_nth_back)] + /// let a = [1, 2, 3]; + /// assert_eq!(a.iter().nth_back(2), Some(&1)); + /// ``` + /// + /// Calling `nth_back()` multiple times doesn't rewind the iterator: + /// + /// ``` + /// #![feature(iter_nth_back)] + /// let a = [1, 2, 3]; + /// + /// let mut iter = a.iter(); + /// + /// assert_eq!(iter.nth_back(1), Some(&2)); + /// assert_eq!(iter.nth_back(1), None); + /// ``` + /// + /// Returning `None` if there are less than `n + 1` elements: + /// + /// ``` + /// #![feature(iter_nth_back)] + /// let a = [1, 2, 3]; + /// assert_eq!(a.iter().nth_back(10), None); + /// ``` + #[inline] + #[unstable(feature = "iter_nth_back", issue = "56995")] + fn nth_back(&mut self, mut n: usize) -> Option { + for x in self.rev() { + if n == 0 { return Some(x) } + n -= 1; + } + None + } + /// This is the reverse version of [`try_fold()`]: it takes elements /// starting from the back of the iterator. /// @@ -461,8 +517,11 @@ pub trait DoubleEndedIterator: Iterator { /// ``` #[inline] #[stable(feature = "iterator_try_fold", since = "1.27.0")] - fn try_rfold(&mut self, init: B, mut f: F) -> R where - Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try + fn try_rfold(&mut self, init: B, mut f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try { let mut accum = init; while let Some(x) = self.next_back() { @@ -524,8 +583,10 @@ pub trait DoubleEndedIterator: Iterator { /// ``` #[inline] #[stable(feature = "iter_rfold", since = "1.27.0")] - fn rfold(mut self, accum: B, mut f: F) -> B where - Self: Sized, F: FnMut(B, Self::Item) -> B, + fn rfold(mut self, accum: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, { self.try_rfold(accum, move |acc, x| Ok::(f(acc, x))).unwrap() } @@ -574,7 +635,8 @@ pub trait DoubleEndedIterator: Iterator { /// ``` #[inline] #[stable(feature = "iter_rfind", since = "1.27.0")] - fn rfind

(&mut self, mut predicate: P) -> Option where + fn rfind

(&mut self, mut predicate: P) -> Option + where Self: Sized, P: FnMut(&Self::Item) -> bool { @@ -587,7 +649,12 @@ pub trait DoubleEndedIterator: Iterator { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for &'a mut I { - fn next_back(&mut self) -> Option { (**self).next_back() } + fn next_back(&mut self) -> Option { + (**self).next_back() + } + fn nth_back(&mut self, n: usize) -> Option { + (**self).nth_back(n) + } } /// An iterator that knows its exact length. @@ -770,7 +837,7 @@ pub trait Product: Sized { fn product>(iter: I) -> Self; } -// NB: explicitly use Add and Mul here to inherit overflow checks +// N.B., explicitly use Add and Mul here to inherit overflow checks macro_rules! integer_sum_product { (@impls $zero:expr, $one:expr, #[$attr:meta], $($a:ty)*) => ($( #[$attr] diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 726e891df0c..2124458dc55 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -71,6 +71,7 @@ #![no_core] #![deny(missing_docs)] +#![deny(intra_doc_link_resolution_failure)] #![deny(missing_debug_implementations)] #![feature(allow_internal_unstable)] @@ -92,6 +93,7 @@ #![feature(link_llvm_intrinsics)] #![feature(never_type)] #![feature(nll)] +#![feature(bind_by_move_pattern_guards)] #![feature(exhaustive_patterns)] #![feature(no_core)] #![feature(on_unimplemented)] @@ -120,7 +122,6 @@ #![feature(const_slice_len)] #![feature(const_str_as_bytes)] #![feature(const_str_len)] -#![feature(const_let)] #![feature(const_int_rotate)] #![feature(const_int_wrapping)] #![feature(const_int_sign)] @@ -250,9 +251,7 @@ macro_rules! vector_impl { ($([$f:ident, $($args:tt)*]),*) => { $($f!($($args)*) #[path = "../stdsimd/coresimd/mod.rs"] #[allow(missing_docs, missing_debug_implementations, dead_code, unused_imports)] #[unstable(feature = "stdsimd", issue = "48556")] -#[cfg(not(stage0))] // allow changes to how stdsimd works in stage0 mod coresimd; #[stable(feature = "simd_arch", since = "1.27.0")] -#[cfg(not(stage0))] pub use coresimd::arch; diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 8b1855800c2..5ba0e949483 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -238,6 +238,10 @@ macro_rules! debug_assert_ne { /// with converting downstream errors. /// /// The `?` operator was added to replace `try!` and should be used instead. +/// Furthermore, `try` is a reserved word in Rust 2018, so if you must use +/// it, you will need to use the [raw-identifier syntax][ris]: `r#try`. +/// +/// [ris]: https://doc.rust-lang.org/nightly/rust-by-example/compatibility/raw_identifiers.html /// /// `try!` matches the given [`Result`]. In case of the `Ok` variant, the /// expression has the value of the wrapped value. diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 3bcdfabbb24..d3d16127ed5 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -274,10 +274,10 @@ pub trait Unsize { /// In addition to the [implementors listed below][impls], /// the following types also implement `Copy`: /// -/// * Function item types (i.e. the distinct types defined for each function) -/// * Function pointer types (e.g. `fn() -> i32`) -/// * Array types, for all sizes, if the item type also implements `Copy` (e.g. `[i32; 123456]`) -/// * Tuple types, if each component also implements `Copy` (e.g. `()`, `(i32, bool)`) +/// * Function item types (i.e., the distinct types defined for each function) +/// * Function pointer types (e.g., `fn() -> i32`) +/// * Array types, for all sizes, if the item type also implements `Copy` (e.g., `[i32; 123456]`) +/// * Tuple types, if each component also implements `Copy` (e.g., `()`, `(i32, bool)`) /// * Closure types, if they capture no value from the environment /// or if all such captured values implement `Copy` themselves. /// Note that variables captured by shared reference always implement `Copy` @@ -596,7 +596,7 @@ mod impls { /// This affects, for example, whether a `static` of that type is /// placed in read-only static memory or writable static memory. #[lang = "freeze"] -unsafe auto trait Freeze {} +pub(crate) unsafe auto trait Freeze {} impl !Freeze for UnsafeCell {} unsafe impl Freeze for PhantomData {} @@ -640,15 +640,15 @@ unsafe impl Freeze for &mut T {} #[unstable(feature = "pin", issue = "49150")] pub auto trait Unpin {} -/// A type which does not implement `Unpin`. +/// A marker type which does not implement `Unpin`. /// -/// If a type contains a `Pinned`, it will not implement `Unpin` by default. +/// If a type contains a `PhantomPinned`, it will not implement `Unpin` by default. #[unstable(feature = "pin", issue = "49150")] #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] -pub struct Pinned; +pub struct PhantomPinned; #[unstable(feature = "pin", issue = "49150")] -impl !Unpin for Pinned {} +impl !Unpin for PhantomPinned {} #[unstable(feature = "pin", issue = "49150")] impl<'a, T: ?Sized + 'a> Unpin for &'a T {} diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index e4b2800ae21..87dde906601 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -149,7 +149,6 @@ pub fn forget(t: T) { /// /// [`forget`]: fn.forget.html #[inline] -#[cfg(not(stage0))] #[unstable(feature = "forget_unsized", issue = "0")] pub fn forget_unsized(t: T) { unsafe { intrinsics::forget(t) } @@ -305,7 +304,7 @@ pub const fn size_of() -> usize { /// Returns the size of the pointed-to value in bytes. /// /// This is usually the same as `size_of::()`. However, when `T` *has* no -/// statically known size, e.g. a slice [`[T]`][slice] or a [trait object], +/// statically known size, e.g., a slice [`[T]`][slice] or a [trait object], /// then `size_of_val` can be used to get the dynamically-known size. /// /// [slice]: ../../std/primitive.slice.html @@ -531,6 +530,12 @@ pub unsafe fn zeroed() -> T { /// it goes out of scope (and therefore would be dropped). Note that this /// includes a `panic` occurring and unwinding the stack suddenly. /// +/// If you partially initialize an array, you may need to use +/// [`ptr::drop_in_place`][drop_in_place] to remove the elements you have fully +/// initialized followed by [`mem::forget`][mem_forget] to prevent drop running +/// on the array. If a partially allocated array is dropped this will lead to +/// undefined behaviour. +/// /// # Examples /// /// Here's how to safely initialize an array of [`Vec`]s. @@ -584,11 +589,44 @@ pub unsafe fn zeroed() -> T { /// println!("{:?}", &data[0]); /// ``` /// +/// This example shows how to handle partially initialized arrays, which could +/// be found in low-level datastructures. +/// +/// ``` +/// use std::mem; +/// use std::ptr; +/// +/// // Count the number of elements we have assigned. +/// let mut data_len: usize = 0; +/// let mut data: [String; 1000]; +/// +/// unsafe { +/// data = mem::uninitialized(); +/// +/// for elem in &mut data[0..500] { +/// ptr::write(elem, String::from("hello")); +/// data_len += 1; +/// } +/// +/// // For each item in the array, drop if we allocated it. +/// for i in &mut data[0..data_len] { +/// ptr::drop_in_place(i); +/// } +/// } +/// // Forget the data. If this is allowed to drop, you may see a crash such as: +/// // 'mem_uninit_test(2457,0x7fffb55dd380) malloc: *** error for object +/// // 0x7ff3b8402920: pointer being freed was not allocated' +/// mem::forget(data); +/// ``` +/// /// [`Vec`]: ../../std/vec/struct.Vec.html /// [`vec!`]: ../../std/macro.vec.html /// [`Clone`]: ../../std/clone/trait.Clone.html /// [ub]: ../../reference/behavior-considered-undefined.html /// [write]: ../ptr/fn.write.html +/// [drop_in_place]: ../ptr/fn.drop_in_place.html +/// [mem_zeroed]: fn.zeroed.html +/// [mem_forget]: fn.forget.html /// [copy]: ../intrinsics/fn.copy.html /// [copy_no]: ../intrinsics/fn.copy_nonoverlapping.html /// [`Drop`]: ../ops/trait.Drop.html @@ -985,6 +1023,9 @@ impl ManuallyDrop { /// /// This function semantically moves out the contained value without preventing further usage. /// It is up to the user of this method to ensure that this container is not used again. + /// + /// [`ManuallyDrop::drop`]: #method.drop + /// [`ManuallyDrop::into_inner`]: #method.into_inner #[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead"] #[unstable(feature = "manually_drop_take", issue = "55422")] #[inline] @@ -1119,7 +1160,7 @@ impl MaybeUninit { /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized /// state, otherwise this will immediately cause undefined behavior. // FIXME(#53491): We currently rely on the above being incorrect, i.e., we have references - // to uninitialized data (e.g. in `libcore/fmt/float.rs`). We should make + // to uninitialized data (e.g., in `libcore/fmt/float.rs`). We should make // a final decision about the rules before stabilization. #[unstable(feature = "maybe_uninit", issue = "53491")] #[inline(always)] diff --git a/src/libcore/nonzero.rs b/src/libcore/nonzero.rs index 436cd1fc057..a89c6ca60cb 100644 --- a/src/libcore/nonzero.rs +++ b/src/libcore/nonzero.rs @@ -11,14 +11,23 @@ //! Exposes the NonZero lang item which provides optimization hints. use ops::{CoerceUnsized, DispatchFromDyn}; +use marker::Freeze; /// A wrapper type for raw pointers and integers that will never be /// NULL or 0 that might allow certain optimizations. #[rustc_layout_scalar_valid_range_start(1)] -#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[derive(Copy, Eq, PartialEq, Ord, PartialOrd, Hash)] #[repr(transparent)] -pub(crate) struct NonZero(pub(crate) T); +pub(crate) struct NonZero(pub(crate) T); -impl, U> CoerceUnsized> for NonZero {} +// Do not call `T::clone` as theoretically it could turn the field into `0` +// invalidating `NonZero`'s invariant. +impl Clone for NonZero { + fn clone(&self) -> Self { + unsafe { NonZero(self.0) } + } +} -impl, U> DispatchFromDyn> for NonZero {} +impl + Freeze, U: Freeze> CoerceUnsized> for NonZero {} + +impl + Freeze, U: Freeze> DispatchFromDyn> for NonZero {} diff --git a/src/libcore/num/bignum.rs b/src/libcore/num/bignum.rs index 732a02e8c42..2bfb49c0682 100644 --- a/src/libcore/num/bignum.rs +++ b/src/libcore/num/bignum.rs @@ -183,7 +183,7 @@ macro_rules! define_bignum { let nonzero = &digits[..end]; if nonzero.is_empty() { - // There are no non-zero digits, i.e. the number is zero. + // There are no non-zero digits, i.e., the number is zero. return 0; } // This could be optimized with leading_zeros() and bit shifts, but that's diff --git a/src/libcore/num/dec2flt/algorithm.rs b/src/libcore/num/dec2flt/algorithm.rs index ccf3950c2ba..c3a983d0f0e 100644 --- a/src/libcore/num/dec2flt/algorithm.rs +++ b/src/libcore/num/dec2flt/algorithm.rs @@ -61,9 +61,9 @@ mod fpu_precision { /// /// The only field which is relevant for the following code is PC, Precision Control. This /// field determines the precision of the operations performed by the FPU. It can be set to: - /// - 0b00, single precision i.e. 32-bits - /// - 0b10, double precision i.e. 64-bits - /// - 0b11, double extended precision i.e. 80-bits (default state) + /// - 0b00, single precision i.e., 32-bits + /// - 0b10, double precision i.e., 64-bits + /// - 0b11, double extended precision i.e., 80-bits (default state) /// The 0b01 value is reserved and should not be used. pub struct FPUControlWord(u16); diff --git a/src/libcore/num/dec2flt/rawfp.rs b/src/libcore/num/dec2flt/rawfp.rs index 38f4e4687a9..18c30e29c79 100644 --- a/src/libcore/num/dec2flt/rawfp.rs +++ b/src/libcore/num/dec2flt/rawfp.rs @@ -349,7 +349,7 @@ pub fn prev_float(x: T) -> T { } // Find the smallest floating point number strictly larger than the argument. -// This operation is saturating, i.e. next_float(inf) == inf. +// This operation is saturating, i.e., next_float(inf) == inf. // Unlike most code in this module, this function does handle zero, subnormals, and infinities. // However, like all other code here, it does not deal with NaN and negative numbers. pub fn next_float(x: T) -> T { diff --git a/src/libcore/num/flt2dec/mod.rs b/src/libcore/num/flt2dec/mod.rs index d58015beecb..097240e58ae 100644 --- a/src/libcore/num/flt2dec/mod.rs +++ b/src/libcore/num/flt2dec/mod.rs @@ -23,7 +23,7 @@ representation `V = 0.d[0..n-1] * 10^k` such that: - `d[0]` is non-zero. - It's correctly rounded when parsed back: `v - minus < V < v + plus`. - Furthermore it is shortest such one, i.e. there is no representation + Furthermore it is shortest such one, i.e., there is no representation with less than `n` digits that is correctly rounded. - It's closest to the original value: `abs(V - v) <= 10^(k-n) / 2`. Note that @@ -398,7 +398,7 @@ fn determine_sign(sign: Sign, decoded: &FullDecoded, negative: bool) -> &'static /// given number of fractional digits. The result is stored to the supplied parts /// array while utilizing given byte buffer as a scratch. `upper` is currently /// unused but left for the future decision to change the case of non-finite values, -/// i.e. `inf` and `nan`. The first part to be rendered is always a `Part::Sign` +/// i.e., `inf` and `nan`. The first part to be rendered is always a `Part::Sign` /// (which can be an empty string if no sign is rendered). /// /// `format_shortest` should be the underlying digit-generation function. @@ -591,7 +591,7 @@ pub fn to_exact_exp_str<'a, T, F>(mut format_exact: F, v: T, /// given number of fractional digits. The result is stored to the supplied parts /// array while utilizing given byte buffer as a scratch. `upper` is currently /// unused but left for the future decision to change the case of non-finite values, -/// i.e. `inf` and `nan`. The first part to be rendered is always a `Part::Sign` +/// i.e., `inf` and `nan`. The first part to be rendered is always a `Part::Sign` /// (which can be an empty string if no sign is rendered). /// /// `format_exact` should be the underlying digit-generation function. diff --git a/src/libcore/num/flt2dec/strategy/dragon.rs b/src/libcore/num/flt2dec/strategy/dragon.rs index aa6a08cb205..cda0773afbd 100644 --- a/src/libcore/num/flt2dec/strategy/dragon.rs +++ b/src/libcore/num/flt2dec/strategy/dragon.rs @@ -81,11 +81,11 @@ pub fn format_shortest(d: &Decoded, buf: &mut [u8]) -> (/*#digits*/ usize, /*exp // - followed by `(mant + 2 * plus) * 2^exp` in the original type. // // obviously, `minus` and `plus` cannot be zero. (for infinities, we use out-of-range values.) - // also we assume that at least one digit is generated, i.e. `mant` cannot be zero too. + // also we assume that at least one digit is generated, i.e., `mant` cannot be zero too. // // this also means that any number between `low = (mant - minus) * 2^exp` and // `high = (mant + plus) * 2^exp` will map to this exact floating point number, - // with bounds included when the original mantissa was even (i.e. `!mant_was_odd`). + // with bounds included when the original mantissa was even (i.e., `!mant_was_odd`). assert!(d.mant > 0); assert!(d.minus > 0); @@ -172,7 +172,7 @@ pub fn format_shortest(d: &Decoded, buf: &mut [u8]) -> (/*#digits*/ usize, /*exp // - `high - v = plus / scale * 10^(k-n)` // // assume that `d[0..n-1]` is the shortest representation between `low` and `high`, - // i.e. `d[0..n-1]` satisfies both of the following but `d[0..n-2]` doesn't: + // i.e., `d[0..n-1]` satisfies both of the following but `d[0..n-2]` doesn't: // - `low < d[0..n-1] * 10^(k-n) < high` (bijectivity: digits round to `v`); and // - `abs(v / 10^(k-n) - d[0..n-1]) <= 1/2` (the last digit is correct). // @@ -304,7 +304,7 @@ pub fn format_exact(d: &Decoded, buf: &mut [u8], limit: i16) -> (/*#digits*/ usi // rounding up if we stop in the middle of digits // if the following digits are exactly 5000..., check the prior digit and try to - // round to even (i.e. avoid rounding up when the prior digit is even). + // round to even (i.e., avoid rounding up when the prior digit is even). let order = mant.cmp(scale.mul_small(5)); if order == Ordering::Greater || (order == Ordering::Equal && (len == 0 || buf[len-1] & 1 == 1)) { diff --git a/src/libcore/num/flt2dec/strategy/grisu.rs b/src/libcore/num/flt2dec/strategy/grisu.rs index effe073c381..3e76feca885 100644 --- a/src/libcore/num/flt2dec/strategy/grisu.rs +++ b/src/libcore/num/flt2dec/strategy/grisu.rs @@ -242,7 +242,7 @@ pub fn format_shortest_opt(d: &Decoded, // // find the digit length `kappa` between `(minus1, plus1)` as per Theorem 6.2. // Theorem 6.2 can be adopted to exclude `x` by requiring `y mod 10^k < y - x` instead. - // (e.g. `x` = 32000, `y` = 32777; `kappa` = 2 since `y mod 10^3 = 777 < y - x = 777`.) + // (e.g., `x` = 32000, `y` = 32777; `kappa` = 2 since `y mod 10^3 = 777 < y - x = 777`.) // the algorithm relies on the later verification phase to exclude `y`. let delta1 = plus1 - minus1; // let delta1int = (delta1 >> e) as usize; // only for explanation @@ -362,19 +362,19 @@ pub fn format_shortest_opt(d: &Decoded, // proceed, but we then have at least one valid representation known to be closest to // `v + 1 ulp` anyway. we will denote them as TC1 through TC3 for brevity. // - // TC1: `w(n) <= v + 1 ulp`, i.e. this is the last repr that can be the closest one. + // TC1: `w(n) <= v + 1 ulp`, i.e., this is the last repr that can be the closest one. // this is equivalent to `plus1 - w(n) = plus1w(n) >= plus1 - (v + 1 ulp) = plus1v_up`. // combined with TC2 (which checks if `w(n+1)` is valid), this prevents the possible // overflow on the calculation of `plus1w(n)`. // - // TC2: `w(n+1) < minus1`, i.e. the next repr definitely does not round to `v`. + // TC2: `w(n+1) < minus1`, i.e., the next repr definitely does not round to `v`. // this is equivalent to `plus1 - w(n) + 10^kappa = plus1w(n) + 10^kappa > // plus1 - minus1 = threshold`. the left hand side can overflow, but we know // `threshold > plus1v`, so if TC1 is false, `threshold - plus1w(n) > // threshold - (plus1v - 1 ulp) > 1 ulp` and we can safely test if // `threshold - plus1w(n) < 10^kappa` instead. // - // TC3: `abs(w(n) - (v + 1 ulp)) <= abs(w(n+1) - (v + 1 ulp))`, i.e. the next repr is + // TC3: `abs(w(n) - (v + 1 ulp)) <= abs(w(n+1) - (v + 1 ulp))`, i.e., the next repr is // no closer to `v + 1 ulp` than the current repr. given `z(n) = plus1v_up - plus1w(n)`, // this becomes `abs(z(n)) <= abs(z(n+1))`. again assuming that TC1 is false, we have // `z(n) > 0`. we have two cases to consider: @@ -384,7 +384,7 @@ pub fn format_shortest_opt(d: &Decoded, // - when `z(n+1) < 0`: // - TC3a: the precondition is `plus1v_up < plus1w(n) + 10^kappa`. assuming TC2 is // false, `threshold >= plus1w(n) + 10^kappa` so it cannot overflow. - // - TC3b: TC3 becomes `z(n) <= -z(n+1)`, i.e. `plus1v_up - plus1w(n) >= + // - TC3b: TC3 becomes `z(n) <= -z(n+1)`, i.e., `plus1v_up - plus1w(n) >= // plus1w(n+1) - plus1v_up = plus1w(n) + 10^kappa - plus1v_up`. the negated TC1 // gives `plus1v_up > plus1w(n)`, so it cannot overflow or underflow when // combined with TC3a. @@ -414,7 +414,7 @@ pub fn format_shortest_opt(d: &Decoded, // now we have the closest representation to `v` between `plus1` and `minus1`. // this is too liberal, though, so we reject any `w(n)` not between `plus0` and `minus0`, - // i.e. `plus1 - plus1w(n) <= minus0` or `plus1 - plus1w(n) >= plus0`. we utilize the facts + // i.e., `plus1 - plus1w(n) <= minus0` or `plus1 - plus1w(n) >= plus0`. we utilize the facts // that `threshold = plus1 - minus1` and `plus1 - plus0 = minus0 - minus1 = 2 ulp`. if 2 * ulp <= plus1w && plus1w <= threshold - 4 * ulp { Some((buf.len(), exp)) @@ -675,7 +675,7 @@ pub fn format_exact_opt(d: &Decoded, buf: &mut [u8], limit: i16) return Some((len, exp)); } - // otherwise we are doomed (i.e. some values between `v - 1 ulp` and `v + 1 ulp` are + // otherwise we are doomed (i.e., some values between `v - 1 ulp` and `v + 1 ulp` are // rounding down and others are rounding up) and give up. None } diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 805be431328..7ffb81901c6 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -78,7 +78,7 @@ assert_eq!(size_of::>(), size_of::<", st #[inline] pub fn new(n: $Int) -> Option { if n != 0 { - Some($Ty(NonZero(n))) + Some($Ty(unsafe { NonZero(n) })) } else { None } @@ -673,7 +673,7 @@ $EndFeature, " } doc_comment! { - concat!("Checked Euclidean division. Computes `self.div_euc(rhs)`, + concat!("Checked Euclidean division. Computes `self.div_euclid(rhs)`, returning `None` if `rhs == 0` or the division results in overflow. # Examples @@ -683,17 +683,17 @@ Basic usage: ``` #![feature(euclidean_division)] assert_eq!((", stringify!($SelfT), -"::min_value() + 1).checked_div_euc(-1), Some(", stringify!($Max), ")); -assert_eq!(", stringify!($SelfT), "::min_value().checked_div_euc(-1), None); -assert_eq!((1", stringify!($SelfT), ").checked_div_euc(0), None); +"::min_value() + 1).checked_div_euclid(-1), Some(", stringify!($Max), ")); +assert_eq!(", stringify!($SelfT), "::min_value().checked_div_euclid(-1), None); +assert_eq!((1", stringify!($SelfT), ").checked_div_euclid(0), None); ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] - pub fn checked_div_euc(self, rhs: Self) -> Option { + pub fn checked_div_euclid(self, rhs: Self) -> Option { if rhs == 0 || (self == Self::min_value() && rhs == -1) { None } else { - Some(self.div_euc(rhs)) + Some(self.div_euclid(rhs)) } } } @@ -726,8 +726,8 @@ $EndFeature, " } doc_comment! { - concat!("Checked Euclidean modulo. Computes `self.mod_euc(rhs)`, returning `None` if -`rhs == 0` or the division results in overflow. + concat!("Checked Euclidean remainder. Computes `self.rem_euclid(rhs)`, returning `None` +if `rhs == 0` or the division results in overflow. # Examples @@ -737,17 +737,17 @@ Basic usage: #![feature(euclidean_division)] use std::", stringify!($SelfT), "; -assert_eq!(5", stringify!($SelfT), ".checked_mod_euc(2), Some(1)); -assert_eq!(5", stringify!($SelfT), ".checked_mod_euc(0), None); -assert_eq!(", stringify!($SelfT), "::MIN.checked_mod_euc(-1), None); +assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(2), Some(1)); +assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None); +assert_eq!(", stringify!($SelfT), "::MIN.checked_rem_euclid(-1), None); ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] - pub fn checked_mod_euc(self, rhs: Self) -> Option { + pub fn checked_rem_euclid(self, rhs: Self) -> Option { if rhs == 0 || (self == Self::min_value() && rhs == -1) { None } else { - Some(self.mod_euc(rhs)) + Some(self.rem_euclid(rhs)) } } } @@ -1089,7 +1089,7 @@ $EndFeature, " } doc_comment! { - concat!("Wrapping Euclidean division. Computes `self.div_euc(rhs)`, + concat!("Wrapping Euclidean division. Computes `self.div_euclid(rhs)`, wrapping around at the boundary of the type. Wrapping will only occur in `MIN / -1` on a signed type (where `MIN` is the negative minimal value @@ -1106,13 +1106,13 @@ Basic usage: ``` #![feature(euclidean_division)] -assert_eq!(100", stringify!($SelfT), ".wrapping_div_euc(10), 10); -assert_eq!((-128i8).wrapping_div_euc(-1), -128); +assert_eq!(100", stringify!($SelfT), ".wrapping_div_euclid(10), 10); +assert_eq!((-128i8).wrapping_div_euclid(-1), -128); ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] - pub fn wrapping_div_euc(self, rhs: Self) -> Self { - self.overflowing_div_euc(rhs).0 + pub fn wrapping_div_euclid(self, rhs: Self) -> Self { + self.overflowing_div_euclid(rhs).0 } } @@ -1145,8 +1145,8 @@ $EndFeature, " } doc_comment! { - concat!("Wrapping Euclidean modulo. Computes `self.mod_euc(rhs)`, wrapping around at the -boundary of the type. + concat!("Wrapping Euclidean remainder. Computes `self.rem_euclid(rhs)`, wrapping around +at the boundary of the type. Wrapping will only occur in `MIN % -1` on a signed type (where `MIN` is the negative minimal value for the type). In this case, this method returns 0. @@ -1161,13 +1161,13 @@ Basic usage: ``` #![feature(euclidean_division)] -assert_eq!(100", stringify!($SelfT), ".wrapping_mod_euc(10), 0); -assert_eq!((-128i8).wrapping_mod_euc(-1), 0); +assert_eq!(100", stringify!($SelfT), ".wrapping_rem_euclid(10), 0); +assert_eq!((-128i8).wrapping_rem_euclid(-1), 0); ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] - pub fn wrapping_mod_euc(self, rhs: Self) -> Self { - self.overflowing_mod_euc(rhs).0 + pub fn wrapping_rem_euclid(self, rhs: Self) -> Self { + self.overflowing_rem_euclid(rhs).0 } } @@ -1442,7 +1442,7 @@ $EndFeature, " } doc_comment! { - concat!("Calculates the quotient of Euclidean division `self.div_euc(rhs)`. + concat!("Calculates the quotient of Euclidean division `self.div_euclid(rhs)`. Returns a tuple of the divisor along with a boolean indicating whether an arithmetic overflow would occur. If an overflow would occur then `self` is returned. @@ -1459,17 +1459,17 @@ Basic usage: #![feature(euclidean_division)] use std::", stringify!($SelfT), "; -assert_eq!(5", stringify!($SelfT), ".overflowing_div_euc(2), (2, false)); -assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div_euc(-1), (", stringify!($SelfT), +assert_eq!(5", stringify!($SelfT), ".overflowing_div_euclid(2), (2, false)); +assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div_euclid(-1), (", stringify!($SelfT), "::MIN, true)); ```"), #[inline] #[unstable(feature = "euclidean_division", issue = "49048")] - pub fn overflowing_div_euc(self, rhs: Self) -> (Self, bool) { + pub fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { if self == Self::min_value() && rhs == -1 { (self, true) } else { - (self.div_euc(rhs), false) + (self.div_euclid(rhs), false) } } } @@ -1508,7 +1508,7 @@ $EndFeature, " doc_comment! { - concat!("Calculates the remainder `self.mod_euc(rhs)` by Euclidean division. + concat!("Overflowing Euclidean remainder. Calculates `self.rem_euclid(rhs)`. Returns a tuple of the remainder after dividing along with a boolean indicating whether an arithmetic overflow would occur. If an overflow would occur then 0 is returned. @@ -1525,16 +1525,16 @@ Basic usage: #![feature(euclidean_division)] use std::", stringify!($SelfT), "; -assert_eq!(5", stringify!($SelfT), ".overflowing_mod_euc(2), (1, false)); -assert_eq!(", stringify!($SelfT), "::MIN.overflowing_mod_euc(-1), (0, true)); +assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false)); +assert_eq!(", stringify!($SelfT), "::MIN.overflowing_rem_euclid(-1), (0, true)); ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] - pub fn overflowing_mod_euc(self, rhs: Self) -> (Self, bool) { + pub fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { if self == Self::min_value() && rhs == -1 { (0, true) } else { - (self.mod_euc(rhs), false) + (self.rem_euclid(rhs), false) } } } @@ -1544,7 +1544,7 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_mod_euc(-1), (0, true)); concat!("Negates self, overflowing if this is equal to the minimum value. Returns a tuple of the negated version of self along with a boolean indicating whether an overflow -happened. If `self` is the minimum value (e.g. `i32::MIN` for values of type `i32`), then the +happened. If `self` is the minimum value (e.g., `i32::MIN` for values of type `i32`), then the minimum value will be returned again and `true` will be returned for an overflow happening. # Examples @@ -1621,7 +1621,7 @@ $EndFeature, " concat!("Computes the absolute value of `self`. Returns a tuple of the absolute version of self along with a boolean indicating whether an overflow -happened. If self is the minimum value (e.g. ", stringify!($SelfT), "::MIN for values of type +happened. If self is the minimum value (e.g., ", stringify!($SelfT), "::MIN for values of type ", stringify!($SelfT), "), then the minimum value will be returned again and true will be returned for an overflow happening. @@ -1739,9 +1739,13 @@ $EndFeature, " doc_comment! { concat!("Calculates the quotient of Euclidean division of `self` by `rhs`. -This computes the integer `n` such that `self = n * rhs + self.mod_euc(rhs)`. +This computes the integer `n` such that `self = n * rhs + self.rem_euclid(rhs)`, +with `0 <= self.rem_euclid(rhs) < rhs`. + In other words, the result is `self / rhs` rounded to the integer `n` such that `self >= n * rhs`. +If `self > 0`, this is equal to round towards zero (the default in Rust); +if `self < 0`, this is equal to round towards +/- infinity. # Panics @@ -1756,15 +1760,15 @@ Basic usage: let a: ", stringify!($SelfT), " = 7; // or any other integer type let b = 4; -assert_eq!(a.div_euc(b), 1); // 7 >= 4 * 1 -assert_eq!(a.div_euc(-b), -1); // 7 >= -4 * -1 -assert_eq!((-a).div_euc(b), -2); // -7 >= 4 * -2 -assert_eq!((-a).div_euc(-b), 2); // -7 >= -4 * 2 +assert_eq!(a.div_euclid(b), 1); // 7 >= 4 * 1 +assert_eq!(a.div_euclid(-b), -1); // 7 >= -4 * -1 +assert_eq!((-a).div_euclid(b), -2); // -7 >= 4 * -2 +assert_eq!((-a).div_euclid(-b), 2); // -7 >= -4 * 2 ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] #[rustc_inherit_overflow_checks] - pub fn div_euc(self, rhs: Self) -> Self { + pub fn div_euclid(self, rhs: Self) -> Self { let q = self / rhs; if self % rhs < 0 { return if rhs > 0 { q - 1 } else { q + 1 } @@ -1775,9 +1779,11 @@ assert_eq!((-a).div_euc(-b), 2); // -7 >= -4 * 2 doc_comment! { - concat!("Calculates the remainder `self mod rhs` by Euclidean division. + concat!("Calculates the least nonnegative remainder of `self (mod rhs)`. -In particular, the result `n` satisfies `0 <= n < rhs.abs()`. +This is done as if by the Euclidean division algorithm -- given +`r = self.rem_euclid(rhs)`, `self = rhs * self.div_euclid(rhs) + r`, and +`0 <= r < abs(rhs)`. # Panics @@ -1792,15 +1798,15 @@ Basic usage: let a: ", stringify!($SelfT), " = 7; // or any other integer type let b = 4; -assert_eq!(a.mod_euc(b), 3); -assert_eq!((-a).mod_euc(b), 1); -assert_eq!(a.mod_euc(-b), 3); -assert_eq!((-a).mod_euc(-b), 1); +assert_eq!(a.rem_euclid(b), 3); +assert_eq!((-a).rem_euclid(b), 1); +assert_eq!(a.rem_euclid(-b), 3); +assert_eq!((-a).rem_euclid(-b), 1); ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] #[rustc_inherit_overflow_checks] - pub fn mod_euc(self, rhs: Self) -> Self { + pub fn rem_euclid(self, rhs: Self) -> Self { let r = self % rhs; if r < 0 { if rhs < 0 { @@ -2150,19 +2156,6 @@ impl isize { "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]" } } -// Emits the correct `cttz` call, depending on the size of the type. -macro_rules! uint_cttz_call { - // As of LLVM 3.6 the codegen for the zero-safe cttz8 intrinsic - // emits two conditional moves on x86_64. By promoting the value to - // u16 and setting bit 8, we get better code without any conditional - // operations. - // FIXME: There's a LLVM patch (http://reviews.llvm.org/D9284) - // pending, remove this workaround once LLVM generates better code - // for cttz8. - ($value:expr, 8) => { intrinsics::cttz($value as u16 | 0x100) }; - ($value:expr, $_BITS:expr) => { intrinsics::cttz($value) } -} - // `Int` + `UnsignedInt` implemented for unsigned integers macro_rules! uint_impl { ($SelfT:ty, $ActualT:ty, $BITS:expr, $MaxV:expr, $Feature:expr, $EndFeature:expr, @@ -2306,7 +2299,7 @@ assert_eq!(n.trailing_zeros(), 3);", $EndFeature, " #[rustc_const_unstable(feature = "const_int_ops")] #[inline] pub const fn trailing_zeros(self) -> u32 { - unsafe { uint_cttz_call!(self, $BITS) as u32 } + unsafe { intrinsics::cttz(self) as u32 } } } @@ -2330,12 +2323,7 @@ assert_eq!(n.rotate_left(", $rot, "), m); #[rustc_const_unstable(feature = "const_int_rotate")] #[inline] pub const fn rotate_left(self, n: u32) -> Self { - #[cfg(not(stage0))] { - unsafe { intrinsics::rotate_left(self, n as $SelfT) } - } - #[cfg(stage0)] { - (self << (n % $BITS)) | (self >> (($BITS - (n % $BITS)) % $BITS)) - } + unsafe { intrinsics::rotate_left(self, n as $SelfT) } } } @@ -2360,12 +2348,7 @@ assert_eq!(n.rotate_right(", $rot, "), m); #[rustc_const_unstable(feature = "const_int_rotate")] #[inline] pub const fn rotate_right(self, n: u32) -> Self { - #[cfg(not(stage0))] { - unsafe { intrinsics::rotate_right(self, n as $SelfT) } - } - #[cfg(stage0)] { - (self >> (n % $BITS)) | (self << (($BITS - (n % $BITS)) % $BITS)) - } + unsafe { intrinsics::rotate_right(self, n as $SelfT) } } } @@ -2634,7 +2617,7 @@ assert_eq!(1", stringify!($SelfT), ".checked_div(0), None);", $EndFeature, " } doc_comment! { - concat!("Checked Euclidean division. Computes `self.div_euc(rhs)`, returning `None` + concat!("Checked Euclidean division. Computes `self.div_euclid(rhs)`, returning `None` if `rhs == 0`. # Examples @@ -2643,16 +2626,16 @@ Basic usage: ``` #![feature(euclidean_division)] -assert_eq!(128", stringify!($SelfT), ".checked_div(2), Some(64)); -assert_eq!(1", stringify!($SelfT), ".checked_div_euc(0), None); +assert_eq!(128", stringify!($SelfT), ".checked_div_euclid(2), Some(64)); +assert_eq!(1", stringify!($SelfT), ".checked_div_euclid(0), None); ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] - pub fn checked_div_euc(self, rhs: Self) -> Option { + pub fn checked_div_euclid(self, rhs: Self) -> Option { if rhs == 0 { None } else { - Some(self.div_euc(rhs)) + Some(self.div_euclid(rhs)) } } } @@ -2682,7 +2665,7 @@ assert_eq!(5", stringify!($SelfT), ".checked_rem(0), None);", $EndFeature, " } doc_comment! { - concat!("Checked Euclidean modulo. Computes `self.mod_euc(rhs)`, returning `None` + concat!("Checked Euclidean modulo. Computes `self.rem_euclid(rhs)`, returning `None` if `rhs == 0`. # Examples @@ -2691,16 +2674,16 @@ Basic usage: ``` #![feature(euclidean_division)] -assert_eq!(5", stringify!($SelfT), ".checked_mod_euc(2), Some(1)); -assert_eq!(5", stringify!($SelfT), ".checked_mod_euc(0), None); +assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(2), Some(1)); +assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None); ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] - pub fn checked_mod_euc(self, rhs: Self) -> Option { + pub fn checked_rem_euclid(self, rhs: Self) -> Option { if rhs == 0 { None } else { - Some(self.mod_euc(rhs)) + Some(self.rem_euclid(rhs)) } } } @@ -2988,11 +2971,14 @@ Basic usage: } doc_comment! { - concat!("Wrapping Euclidean division. Computes `self.div_euc(rhs)`. + concat!("Wrapping Euclidean division. Computes `self.div_euclid(rhs)`. Wrapped division on unsigned types is just normal division. There's no way wrapping could ever happen. This function exists, so that all operations are accounted for in the wrapping operations. +Since, for the positive integers, all common +definitions of division are equal, this +is exactly equal to `self.wrapping_div(rhs)`. # Examples @@ -3000,11 +2986,11 @@ Basic usage: ``` #![feature(euclidean_division)] -assert_eq!(100", stringify!($SelfT), ".wrapping_div_euc(10), 10); +assert_eq!(100", stringify!($SelfT), ".wrapping_div_euclid(10), 10); ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] - pub fn wrapping_div_euc(self, rhs: Self) -> Self { + pub fn wrapping_div_euclid(self, rhs: Self) -> Self { self / rhs } } @@ -3032,12 +3018,15 @@ Basic usage: } doc_comment! { - concat!("Wrapping Euclidean modulo. Computes `self.mod_euc(rhs)`. + concat!("Wrapping Euclidean modulo. Computes `self.rem_euclid(rhs)`. Wrapped modulo calculation on unsigned types is just the regular remainder calculation. There's no way wrapping could ever happen. This function exists, so that all operations are accounted for in the wrapping operations. +Since, for the positive integers, all common +definitions of division are equal, this +is exactly equal to `self.wrapping_rem(rhs)`. # Examples @@ -3045,11 +3034,11 @@ Basic usage: ``` #![feature(euclidean_division)] -assert_eq!(100", stringify!($SelfT), ".wrapping_mod_euc(10), 0); +assert_eq!(100", stringify!($SelfT), ".wrapping_rem_euclid(10), 0); ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] - pub fn wrapping_mod_euc(self, rhs: Self) -> Self { + pub fn wrapping_rem_euclid(self, rhs: Self) -> Self { self % rhs } } @@ -3293,12 +3282,15 @@ Basic usage } doc_comment! { - concat!("Calculates the quotient of Euclidean division `self.div_euc(rhs)`. + concat!("Calculates the quotient of Euclidean division `self.div_euclid(rhs)`. Returns a tuple of the divisor along with a boolean indicating whether an arithmetic overflow would occur. Note that for unsigned integers overflow never occurs, so the second value is always `false`. +Since, for the positive integers, all common +definitions of division are equal, this +is exactly equal to `self.overflowing_div(rhs)`. # Panics @@ -3310,11 +3302,11 @@ Basic usage ``` #![feature(euclidean_division)] -assert_eq!(5", stringify!($SelfT), ".overflowing_div_euc(2), (2, false)); +assert_eq!(5", stringify!($SelfT), ".overflowing_div_euclid(2), (2, false)); ```"), #[inline] #[unstable(feature = "euclidean_division", issue = "49048")] - pub fn overflowing_div_euc(self, rhs: Self) -> (Self, bool) { + pub fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { (self / rhs, false) } } @@ -3346,12 +3338,15 @@ Basic usage } doc_comment! { - concat!("Calculates the remainder `self.mod_euc(rhs)` by Euclidean division. + concat!("Calculates the remainder `self.rem_euclid(rhs)` as if by Euclidean division. Returns a tuple of the modulo after dividing along with a boolean indicating whether an arithmetic overflow would occur. Note that for unsigned integers overflow never occurs, so the second value is always `false`. +Since, for the positive integers, all common +definitions of division are equal, this operation +is exactly equal to `self.overflowing_rem(rhs)`. # Panics @@ -3363,11 +3358,11 @@ Basic usage ``` #![feature(euclidean_division)] -assert_eq!(5", stringify!($SelfT), ".overflowing_mod_euc(2), (1, false)); +assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false)); ```"), #[inline] #[unstable(feature = "euclidean_division", issue = "49048")] - pub fn overflowing_mod_euc(self, rhs: Self) -> (Self, bool) { + pub fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { (self % rhs, false) } } @@ -3534,7 +3529,9 @@ Basic usage: doc_comment! { concat!("Performs Euclidean division. -For unsigned types, this is just the same as `self / rhs`. +Since, for the positive integers, all common +definitions of division are equal, this +is exactly equal to `self / rhs`. # Examples @@ -3542,21 +3539,23 @@ Basic usage: ``` #![feature(euclidean_division)] -assert_eq!(7", stringify!($SelfT), ".div_euc(4), 1); // or any other integer type +assert_eq!(7", stringify!($SelfT), ".div_euclid(4), 1); // or any other integer type ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] #[rustc_inherit_overflow_checks] - pub fn div_euc(self, rhs: Self) -> Self { + pub fn div_euclid(self, rhs: Self) -> Self { self / rhs } } doc_comment! { - concat!("Calculates the remainder `self mod rhs` by Euclidean division. + concat!("Calculates the least remainder of `self (mod rhs)`. -For unsigned types, this is just the same as `self % rhs`. +Since, for the positive integers, all common +definitions of division are equal, this +is exactly equal to `self % rhs`. # Examples @@ -3564,12 +3563,12 @@ Basic usage: ``` #![feature(euclidean_division)] -assert_eq!(7", stringify!($SelfT), ".mod_euc(4), 3); // or any other integer type +assert_eq!(7", stringify!($SelfT), ".rem_euclid(4), 3); // or any other integer type ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] #[rustc_inherit_overflow_checks] - pub fn mod_euc(self, rhs: Self) -> Self { + pub fn rem_euclid(self, rhs: Self) -> Self { self % rhs } } @@ -3617,7 +3616,7 @@ assert!(!10", stringify!($SelfT), ".is_power_of_two());", $EndFeature, " doc_comment! { concat!("Returns the smallest power of two greater than or equal to `self`. -When return value overflows (i.e. `self > (1 << (N-1))` for type +When return value overflows (i.e., `self > (1 << (N-1))` for type `uN`), it panics in debug mode and return value is wrapped to 0 in release mode (the only situation in which method can return 0). @@ -4827,7 +4826,7 @@ fn from_str_radix(src: &str, radix: u32) -> Result (1 << (N-1))` for type +When return value overflows (i.e., `self > (1 << (N-1))` for type `uN`), overflows to `2^N = 0`. # Examples diff --git a/src/libcore/ops/deref.rs b/src/libcore/ops/deref.rs index 91a3d77e8b2..ff836f4aa69 100644 --- a/src/libcore/ops/deref.rs +++ b/src/libcore/ops/deref.rs @@ -177,3 +177,19 @@ pub trait DerefMut: Deref { impl DerefMut for &mut T { fn deref_mut(&mut self) -> &mut T { *self } } + +/// Indicates that a struct can be used as a method receiver, without the +/// `arbitrary_self_types` feature. This is implemented by stdlib pointer types like `Box`, +/// `Rc`, `&T`, and `Pin

`. +#[cfg_attr(not(stage0), lang = "receiver")] +#[unstable(feature = "receiver_trait", issue = "0")] +#[doc(hidden)] +pub trait Receiver { + // Empty. +} + +#[unstable(feature = "receiver_trait", issue = "0")] +impl Receiver for &T {} + +#[unstable(feature = "receiver_trait", issue = "0")] +impl Receiver for &mut T {} diff --git a/src/libcore/ops/function.rs b/src/libcore/ops/function.rs index c9591c3f57b..3b356b9a1e7 100644 --- a/src/libcore/ops/function.rs +++ b/src/libcore/ops/function.rs @@ -26,7 +26,7 @@ /// is expected. /// /// Use `Fn` as a bound when you want to accept a parameter of function-like -/// type and need to call it repeatedly and without mutating state (e.g. when +/// type and need to call it repeatedly and without mutating state (e.g., when /// calling it concurrently). If you do not need such strict requirements, use /// [`FnMut`] or [`FnOnce`] as bounds. /// @@ -72,6 +72,7 @@ label="expected an `Fn<{Args}>` closure, found `{Self}`", )] #[fundamental] // so that regex can rely that `&str: !FnMut` +#[must_use] pub trait Fn : FnMut { /// Performs the call operation. #[unstable(feature = "fn_traits", issue = "29625")] @@ -84,7 +85,7 @@ pub trait Fn : FnMut { /// /// `FnMut` is implemented automatically by closures which take mutable /// references to captured variables, as well as all types that implement -/// [`Fn`], e.g. (safe) [function pointers][] (since `FnMut` is a supertrait of +/// [`Fn`], e.g., (safe) [function pointers][] (since `FnMut` is a supertrait of /// [`Fn`]). Additionally, for any type `F` that implements `FnMut`, `&mut F` /// implements `FnMut`, too. /// @@ -150,6 +151,7 @@ pub trait Fn : FnMut { label="expected an `FnMut<{Args}>` closure, found `{Self}`", )] #[fundamental] // so that regex can rely that `&str: !FnMut` +#[must_use] pub trait FnMut : FnOnce { /// Performs the call operation. #[unstable(feature = "fn_traits", issue = "29625")] @@ -163,7 +165,7 @@ pub trait FnMut : FnOnce { /// implements `FnOnce`, it can only be called once. /// /// `FnOnce` is implemented automatically by closure that might consume captured -/// variables, as well as all types that implement [`FnMut`], e.g. (safe) +/// variables, as well as all types that implement [`FnMut`], e.g., (safe) /// [function pointers][] (since `FnOnce` is a supertrait of [`FnMut`]). /// /// Since both [`Fn`] and [`FnMut`] are subtraits of `FnOnce`, any instance of @@ -228,6 +230,7 @@ pub trait FnMut : FnOnce { label="expected an `FnOnce<{Args}>` closure, found `{Self}`", )] #[fundamental] // so that regex can rely that `&str: !FnMut` +#[must_use] pub trait FnOnce { /// The returned type after the call operator is used. #[stable(feature = "fn_once_output", since = "1.12.0")] diff --git a/src/libcore/ops/mod.rs b/src/libcore/ops/mod.rs index edfa6df11ac..06740d2e4cd 100644 --- a/src/libcore/ops/mod.rs +++ b/src/libcore/ops/mod.rs @@ -27,7 +27,7 @@ //! should have some resemblance to multiplication (and share expected //! properties like associativity). //! -//! Note that the `&&` and `||` operators short-circuit, i.e. they only +//! Note that the `&&` and `||` operators short-circuit, i.e., they only //! evaluate their second operand if it contributes to the result. Since this //! behavior is not enforceable by traits, `&&` and `||` are not supported as //! overloadable operators. @@ -178,6 +178,9 @@ pub use self::bit::{BitAndAssign, BitOrAssign, BitXorAssign, ShlAssign, ShrAssig #[stable(feature = "rust1", since = "1.0.0")] pub use self::deref::{Deref, DerefMut}; +#[unstable(feature = "receiver_trait", issue = "0")] +pub use self::deref::Receiver; + #[stable(feature = "rust1", since = "1.0.0")] pub use self::drop::Drop; diff --git a/src/libcore/ops/unsize.rs b/src/libcore/ops/unsize.rs index 4d9a40a1b90..e86a392a2c8 100644 --- a/src/libcore/ops/unsize.rs +++ b/src/libcore/ops/unsize.rs @@ -93,7 +93,7 @@ impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} /// {} /// ``` #[unstable(feature = "dispatch_from_dyn", issue = "0")] -#[cfg_attr(not(stage0), lang = "dispatch_from_dyn")] +#[lang = "dispatch_from_dyn"] pub trait DispatchFromDyn { // Empty. } diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 67bed63e6ff..3147b21f86b 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -62,7 +62,7 @@ //! The following example uses [`Option`] to create an optional box of //! [`i32`]. Notice that in order to use the inner [`i32`] value first, the //! `check_optional` function needs to use pattern matching to -//! determine whether the box has a value (i.e. it is [`Some(...)`][`Some`]) or +//! determine whether the box has a value (i.e., it is [`Some(...)`][`Some`]) or //! not ([`None`]). //! //! ``` diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 308dd9c79fa..521ce9b5f6b 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -7,23 +7,33 @@ //! 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. +//! By default, all types in Rust are movable. Rust allows passing all types by-value, +//! and common smart-pointer types such as `Box`, `Rc`, and `&mut` allow replacing and +//! moving the values they contain. In order to prevent objects from moving, they must +//! be pinned by wrapping a pointer to the data in the [`Pin`] type. +//! Doing this prohibits moving the value behind the pointer. +//! For example, `Pin>` functions much like a regular `Box`, +//! but doesn't allow moving `T`. The pointer value itself (the `Box`) can still be moved, +//! but the value behind it cannot. //! -//! 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. +//! Since data can be moved out of `&mut` and `Box` with functions such as [`swap`], +//! changing the location of the underlying data, [`Pin`] prohibits accessing the +//! underlying pointer type (the `&mut` or `Box`) directly, and provides its own set of +//! APIs for accessing and using the value. [`Pin`] also guarantees that no other +//! functions will move the pointed-to value. This allows for the creation of +//! self-references and other special behaviors that are only possible for unmovable +//! values. //! -//! 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. +//! However, these restrictions are usually not necessary. Many types are always freely +//! movable. These types implement the [`Unpin`] auto-trait, which nullifies the affect +//! of [`Pin`]. For `T: Unpin`, `Pin>` and `Box` function identically, as do +//! `Pin<&mut T>` and `&mut T`. +//! +//! Note that pinning and `Unpin` only affect the pointed-to type. For example, whether +//! or not `Box` is `Unpin` has no affect on the behavior of `Pin>`. Similarly, +//! `Pin>` and `Pin<&mut T>` are always `Unpin` themselves, even though the +//! `T` underneath them isn't, because the pointers in `Pin>` and `Pin<&mut _>` +//! are always freely movable, even if the data they point to isn't. //! //! [`Pin`]: struct.Pin.html //! [`Unpin`]: trait.Unpin.html @@ -36,7 +46,7 @@ //! #![feature(pin)] //! //! use std::pin::Pin; -//! use std::marker::Pinned; +//! use std::marker::PhantomPinned; //! use std::ptr::NonNull; //! //! // This is a self-referential struct since the slice field points to the data field. @@ -47,7 +57,7 @@ //! struct Unmovable { //! data: String, //! slice: NonNull, -//! _pin: Pinned, +//! _pin: PhantomPinned, //! } //! //! impl Unmovable { @@ -60,7 +70,7 @@ //! // 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, +//! _pin: PhantomPinned, //! }; //! let mut boxed = Box::pinned(res); //! @@ -91,7 +101,7 @@ use fmt; use marker::Sized; -use ops::{Deref, DerefMut, CoerceUnsized, DispatchFromDyn}; +use ops::{Deref, DerefMut, Receiver, CoerceUnsized, DispatchFromDyn}; #[doc(inline)] pub use marker::Unpin; @@ -292,6 +302,9 @@ where } } +#[unstable(feature = "receiver_trait", issue = "0")] +impl Receiver for Pin

{} + #[unstable(feature = "pin", issue = "49150")] impl fmt::Debug for Pin

{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index d3a74ed2a68..b3c93ae1fa7 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -103,7 +103,7 @@ pub use intrinsics::write_bytes; /// dropped normally. /// /// * It is friendlier to the optimizer to do this over [`ptr::read`] when -/// dropping manually allocated memory (e.g. when writing Box/Rc/Vec), +/// dropping manually allocated memory (e.g., when writing Box/Rc/Vec), /// as the compiler doesn't need to prove that it's sound to elide the /// copy. /// @@ -836,7 +836,7 @@ pub unsafe fn write_unaligned(dst: *mut T, src: T) { /// /// The compiler shouldn't change the relative order or number of volatile /// memory operations. However, volatile memory operations on zero-sized types -/// (e.g. if a zero-sized type is passed to `read_volatile`) are no-ops +/// (e.g., if a zero-sized type is passed to `read_volatile`) are no-ops /// and may be ignored. /// /// [c11]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf @@ -913,7 +913,7 @@ pub unsafe fn read_volatile(src: *const T) -> T { /// /// The compiler shouldn't change the relative order or number of volatile /// memory operations. However, volatile memory operations on zero-sized types -/// (e.g. if a zero-sized type is passed to `write_volatile`) are no-ops +/// (e.g., if a zero-sized type is passed to `write_volatile`) are no-ops /// and may be ignored. /// /// [c11]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf @@ -1035,7 +1035,7 @@ impl *const T { /// Calculates the offset from a pointer. /// - /// `count` is in units of T; e.g. a `count` of 3 represents a pointer + /// `count` is in units of T; e.g., a `count` of 3 represents a pointer /// offset of `3 * size_of::()` bytes. /// /// # Safety @@ -1089,7 +1089,7 @@ impl *const T { /// Calculates the offset from a pointer using wrapping arithmetic. /// - /// `count` is in units of T; e.g. a `count` of 3 represents a pointer + /// `count` is in units of T; e.g., a `count` of 3 represents a pointer /// offset of `3 * size_of::()` bytes. /// /// # Safety @@ -1253,7 +1253,7 @@ impl *const T { /// Calculates the offset from a pointer (convenience for `.offset(count as isize)`). /// - /// `count` is in units of T; e.g. a `count` of 3 represents a pointer + /// `count` is in units of T; e.g., a `count` of 3 represents a pointer /// offset of `3 * size_of::()` bytes. /// /// # Safety @@ -1310,7 +1310,7 @@ impl *const T { /// Calculates the offset from a pointer (convenience for /// `.offset((count as isize).wrapping_neg())`). /// - /// `count` is in units of T; e.g. a `count` of 3 represents a pointer + /// `count` is in units of T; e.g., a `count` of 3 represents a pointer /// offset of `3 * size_of::()` bytes. /// /// # Safety @@ -1367,7 +1367,7 @@ impl *const T { /// Calculates the offset from a pointer using wrapping arithmetic. /// (convenience for `.wrapping_offset(count as isize)`) /// - /// `count` is in units of T; e.g. a `count` of 3 represents a pointer + /// `count` is in units of T; e.g., a `count` of 3 represents a pointer /// offset of `3 * size_of::()` bytes. /// /// # Safety @@ -1408,7 +1408,7 @@ impl *const T { /// Calculates the offset from a pointer using wrapping arithmetic. /// (convenience for `.wrapping_offset((count as isize).wrapping_sub())`) /// - /// `count` is in units of T; e.g. a `count` of 3 represents a pointer + /// `count` is in units of T; e.g., a `count` of 3 represents a pointer /// offset of `3 * size_of::()` bytes. /// /// # Safety @@ -1655,7 +1655,7 @@ impl *mut T { /// Calculates the offset from a pointer. /// - /// `count` is in units of T; e.g. a `count` of 3 represents a pointer + /// `count` is in units of T; e.g., a `count` of 3 represents a pointer /// offset of `3 * size_of::()` bytes. /// /// # Safety @@ -1708,7 +1708,7 @@ impl *mut T { } /// Calculates the offset from a pointer using wrapping arithmetic. - /// `count` is in units of T; e.g. a `count` of 3 represents a pointer + /// `count` is in units of T; e.g., a `count` of 3 represents a pointer /// offset of `3 * size_of::()` bytes. /// /// # Safety @@ -1891,7 +1891,7 @@ impl *mut T { /// Calculates the offset from a pointer (convenience for `.offset(count as isize)`). /// - /// `count` is in units of T; e.g. a `count` of 3 represents a pointer + /// `count` is in units of T; e.g., a `count` of 3 represents a pointer /// offset of `3 * size_of::()` bytes. /// /// # Safety @@ -1948,7 +1948,7 @@ impl *mut T { /// Calculates the offset from a pointer (convenience for /// `.offset((count as isize).wrapping_neg())`). /// - /// `count` is in units of T; e.g. a `count` of 3 represents a pointer + /// `count` is in units of T; e.g., a `count` of 3 represents a pointer /// offset of `3 * size_of::()` bytes. /// /// # Safety @@ -2005,7 +2005,7 @@ impl *mut T { /// Calculates the offset from a pointer using wrapping arithmetic. /// (convenience for `.wrapping_offset(count as isize)`) /// - /// `count` is in units of T; e.g. a `count` of 3 represents a pointer + /// `count` is in units of T; e.g., a `count` of 3 represents a pointer /// offset of `3 * size_of::()` bytes. /// /// # Safety @@ -2046,7 +2046,7 @@ impl *mut T { /// Calculates the offset from a pointer using wrapping arithmetic. /// (convenience for `.wrapping_offset((count as isize).wrapping_sub())`) /// - /// `count` is in units of T; e.g. a `count` of 3 represents a pointer + /// `count` is in units of T; e.g., a `count` of 3 represents a pointer /// offset of `3 * size_of::()` bytes. /// /// # Safety @@ -2375,7 +2375,7 @@ pub(crate) unsafe fn align_offset(p: *const T, a: usize) -> usize { fn mod_inv(x: usize, m: usize) -> usize { /// Multiplicative modular inverse table modulo 2â´ = 16. /// - /// Note, that this table does not contain values where inverse does not exist (i.e. for + /// Note, that this table does not contain values where inverse does not exist (i.e., for /// `0â»Â¹ mod 16`, `2â»Â¹ mod 16`, etc.) const INV_TABLE_MOD_16: [u8; 8] = [1, 11, 13, 7, 9, 3, 5, 15]; /// Modulo for which the `INV_TABLE_MOD_16` is intended. @@ -2398,7 +2398,7 @@ pub(crate) unsafe fn align_offset(p: *const T, a: usize) -> usize { // y = y * (2 - xy) mod n // // Note, that we use wrapping operations here intentionally – the original formula - // uses e.g. subtraction `mod n`. It is entirely fine to do them `mod + // uses e.g., subtraction `mod n`. It is entirely fine to do them `mod // usize::max_value()` instead, because we take the result `mod n` at the end // anyway. inverse = inverse.wrapping_mul( @@ -2516,6 +2516,39 @@ pub fn eq(a: *const T, b: *const T) -> bool { a == b } +/// Hash a raw pointer. +/// +/// This can be used to hash a `&T` reference (which coerces to `*const T` implicitly) +/// by its address rather than the value it points to +/// (which is what the `Hash for &T` implementation does). +/// +/// # Examples +/// +/// ``` +/// #![feature(ptr_hash)] +/// use std::collections::hash_map::DefaultHasher; +/// use std::hash::{Hash, Hasher}; +/// use std::ptr; +/// +/// let five = 5; +/// let five_ref = &five; +/// +/// let mut hasher = DefaultHasher::new(); +/// ptr::hash(five_ref, &mut hasher); +/// let actual = hasher.finish(); +/// +/// let mut hasher = DefaultHasher::new(); +/// (five_ref as *const i32).hash(&mut hasher); +/// let expected = hasher.finish(); +/// +/// assert_eq!(actual, expected); +/// ``` +#[unstable(feature = "ptr_hash", reason = "newly added", issue = "56286")] +pub fn hash(hashee: *const T, into: &mut S) { + use hash::Hash; + hashee.hash(into); +} + // Impls for function pointers macro_rules! fnptr_impls_safety_abi { ($FnTy: ty, $($Arg: ident),*) => { @@ -2759,7 +2792,7 @@ impl Unique { /// Creates a new `Unique` if `ptr` is non-null. pub fn new(ptr: *mut T) -> Option { if !ptr.is_null() { - Some(Unique { pointer: NonZero(ptr as _), _marker: PhantomData }) + Some(Unique { pointer: unsafe { NonZero(ptr as _) }, _marker: PhantomData }) } else { None } @@ -2815,14 +2848,14 @@ impl fmt::Pointer for Unique { #[unstable(feature = "ptr_internals", issue = "0")] impl<'a, T: ?Sized> From<&'a mut T> for Unique { fn from(reference: &'a mut T) -> Self { - Unique { pointer: NonZero(reference as _), _marker: PhantomData } + Unique { pointer: unsafe { NonZero(reference as *mut T) }, _marker: PhantomData } } } #[unstable(feature = "ptr_internals", issue = "0")] impl<'a, T: ?Sized> From<&'a T> for Unique { fn from(reference: &'a T) -> Self { - Unique { pointer: NonZero(reference as _), _marker: PhantomData } + Unique { pointer: unsafe { NonZero(reference as *const T) }, _marker: PhantomData } } } @@ -2857,12 +2890,12 @@ pub struct NonNull { } /// `NonNull` pointers are not `Send` because the data they reference may be aliased. -// NB: This impl is unnecessary, but should provide better error messages. +// N.B., this impl is unnecessary, but should provide better error messages. #[stable(feature = "nonnull", since = "1.25.0")] impl !Send for NonNull { } /// `NonNull` pointers are not `Sync` because the data they reference may be aliased. -// NB: This impl is unnecessary, but should provide better error messages. +// N.B., this impl is unnecessary, but should provide better error messages. #[stable(feature = "nonnull", since = "1.25.0")] impl !Sync for NonNull { } @@ -2903,7 +2936,7 @@ impl NonNull { #[inline] pub fn new(ptr: *mut T) -> Option { if !ptr.is_null() { - Some(NonNull { pointer: NonZero(ptr as _) }) + Some(unsafe { Self::new_unchecked(ptr) }) } else { None } @@ -3025,7 +3058,7 @@ impl From> for NonNull { impl<'a, T: ?Sized> From<&'a mut T> for NonNull { #[inline] fn from(reference: &'a mut T) -> Self { - NonNull { pointer: NonZero(reference as _) } + NonNull { pointer: unsafe { NonZero(reference as *mut T) } } } } @@ -3033,6 +3066,6 @@ impl<'a, T: ?Sized> From<&'a mut T> for NonNull { impl<'a, T: ?Sized> From<&'a T> for NonNull { #[inline] fn from(reference: &'a T) -> Self { - NonNull { pointer: NonZero(reference as _) } + NonNull { pointer: unsafe { NonZero(reference as *const T) } } } } diff --git a/src/libcore/raw.rs b/src/libcore/raw.rs index 3d4bccb4f9d..4f1af8bf110 100644 --- a/src/libcore/raw.rs +++ b/src/libcore/raw.rs @@ -24,7 +24,7 @@ /// `Box`. /// /// `TraitObject` is guaranteed to match layouts, but it is not the -/// type of trait objects (e.g. the fields are not directly accessible +/// type of trait objects (e.g., the fields are not directly accessible /// on a `&SomeTrait`) nor does it control that layout (changing the /// definition will not change the layout of a `&SomeTrait`). It is /// only designed to be used by unsafe code that needs to manipulate diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 8c55a16f3c8..193061457b5 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Slice management and manipulation +//! Slice management and manipulation. //! //! For more details see [`std::slice`]. //! @@ -702,8 +702,7 @@ impl [T] { /// resulting code better than in the case of [`chunks`]. /// /// See [`chunks`] for a variant of this iterator that also returns the remainder as a smaller - /// chunk, and [`rchunks_exact`] for the same iterator but starting at the end of the slice of - /// the slice. + /// chunk, and [`rchunks_exact`] for the same iterator but starting at the end of the slice. /// /// # Panics /// @@ -878,6 +877,7 @@ impl [T] { /// assert_eq!(iter.remainder(), &['l']); /// ``` /// + /// [`chunks`]: #method.chunks /// [`rchunks`]: #method.rchunks /// [`chunks_exact`]: #method.chunks_exact #[stable(feature = "rchunks", since = "1.31.0")] @@ -922,6 +922,7 @@ impl [T] { /// assert_eq!(v, &[0, 2, 2, 1, 1]); /// ``` /// + /// [`chunks_mut`]: #method.chunks_mut /// [`rchunks_mut`]: #method.rchunks_mut /// [`chunks_exact_mut`]: #method.chunks_exact_mut #[stable(feature = "rchunks", since = "1.31.0")] @@ -1152,7 +1153,7 @@ impl [T] { /// /// # Examples /// - /// Print the slice split once by numbers divisible by 3 (i.e. `[10, 40]`, + /// Print the slice split once by numbers divisible by 3 (i.e., `[10, 40]`, /// `[20, 60, 50]`): /// /// ``` @@ -1216,7 +1217,7 @@ impl [T] { /// # Examples /// /// Print the slice split once, starting from the end, by numbers divisible - /// by 3 (i.e. `[50]`, `[10, 40, 30, 20]`): + /// by 3 (i.e., `[50]`, `[10, 40, 30, 20]`): /// /// ``` /// let v = [10, 40, 30, 20, 60, 50]; @@ -1472,8 +1473,8 @@ impl [T] { /// Sorts the slice, but may not preserve the order of equal elements. /// - /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate), - /// and `O(n log n)` worst-case. + /// This sort is unstable (i.e., may reorder equal elements), in-place + /// (i.e., does not allocate), and `O(n log n)` worst-case. /// /// # Current implementation /// @@ -1483,7 +1484,7 @@ impl [T] { /// randomization to avoid degenerate cases, but with a fixed seed to always provide /// deterministic behavior. /// - /// It is typically faster than stable sorting, except in a few special cases, e.g. when the + /// It is typically faster than stable sorting, except in a few special cases, e.g., when the /// slice consists of several concatenated sorted sequences. /// /// # Examples @@ -1507,8 +1508,8 @@ impl [T] { /// Sorts the slice with a comparator function, but may not preserve the order of equal /// elements. /// - /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate), - /// and `O(n log n)` worst-case. + /// This sort is unstable (i.e., may reorder equal elements), in-place + /// (i.e., does not allocate), and `O(n log n)` worst-case. /// /// The comparator function must define a total ordering for the elements in the slice. If /// the ordering is not total, the order of the elements is unspecified. An order is a @@ -1534,7 +1535,7 @@ impl [T] { /// randomization to avoid degenerate cases, but with a fixed seed to always provide /// deterministic behavior. /// - /// It is typically faster than stable sorting, except in a few special cases, e.g. when the + /// It is typically faster than stable sorting, except in a few special cases, e.g., when the /// slice consists of several concatenated sorted sequences. /// /// # Examples @@ -1561,8 +1562,9 @@ impl [T] { /// Sorts the slice with a key extraction function, but may not preserve the order of equal /// elements. /// - /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate), - /// and `O(m n log(m n))` worst-case, where the key function is `O(m)`. + /// This sort is unstable (i.e., may reorder equal elements), in-place + /// (i.e., does not allocate), and `O(m n log(m n))` worst-case, where the key function is + /// `O(m)`. /// /// # Current implementation /// @@ -2459,13 +2461,13 @@ impl SliceIndex<[T]> for usize { #[inline] fn index(self, slice: &[T]) -> &T { - // NB: use intrinsic indexing + // N.B., use intrinsic indexing &(*slice)[self] } #[inline] fn index_mut(self, slice: &mut [T]) -> &mut T { - // NB: use intrinsic indexing + // N.B., use intrinsic indexing &mut (*slice)[self] } } diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 89efa120a6f..4a22d929fed 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -482,7 +482,7 @@ fn utf8_first_byte(byte: u8, width: u32) -> u32 { (byte & (0x7F >> width)) as u3 #[inline] fn utf8_acc_cont_byte(ch: u32, byte: u8) -> u32 { (ch << 6) | (byte & CONT_MASK) as u32 } -/// Checks whether the byte is a UTF-8 continuation byte (i.e. starts with the +/// Checks whether the byte is a UTF-8 continuation byte (i.e., starts with the /// bits `10`). #[inline] fn utf8_is_cont_byte(byte: u8) -> bool { (byte & !CONT_MASK) == TAG_CONT_U8 } @@ -536,10 +536,9 @@ fn next_code_point_reverse<'a, I>(bytes: &mut I) -> Option where I: DoubleEndedIterator, { // Decode UTF-8 - let w = match bytes.next_back() { - None => return None, - Some(&next_byte) if next_byte < 128 => return Some(next_byte as u32), - Some(&back_byte) => back_byte, + let w = match *bytes.next_back()? { + next_byte if next_byte < 128 => return Some(next_byte as u32), + back_byte => back_byte, }; // Multibyte case follows diff --git a/src/libcore/str/pattern.rs b/src/libcore/str/pattern.rs index 1c974533e10..2059160ddfe 100644 --- a/src/libcore/str/pattern.rs +++ b/src/libcore/str/pattern.rs @@ -397,7 +397,7 @@ unsafe impl<'a> ReverseSearcher<'a> for CharSearcher<'a> { let found_char = index - shift; if let Some(slice) = haystack.get(found_char..(found_char + self.utf8_size)) { if slice == &self.utf8_encoded[0..self.utf8_size] { - // move finger to before the character found (i.e. at its start index) + // move finger to before the character found (i.e., at its start index) self.finger_back = found_char; return Some((self.finger_back, self.finger_back + self.utf8_size)); } @@ -1016,7 +1016,7 @@ struct TwoWaySearcher { It can be proven that the following is an equivalent definition of a local period for a factorization (u, v): any positive integer r such that x[i] == x[i+r] for all i such that |u| - r <= i <= |u| - 1 and such that both x[i] and x[i+r] are - defined. (i.e. i > 0 and i + r < |x|). + defined. (i.e., i > 0 and i + r < |x|). Using the above reformulation, it is easy to prove that diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 27eeb045bb1..70d940e2b55 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -188,7 +188,7 @@ unsafe impl Sync for AtomicPtr {} /// [Ordering::Relaxed]: #variant.Relaxed /// [Ordering::SeqCst]: #variant.SeqCst #[stable(feature = "rust1", since = "1.0.0")] -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] #[non_exhaustive] pub enum Ordering { /// No ordering constraints, only atomic operations. @@ -1072,6 +1072,15 @@ impl AtomicPtr { #[cfg(target_has_atomic = "8")] #[stable(feature = "atomic_bool_from", since = "1.24.0")] impl From for AtomicBool { + /// Converts a `bool` into an `AtomicBool`. + /// + /// # Examples + /// + /// ``` + /// use std::sync::atomic::AtomicBool; + /// let atomic_bool = AtomicBool::from(true); + /// assert_eq!(format!("{:?}", atomic_bool), "true") + /// ``` #[inline] fn from(b: bool) -> Self { Self::new(b) } } @@ -1126,8 +1135,12 @@ macro_rules! atomic_int { #[$stable_from] impl From<$int_type> for $atomic_type { - #[inline] - fn from(v: $int_type) -> Self { Self::new(v) } + doc_comment! { + concat!( +"Converts an `", stringify!($int_type), "` into an `", stringify!($atomic_type), "`."), + #[inline] + fn from(v: $int_type) -> Self { Self::new(v) } + } } #[$stable_debug] @@ -1940,7 +1953,7 @@ atomic_int! { 8, u64 AtomicU64 ATOMIC_U64_INIT } -#[cfg(all(not(stage0), target_has_atomic = "128"))] +#[cfg(target_has_atomic = "128")] atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), @@ -1954,7 +1967,7 @@ atomic_int! { 16, i128 AtomicI128 ATOMIC_I128_INIT } -#[cfg(all(not(stage0), target_has_atomic = "128"))] +#[cfg(target_has_atomic = "128")] atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), diff --git a/src/libcore/task/wake.rs b/src/libcore/task/wake.rs index c0ce7255d62..8ea7abce67b 100644 --- a/src/libcore/task/wake.rs +++ b/src/libcore/task/wake.rs @@ -227,7 +227,7 @@ pub unsafe trait UnsafeWake: Send + Sync { /// # Unsafety /// /// This function is unsafe to call because it's asserting the `UnsafeWake` - /// value is in a consistent state, i.e. hasn't been dropped. + /// value is in a consistent state, i.e., hasn't been dropped. unsafe fn clone_raw(&self) -> Waker; /// Drops this instance of `UnsafeWake`, deallocating resources @@ -249,7 +249,7 @@ pub unsafe trait UnsafeWake: Send + Sync { /// # Unsafety /// /// This function is unsafe to call because it's asserting the `UnsafeWake` - /// value is in a consistent state, i.e. hasn't been dropped. + /// value is in a consistent state, i.e., hasn't been dropped. unsafe fn drop_raw(&self); /// Indicates that the associated task is ready to make progress and should @@ -266,7 +266,7 @@ pub unsafe trait UnsafeWake: Send + Sync { /// # Unsafety /// /// This function is unsafe to call because it's asserting the `UnsafeWake` - /// value is in a consistent state, i.e. hasn't been dropped. + /// value is in a consistent state, i.e., hasn't been dropped. unsafe fn wake(&self); /// Indicates that the associated task is ready to make progress and should @@ -286,7 +286,7 @@ pub unsafe trait UnsafeWake: Send + Sync { /// # Unsafety /// /// This function is unsafe to call because it's asserting the `UnsafeWake` - /// value is in a consistent state, i.e. hasn't been dropped, and that the + /// value is in a consistent state, i.e., hasn't been dropped, and that the /// `UnsafeWake` hasn't moved from the thread on which it was created. unsafe fn wake_local(&self) { self.wake() diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 0964aae1db5..44899c3f412 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -1001,6 +1001,10 @@ fn test_cycle() { let mut it = (0..).step_by(1).take(0).cycle(); assert_eq!(it.size_hint(), (0, Some(0))); assert_eq!(it.next(), None); + + assert_eq!(empty::().cycle().fold(0, |acc, x| acc + x), 0); + + assert_eq!(once(1).cycle().skip(1).take(4).fold(0, |acc, x| acc + x), 4); } #[test] @@ -1012,6 +1016,33 @@ fn test_iterator_nth() { assert_eq!(v.iter().nth(v.len()), None); } +#[test] +fn test_iterator_nth_back() { + let v: &[_] = &[0, 1, 2, 3, 4]; + for i in 0..v.len() { + assert_eq!(v.iter().nth_back(i).unwrap(), &v[v.len() - 1 - i]); + } + assert_eq!(v.iter().nth_back(v.len()), None); +} + +#[test] +fn test_iterator_rev_nth_back() { + let v: &[_] = &[0, 1, 2, 3, 4]; + for i in 0..v.len() { + assert_eq!(v.iter().rev().nth_back(i).unwrap(), &v[i]); + } + assert_eq!(v.iter().rev().nth_back(v.len()), None); +} + +#[test] +fn test_iterator_rev_nth() { + let v: &[_] = &[0, 1, 2, 3, 4]; + for i in 0..v.len() { + assert_eq!(v.iter().rev().nth(i).unwrap(), &v[v.len() - 1 - i]); + } + assert_eq!(v.iter().rev().nth(v.len()), None); +} + #[test] fn test_iterator_last() { let v: &[_] = &[0, 1, 2, 3, 4]; @@ -1266,6 +1297,23 @@ fn test_cloned() { assert_eq!(it.next_back(), None); } +#[test] +fn test_cloned_side_effects() { + let mut count = 0; + { + let iter = [1, 2, 3] + .iter() + .map(|x| { + count += 1; + x + }) + .cloned() + .zip(&[1]); + for _ in iter {} + } + assert_eq!(count, 2); +} + #[test] fn test_double_ended_map() { let xs = [1, 2, 3, 4, 5, 6]; diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 1f7a8b774d7..400a86d2ffe 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -21,6 +21,7 @@ #![feature(fmt_internals)] #![feature(hashmap_internals)] #![feature(iter_copied)] +#![feature(iter_nth_back)] #![feature(iter_unfold)] #![feature(pattern)] #![feature(range_is_empty)] diff --git a/src/libcore/tests/num/dec2flt/mod.rs b/src/libcore/tests/num/dec2flt/mod.rs index 17b2f59cd4d..879a41b4b77 100644 --- a/src/libcore/tests/num/dec2flt/mod.rs +++ b/src/libcore/tests/num/dec2flt/mod.rs @@ -17,7 +17,7 @@ mod rawfp; // Take a float literal, turn it into a string in various ways (that are all trusted // to be correct) and see if those strings are parsed back to the value of the literal. -// Requires a *polymorphic literal*, i.e. one that can serve as f64 as well as f32. +// Requires a *polymorphic literal*, i.e., one that can serve as f64 as well as f32. macro_rules! test_literal { ($x: expr) => ({ let x32: f32 = $x; diff --git a/src/libcore/tests/num/flt2dec/random.rs b/src/libcore/tests/num/flt2dec/random.rs index ab619093d9d..21a7c9fc6b3 100644 --- a/src/libcore/tests/num/flt2dec/random.rs +++ b/src/libcore/tests/num/flt2dec/random.rs @@ -18,7 +18,8 @@ use core::num::flt2dec::strategy::grisu::format_exact_opt; use core::num::flt2dec::strategy::grisu::format_shortest_opt; use core::num::flt2dec::{decode, DecodableFloat, FullDecoded, Decoded}; -use rand::{FromEntropy, XorShiftRng}; +use rand::FromEntropy; +use rand::rngs::SmallRng; use rand::distributions::{Distribution, Uniform}; pub fn decode_finite(v: T) -> Decoded { @@ -71,7 +72,10 @@ fn iterate(func: &str, k: usize, n: usize, mut f: F, mut g: G, mut v: V pub fn f32_random_equivalence_test(f: F, g: G, k: usize, n: usize) where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>, G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) { - let mut rng = XorShiftRng::from_entropy(); + if cfg!(target_os = "emscripten") { + return // using rng pulls in i128 support, which doesn't work + } + let mut rng = SmallRng::from_entropy(); let f32_range = Uniform::new(0x0000_0001u32, 0x7f80_0000); iterate("f32_random_equivalence_test", k, n, f, g, |_| { let x = f32::from_bits(f32_range.sample(&mut rng)); @@ -82,7 +86,10 @@ pub fn f32_random_equivalence_test(f: F, g: G, k: usize, n: usize) pub fn f64_random_equivalence_test(f: F, g: G, k: usize, n: usize) where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>, G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) { - let mut rng = XorShiftRng::from_entropy(); + if cfg!(target_os = "emscripten") { + return // using rng pulls in i128 support, which doesn't work + } + let mut rng = SmallRng::from_entropy(); let f64_range = Uniform::new(0x0000_0000_0000_0001u64, 0x7ff0_0000_0000_0000); iterate("f64_random_equivalence_test", k, n, f, g, |_| { let x = f64::from_bits(f64_range.sample(&mut rng)); @@ -99,7 +106,7 @@ pub fn f32_exhaustive_equivalence_test(f: F, g: G, k: usize) // this is of course very stressful (and thus should be behind an `#[ignore]` attribute), // but with `-C opt-level=3 -C lto` this only takes about an hour or so. - // iterate from 0x0000_0001 to 0x7f7f_ffff, i.e. all finite ranges + // iterate from 0x0000_0001 to 0x7f7f_ffff, i.e., all finite ranges let (npassed, nignored) = iterate("f32_exhaustive_equivalence_test", k, 0x7f7f_ffff, f, g, |i: usize| { diff --git a/src/libcore/tests/num/int_macros.rs b/src/libcore/tests/num/int_macros.rs index 71d2e794538..8b04f84007f 100644 --- a/src/libcore/tests/num/int_macros.rs +++ b/src/libcore/tests/num/int_macros.rs @@ -31,8 +31,8 @@ mod tests { } #[test] - fn test_mod_euc() { - assert!((-1 as $T).mod_euc(MIN) == MAX); + fn test_rem_euclid() { + assert!((-1 as $T).rem_euclid(MIN) == MAX); } #[test] diff --git a/src/libcore/tests/num/mod.rs b/src/libcore/tests/num/mod.rs index 0928f7560e1..e1648db5e8e 100644 --- a/src/libcore/tests/num/mod.rs +++ b/src/libcore/tests/num/mod.rs @@ -694,23 +694,23 @@ macro_rules! test_float { assert!(($nan as $fty).max($nan).is_nan()); } #[test] - fn mod_euc() { + fn rem_euclid() { let a: $fty = 42.0; - assert!($inf.mod_euc(a).is_nan()); - assert_eq!(a.mod_euc($inf), a); - assert!(a.mod_euc($nan).is_nan()); - assert!($inf.mod_euc($inf).is_nan()); - assert!($inf.mod_euc($nan).is_nan()); - assert!($nan.mod_euc($inf).is_nan()); + assert!($inf.rem_euclid(a).is_nan()); + assert_eq!(a.rem_euclid($inf), a); + assert!(a.rem_euclid($nan).is_nan()); + assert!($inf.rem_euclid($inf).is_nan()); + assert!($inf.rem_euclid($nan).is_nan()); + assert!($nan.rem_euclid($inf).is_nan()); } #[test] - fn div_euc() { + fn div_euclid() { let a: $fty = 42.0; - assert_eq!(a.div_euc($inf), 0.0); - assert!(a.div_euc($nan).is_nan()); - assert!($inf.div_euc($inf).is_nan()); - assert!($inf.div_euc($nan).is_nan()); - assert!($nan.div_euc($inf).is_nan()); + assert_eq!(a.div_euclid($inf), 0.0); + assert!(a.div_euclid($nan).is_nan()); + assert!($inf.div_euclid($inf).is_nan()); + assert!($inf.div_euclid($nan).is_nan()); + assert!($nan.div_euclid($inf).is_nan()); } } } } diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index dba5a43eb21..4f00ebee1d2 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -1024,11 +1024,11 @@ fn test_rotate_right() { fn sort_unstable() { use core::cmp::Ordering::{Equal, Greater, Less}; use core::slice::heapsort; - use rand::{FromEntropy, Rng, XorShiftRng}; + use rand::{FromEntropy, Rng, rngs::SmallRng, seq::SliceRandom}; let mut v = [0; 600]; let mut tmp = [0; 600]; - let mut rng = XorShiftRng::from_entropy(); + let mut rng = SmallRng::from_entropy(); for len in (2..25).chain(500..510) { let v = &mut v[0..len]; @@ -1073,7 +1073,7 @@ fn sort_unstable() { for i in 0..v.len() { v[i] = i as i32; } - v.sort_unstable_by(|_, _| *rng.choose(&[Less, Equal, Greater]).unwrap()); + v.sort_unstable_by(|_, _| *[Less, Equal, Greater].choose(&mut rng).unwrap()); v.sort_unstable(); for i in 0..v.len() { assert_eq!(v[i], i as i32); diff --git a/src/libcore/time.rs b/src/libcore/time.rs index 938e97503de..475bb721f23 100644 --- a/src/libcore/time.rs +++ b/src/libcore/time.rs @@ -216,7 +216,7 @@ impl Duration { /// /// This method does **not** return the length of the duration when /// represented by milliseconds. The returned number always represents a - /// fractional portion of a second (i.e. it is less than one thousand). + /// fractional portion of a second (i.e., it is less than one thousand). /// /// # Examples /// @@ -235,7 +235,7 @@ impl Duration { /// /// This method does **not** return the length of the duration when /// represented by microseconds. The returned number always represents a - /// fractional portion of a second (i.e. it is less than one million). + /// fractional portion of a second (i.e., it is less than one million). /// /// # Examples /// @@ -254,7 +254,7 @@ impl Duration { /// /// This method does **not** return the length of the duration when /// represented by nanoseconds. The returned number always represents a - /// fractional portion of a second (i.e. it is less than one billion). + /// fractional portion of a second (i.e., it is less than one billion). /// /// # Examples /// diff --git a/src/libcore/unicode/printable.rs b/src/libcore/unicode/printable.rs index 519dd17bb9b..32e4b6b0fa5 100644 --- a/src/libcore/unicode/printable.rs +++ b/src/libcore/unicode/printable.rs @@ -80,7 +80,7 @@ pub(crate) fn is_printable(x: char) -> bool { } } -const SINGLETONS0U: &'static [(u8, u8)] = &[ +const SINGLETONS0U: &[(u8, u8)] = &[ (0x00, 1), (0x03, 5), (0x05, 6), @@ -122,7 +122,7 @@ const SINGLETONS0U: &'static [(u8, u8)] = &[ (0xfe, 3), (0xff, 9), ]; -const SINGLETONS0L: &'static [u8] = &[ +const SINGLETONS0L: &[u8] = &[ 0xad, 0x78, 0x79, 0x8b, 0x8d, 0xa2, 0x30, 0x57, 0x58, 0x8b, 0x8c, 0x90, 0x1c, 0x1d, 0xdd, 0x0e, 0x0f, 0x4b, 0x4c, 0xfb, 0xfc, 0x2e, 0x2f, 0x3f, @@ -162,7 +162,7 @@ const SINGLETONS0L: &'static [u8] = &[ 0x91, 0xfe, 0xff, 0x53, 0x67, 0x75, 0xc8, 0xc9, 0xd0, 0xd1, 0xd8, 0xd9, 0xe7, 0xfe, 0xff, ]; -const SINGLETONS1U: &'static [(u8, u8)] = &[ +const SINGLETONS1U: &[(u8, u8)] = &[ (0x00, 6), (0x01, 1), (0x03, 1), @@ -197,7 +197,7 @@ const SINGLETONS1U: &'static [(u8, u8)] = &[ (0xf0, 4), (0xf9, 4), ]; -const SINGLETONS1L: &'static [u8] = &[ +const SINGLETONS1L: &[u8] = &[ 0x0c, 0x27, 0x3b, 0x3e, 0x4e, 0x4f, 0x8f, 0x9e, 0x9e, 0x9f, 0x06, 0x07, 0x09, 0x36, 0x3d, 0x3e, 0x56, 0xf3, 0xd0, 0xd1, 0x04, 0x14, 0x18, 0x36, @@ -219,7 +219,7 @@ const SINGLETONS1L: &'static [u8] = &[ 0x78, 0x7d, 0x7f, 0x8a, 0xa4, 0xaa, 0xaf, 0xb0, 0xc0, 0xd0, 0x3f, 0x71, 0x72, 0x7b, ]; -const NORMAL0: &'static [u8] = &[ +const NORMAL0: &[u8] = &[ 0x00, 0x20, 0x5f, 0x22, 0x82, 0xdf, 0x04, @@ -363,7 +363,7 @@ const NORMAL0: &'static [u8] = &[ 0x1b, 0x03, 0x0f, 0x0d, ]; -const NORMAL1: &'static [u8] = &[ +const NORMAL1: &[u8] = &[ 0x5e, 0x22, 0x7b, 0x05, 0x03, 0x04, diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs index 396b0366074..e3cf959beb8 100644 --- a/src/libgraphviz/lib.rs +++ b/src/libgraphviz/lib.rs @@ -10,7 +10,7 @@ //! Generate files suitable for use with [Graphviz](http://www.graphviz.org/) //! -//! The `render` function generates output (e.g. an `output.dot` file) for +//! The `render` function generates output (e.g., an `output.dot` file) for //! use with [Graphviz](http://www.graphviz.org/) by walking a labeled //! graph. (Graphviz can then automatically lay out the nodes and edges //! of the graph, and also optionally render the graph as an image or @@ -25,7 +25,7 @@ //! expressiveness of the [DOT language]( //! http://www.graphviz.org/doc/info/lang.html). For example, there are //! many [attributes](http://www.graphviz.org/content/attrs) related to -//! providing layout hints (e.g. left-to-right versus top-down, which +//! providing layout hints (e.g., left-to-right versus top-down, which //! algorithm to use, etc). The current intention of this library is to //! emit a human-readable .dot file with very regular structure suitable //! for easy post-processing. @@ -373,7 +373,7 @@ impl Style { // implement a Labelling service) that I have encountered is that it // makes it impossible to use types outside of the current crate // directly as Nodes/Edges; you need to wrap them in newtype'd -// structs. See e.g. the `No` and `Ed` structs in the examples. (In +// structs. See e.g., the `No` and `Ed` structs in the examples. (In // practice clients using a graph in some other crate would need to // provide some sort of adapter shim over the graph anyway to // interface with this library). @@ -400,7 +400,7 @@ impl<'a> Id<'a> { /// The caller must ensure that the input conforms to an /// identifier format: it must be a non-empty string made up of /// alphanumeric or underscore characters, not beginning with a - /// digit (i.e. the regular expression `[a-zA-Z_][a-zA-Z_0-9]*`). + /// digit (i.e., the regular expression `[a-zA-Z_][a-zA-Z_0-9]*`). /// /// (Note: this format is a strict subset of the `ID` format /// defined by the DOT language. This function may change in the diff --git a/src/liblibc b/src/liblibc deleted file mode 160000 index c75ca6465a1..00000000000 --- a/src/liblibc +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c75ca6465a139704e00295be355b1f067af2f535 diff --git a/src/libpanic_abort/Cargo.toml b/src/libpanic_abort/Cargo.toml index 633d273b3b9..e304e61c329 100644 --- a/src/libpanic_abort/Cargo.toml +++ b/src/libpanic_abort/Cargo.toml @@ -11,5 +11,5 @@ doc = false [dependencies] core = { path = "../libcore" } -libc = { path = "../rustc/libc_shim" } -compiler_builtins = { path = "../rustc/compiler_builtins_shim" } +libc = { version = "0.2", default-features = false } +compiler_builtins = "0.1.0" diff --git a/src/libpanic_abort/lib.rs b/src/libpanic_abort/lib.rs index 9235f8e7660..95c3514185e 100644 --- a/src/libpanic_abort/lib.rs +++ b/src/libpanic_abort/lib.rs @@ -66,6 +66,12 @@ pub unsafe extern fn __rust_start_panic(_payload: usize) -> u32 { unsafe fn abort() -> ! { core::intrinsics::abort(); } + + #[cfg(target_env="sgx")] + unsafe fn abort() -> ! { + extern "C" { pub fn panic_exit() -> !; } + panic_exit(); + } } // This... is a bit of an oddity. The tl;dr; is that this is required to link diff --git a/src/libpanic_unwind/Cargo.toml b/src/libpanic_unwind/Cargo.toml index 74aaa4d5ae3..c9fce621608 100644 --- a/src/libpanic_unwind/Cargo.toml +++ b/src/libpanic_unwind/Cargo.toml @@ -12,6 +12,6 @@ doc = false [dependencies] alloc = { path = "../liballoc" } core = { path = "../libcore" } -libc = { path = "../rustc/libc_shim" } +libc = { version = "0.2", default-features = false } unwind = { path = "../libunwind" } -compiler_builtins = { path = "../rustc/compiler_builtins_shim" } +compiler_builtins = "0.1.0" diff --git a/src/libpanic_unwind/dwarf/mod.rs b/src/libpanic_unwind/dwarf/mod.rs index 3ff250ff659..c9ae87ade28 100644 --- a/src/libpanic_unwind/dwarf/mod.rs +++ b/src/libpanic_unwind/dwarf/mod.rs @@ -32,7 +32,7 @@ impl DwarfReader { DwarfReader { ptr } } - // DWARF streams are packed, so e.g. a u32 would not necessarily be aligned + // DWARF streams are packed, so e.g., a u32 would not necessarily be aligned // on a 4-byte boundary. This may cause problems on platforms with strict // alignment requirements. By wrapping data in a "packed" struct, we are // telling the backend to generate "misalignment-safe" code. diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs index 11ebcf5c01e..441058c8d74 100644 --- a/src/libpanic_unwind/gcc.rs +++ b/src/libpanic_unwind/gcc.rs @@ -25,7 +25,7 @@ //! //! In both phases the unwinder walks stack frames from top to bottom using //! information from the stack frame unwind sections of the current process's -//! modules ("module" here refers to an OS module, i.e. an executable or a +//! modules ("module" here refers to an OS module, i.e., an executable or a //! dynamic library). //! //! For each stack frame, it invokes the associated "personality routine", whose @@ -296,7 +296,7 @@ unsafe extern "C" fn rust_eh_unwind_resume(panic_ctx: *mut u8) -> ! { // Each module's image contains a frame unwind info section (usually // ".eh_frame"). When a module is loaded/unloaded into the process, the // unwinder must be informed about the location of this section in memory. The -// methods of achieving that vary by the platform. On some (e.g. Linux), the +// methods of achieving that vary by the platform. On some (e.g., Linux), the // unwinder can discover unwind info sections on its own (by dynamically // enumerating currently loaded modules via the dl_iterate_phdr() API and // finding their ".eh_frame" sections); Others, like Windows, require modules diff --git a/src/libpanic_unwind/seh.rs b/src/libpanic_unwind/seh.rs index 832a0aff71b..9d24079d91e 100644 --- a/src/libpanic_unwind/seh.rs +++ b/src/libpanic_unwind/seh.rs @@ -12,7 +12,7 @@ //! //! On Windows (currently only on MSVC), the default exception handling //! mechanism is Structured Exception Handling (SEH). This is quite different -//! than Dwarf-based exception handling (e.g. what other unix platforms use) in +//! than Dwarf-based exception handling (e.g., what other unix platforms use) in //! terms of compiler internals, so LLVM is required to have a good deal of //! extra support for SEH. //! @@ -304,7 +304,7 @@ pub unsafe fn cleanup(payload: [u64; 2]) -> Box { }) } -// This is required by the compiler to exist (e.g. it's a lang item), but +// This is required by the compiler to exist (e.g., it's a lang item), but // it's never actually called by the compiler because __C_specific_handler // or _except_handler3 is the personality function that is always used. // Hence this is just an aborting stub. diff --git a/src/libproc_macro/bridge/client.rs b/src/libproc_macro/bridge/client.rs index ed27df44962..f5e12713e4e 100644 --- a/src/libproc_macro/bridge/client.rs +++ b/src/libproc_macro/bridge/client.rs @@ -262,7 +262,7 @@ enum BridgeState<'a> { Connected(Bridge<'a>), /// Access to the bridge is being exclusively acquired - /// (e.g. during `BridgeState::with`). + /// (e.g., during `BridgeState::with`). InUse, } @@ -283,7 +283,7 @@ impl BridgeState<'_> { /// The state will be restored after `f` exits, even /// by panic, including modifications made to it by `f`. /// - /// NB: while `f` is running, the thread-local state + /// N.B., while `f` is running, the thread-local state /// is `BridgeState::InUse`. fn with(f: impl FnOnce(&mut BridgeState) -> R) -> R { BRIDGE_STATE.with(|state| { @@ -333,7 +333,7 @@ impl Bridge<'_> { /// which may be using a different `proc_macro` from the one /// used by the server, but can be interacted with compatibly. /// -/// NB: `F` must have FFI-friendly memory layout (e.g. a pointer). +/// N.B., `F` must have FFI-friendly memory layout (e.g., a pointer). /// The call ABI of function pointers used for `F` doesn't /// need to match between server and client, since it's only /// passed between them and (eventually) called by the client. diff --git a/src/libproc_macro/bridge/mod.rs b/src/libproc_macro/bridge/mod.rs index f03c63fc04c..edb4d3fbdaa 100644 --- a/src/libproc_macro/bridge/mod.rs +++ b/src/libproc_macro/bridge/mod.rs @@ -14,7 +14,7 @@ //! Serialization (with C ABI buffers) and unique integer handles are employed //! to allow safely interfacing between two copies of `proc_macro` built //! (from the same source) by different compilers with potentially mismatching -//! Rust ABIs (e.g. stage0/bin/rustc vs stage1/bin/rustc during bootstrap). +//! Rust ABIs (e.g., stage0/bin/rustc vs stage1/bin/rustc during bootstrap). #![deny(unsafe_code)] diff --git a/src/libproc_macro/bridge/scoped_cell.rs b/src/libproc_macro/bridge/scoped_cell.rs index 51d1fece79b..c86d5fc309a 100644 --- a/src/libproc_macro/bridge/scoped_cell.rs +++ b/src/libproc_macro/bridge/scoped_cell.rs @@ -19,7 +19,7 @@ pub trait ApplyL<'a> { type Out; } -/// Type lambda taking a lifetime, i.e. `Lifetime -> Type`. +/// Type lambda taking a lifetime, i.e., `Lifetime -> Type`. pub trait LambdaL: for<'a> ApplyL<'a> {} impl ApplyL<'a>> LambdaL for T {} diff --git a/src/libproc_macro/bridge/server.rs b/src/libproc_macro/bridge/server.rs index f500b17d1ca..0c1d4f7cc50 100644 --- a/src/libproc_macro/bridge/server.rs +++ b/src/libproc_macro/bridge/server.rs @@ -16,7 +16,7 @@ use super::*; use super::client::HandleStore; /// Declare an associated item of one of the traits below, optionally -/// adjusting it (i.e. adding bounds to types and default bodies to methods). +/// adjusting it (i.e., adding bounds to types and default bodies to methods). macro_rules! associated_item { (type TokenStream) => (type TokenStream: 'static + Clone;); diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index 32c81302931..ebba5c81fe0 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -110,7 +110,7 @@ impl FromStr for TokenStream { } } -// NB: the bridge only provides `to_string`, implement `fmt::Display` +// N.B., the bridge only provides `to_string`, implement `fmt::Display` // based on it (the reverse of the usual relationship between the two). #[stable(feature = "proc_macro_lib", since = "1.15.0")] impl ToString for TokenStream { @@ -196,7 +196,7 @@ pub mod token_stream { use {bridge, Group, Ident, Literal, Punct, TokenTree, TokenStream}; /// An iterator over `TokenStream`'s `TokenTree`s. - /// The iteration is "shallow", e.g. the iterator doesn't recurse into delimited groups, + /// The iteration is "shallow", e.g., the iterator doesn't recurse into delimited groups, /// and returns whole groups as token trees. #[derive(Clone)] #[stable(feature = "proc_macro_lib2", since = "1.29.0")] @@ -426,7 +426,7 @@ impl PartialEq for SourceFile { #[unstable(feature = "proc_macro_span", issue = "54725")] impl Eq for SourceFile {} -/// A single token or a delimited sequence of token trees (e.g. `[1, (), ..]`). +/// A single token or a delimited sequence of token trees (e.g., `[1, (), ..]`). #[stable(feature = "proc_macro_lib2", since = "1.29.0")] #[derive(Clone)] pub enum TokenTree { @@ -533,7 +533,7 @@ impl From for TokenTree { } } -// NB: the bridge only provides `to_string`, implement `fmt::Display` +// N.B., the bridge only provides `to_string`, implement `fmt::Display` // based on it (the reverse of the usual relationship between the two). #[stable(feature = "proc_macro_lib", since = "1.15.0")] impl ToString for TokenTree { @@ -663,7 +663,7 @@ impl Group { } } -// NB: the bridge only provides `to_string`, implement `fmt::Display` +// N.B., the bridge only provides `to_string`, implement `fmt::Display` // based on it (the reverse of the usual relationship between the two). #[stable(feature = "proc_macro_lib", since = "1.15.0")] impl ToString for Group { @@ -711,10 +711,10 @@ impl !Sync for Punct {} #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[stable(feature = "proc_macro_lib2", since = "1.29.0")] pub enum Spacing { - /// E.g. `+` is `Alone` in `+ =`, `+ident` or `+()`. + /// e.g., `+` is `Alone` in `+ =`, `+ident` or `+()`. #[stable(feature = "proc_macro_lib2", since = "1.29.0")] Alone, - /// E.g. `+` is `Joint` in `+=` or `'#`. + /// e.g., `+` is `Joint` in `+=` or `'#`. /// Additionally, single quote `'` can join with identifiers to form lifetimes `'ident`. #[stable(feature = "proc_macro_lib2", since = "1.29.0")] Joint, @@ -729,11 +729,6 @@ impl Punct { /// which can be further configured with the `set_span` method below. #[stable(feature = "proc_macro_lib2", since = "1.29.0")] pub fn new(ch: char, spacing: Spacing) -> Punct { - const LEGAL_CHARS: &[char] = &['=', '<', '>', '!', '~', '+', '-', '*', '/', '%', '^', - '&', '|', '@', '.', ',', ';', ':', '#', '$', '?', '\'']; - if !LEGAL_CHARS.contains(&ch) { - panic!("unsupported character `{:?}`", ch) - } Punct(bridge::client::Punct::new(ch, spacing)) } @@ -765,7 +760,7 @@ impl Punct { } } -// NB: the bridge only provides `to_string`, implement `fmt::Display` +// N.B., the bridge only provides `to_string`, implement `fmt::Display` // based on it (the reverse of the usual relationship between the two). #[stable(feature = "proc_macro_lib", since = "1.15.0")] impl ToString for Punct { @@ -800,16 +795,6 @@ impl fmt::Debug for Punct { pub struct Ident(bridge::client::Ident); impl Ident { - fn is_valid(string: &str) -> bool { - let mut chars = string.chars(); - if let Some(start) = chars.next() { - (start == '_' || start.is_xid_start()) - && chars.all(|cont| cont == '_' || cont.is_xid_continue()) - } else { - false - } - } - /// Creates a new `Ident` with the given `string` as well as the specified /// `span`. /// The `string` argument must be a valid identifier permitted by the @@ -831,18 +816,12 @@ impl Ident { /// tokens, requires a `Span` to be specified at construction. #[stable(feature = "proc_macro_lib2", since = "1.29.0")] pub fn new(string: &str, span: Span) -> Ident { - if !Ident::is_valid(string) { - panic!("`{:?}` is not a valid identifier", string) - } Ident(bridge::client::Ident::new(string, span.0, false)) } /// Same as `Ident::new`, but creates a raw identifier (`r#ident`). #[unstable(feature = "proc_macro_raw_ident", issue = "54723")] pub fn new_raw(string: &str, span: Span) -> Ident { - if !Ident::is_valid(string) { - panic!("`{:?}` is not a valid identifier", string) - } Ident(bridge::client::Ident::new(string, span.0, true)) } @@ -860,7 +839,7 @@ impl Ident { } } -// NB: the bridge only provides `to_string`, implement `fmt::Display` +// N.B., the bridge only provides `to_string`, implement `fmt::Display` // based on it (the reverse of the usual relationship between the two). #[stable(feature = "proc_macro_lib", since = "1.15.0")] impl ToString for Ident { @@ -1110,7 +1089,7 @@ impl Literal { } } -// NB: the bridge only provides `to_string`, implement `fmt::Display` +// N.B., the bridge only provides `to_string`, implement `fmt::Display` // based on it (the reverse of the usual relationship between the two). #[stable(feature = "proc_macro_lib", since = "1.15.0")] impl ToString for Literal { diff --git a/src/libprofiler_builtins/Cargo.toml b/src/libprofiler_builtins/Cargo.toml index 79192fbb681..7c95cf0a054 100644 --- a/src/libprofiler_builtins/Cargo.toml +++ b/src/libprofiler_builtins/Cargo.toml @@ -13,7 +13,7 @@ doc = false [dependencies] core = { path = "../libcore" } -compiler_builtins = { path = "../rustc/compiler_builtins_shim" } +compiler_builtins = { version = "0.1.0", features = ['rustc-dep-of-std'] } [build-dependencies] cc = "1.0.1" diff --git a/src/libprofiler_builtins/build.rs b/src/libprofiler_builtins/build.rs index 8d6c7d68dfe..db72ce77e72 100644 --- a/src/libprofiler_builtins/build.rs +++ b/src/libprofiler_builtins/build.rs @@ -56,9 +56,15 @@ fn main() { cfg.define("COMPILER_RT_HAS_UNAME", Some("1")); } + // The source for `compiler-rt` comes from the `compiler-builtins` crate, so + // load our env var set by cargo to find the source code. + let root = env::var_os("DEP_COMPILER_RT_COMPILER_RT").unwrap(); + let root = Path::new(&root); + for src in profile_sources { - cfg.file(Path::new("../libcompiler_builtins/compiler-rt/lib/profile").join(src)); + cfg.file(root.join("lib").join("profile").join(src)); } + cfg.warnings(false); cfg.compile("profiler-rt"); } diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index 3316735de66..a572b6bf919 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -32,7 +32,7 @@ parking_lot = "0.6" byteorder = { version = "1.1", features = ["i128"]} chalk-engine = { version = "0.8.0", default-features=false } rustc_fs_util = { path = "../librustc_fs_util" } -smallvec = { version = "0.6.5", features = ["union"] } +smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } # Note that these dependencies are a lie, they're just here to get linkage to # work. diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index 6b9c0aac52e..4881f10fac2 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -53,7 +53,7 @@ pub fn construct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let body_exit; // Find the tables for this body. - let owner_def_id = tcx.hir.local_def_id(tcx.hir.body_owner(body.id())); + let owner_def_id = tcx.hir().local_def_id(tcx.hir().body_owner(body.id())); let tables = tcx.typeck_tables_of(owner_def_id); let mut cfg_builder = CFGBuilder { @@ -109,7 +109,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { } fn stmt(&mut self, stmt: &hir::Stmt, pred: CFGIndex) -> CFGIndex { - let hir_id = self.tcx.hir.node_to_hir_id(stmt.node.id()); + let hir_id = self.tcx.hir().node_to_hir_id(stmt.node.id()); match stmt.node { hir::StmtKind::Decl(ref decl, _) => { let exit = self.decl(&decl, pred); @@ -379,7 +379,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { } hir::ExprKind::Index(ref l, ref r) | - hir::ExprKind::Binary(_, ref l, ref r) => { // NB: && and || handled earlier + hir::ExprKind::Binary(_, ref l, ref r) => { // N.B., && and || handled earlier self.straightline(expr, pred, [l, r].iter().map(|&e| &**e)) } @@ -415,8 +415,8 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { args: I) -> CFGIndex { let func_or_rcvr_exit = self.expr(func_or_rcvr, pred); let ret = self.straightline(call_expr, func_or_rcvr_exit, args); - // FIXME(canndrew): This is_never should probably be an is_uninhabited. - if self.tables.expr_ty(call_expr).is_never() { + let m = self.tcx.hir().get_module_parent(call_expr.id); + if self.tcx.is_ty_uninhabited_from(m, self.tables.expr_ty(call_expr)) { self.add_unreachable_node() } else { ret @@ -588,9 +588,9 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { match destination.target_id { 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 { + if b.block_expr_id == self.tcx.hir().node_to_hir_id(loop_id).local_id { let scope = region::Scope { - id: self.tcx.hir.node_to_hir_id(loop_id).local_id, + id: self.tcx.hir().node_to_hir_id(loop_id).local_id, data: region::ScopeData::Node }; return (scope, match scope_cf_kind { @@ -600,9 +600,9 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { } } for l in &self.loop_scopes { - if l.loop_id == self.tcx.hir.node_to_hir_id(loop_id).local_id { + if l.loop_id == self.tcx.hir().node_to_hir_id(loop_id).local_id { let scope = region::Scope { - id: self.tcx.hir.node_to_hir_id(loop_id).local_id, + id: self.tcx.hir().node_to_hir_id(loop_id).local_id, data: region::ScopeData::Node }; return (scope, match scope_cf_kind { diff --git a/src/librustc/cfg/graphviz.rs b/src/librustc/cfg/graphviz.rs index 650aa39114f..39810691df8 100644 --- a/src/librustc/cfg/graphviz.rs +++ b/src/librustc/cfg/graphviz.rs @@ -32,11 +32,11 @@ pub struct LabelledCFG<'a, 'tcx: 'a> { impl<'a, 'tcx> LabelledCFG<'a, 'tcx> { fn local_id_to_string(&self, local_id: hir::ItemLocalId) -> String { assert!(self.cfg.owner_def_id.is_local()); - let node_id = self.tcx.hir.hir_to_node_id(hir::HirId { - owner: self.tcx.hir.def_index_to_hir_id(self.cfg.owner_def_id.index).owner, + let node_id = self.tcx.hir().hir_to_node_id(hir::HirId { + owner: self.tcx.hir().def_index_to_hir_id(self.cfg.owner_def_id.index).owner, local_id }); - let s = self.tcx.hir.node_to_string(node_id); + let s = self.tcx.hir().node_to_string(node_id); // Replacing newlines with \\l causes each line to be left-aligned, // improving presentation of (long) pretty-printed expressions. diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 388bbc52c3b..f4d7ef59404 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -17,7 +17,7 @@ //! fully identify a dependency node, even across multiple compilation sessions. //! In other words, the value of the fingerprint does not depend on anything //! that is specific to a given compilation session, like an unpredictable -//! interning key (e.g. NodeId, DefId, Symbol) or the numeric value of a +//! interning key (e.g., NodeId, DefId, Symbol) or the numeric value of a //! pointer. The concept behind this could be compared to how git commit hashes //! uniquely identify a given commit and has a few advantages: //! @@ -28,7 +28,7 @@ //! * A `Fingerprint` is just a bunch of bits, which allows `DepNode` to //! implement `Copy`, `Sync`, `Send`, `Freeze`, etc. //! * Since we just have a bit pattern, `DepNode` can be mapped from disk into -//! memory without any post-processing (e.g. "abomination-style" pointer +//! memory without any post-processing (e.g., "abomination-style" pointer //! reconstruction). //! * Because a `DepNode` is self-contained, we can instantiate `DepNodes` that //! refer to things that do not exist anymore. In previous implementations @@ -81,7 +81,7 @@ use ty::{TyCtxt, FnSig, Instance, InstanceDef, use ty::subst::Substs; // erase!() just makes tokens go away. It's used to specify which macro argument -// is repeated (i.e. which sub-expression of the macro we are in) but don't need +// is repeated (i.e., which sub-expression of the macro we are in) but don't need // to actually use any of the arguments. macro_rules! erase { ($x:tt) => ({}) @@ -162,7 +162,9 @@ macro_rules! define_dep_nodes { } } - #[inline] + // FIXME: Make `is_anon`, `is_input`, `is_eval_always` and `has_params` properties + // of queries + #[inline(always)] pub fn is_anon(&self) -> bool { match *self { $( @@ -171,7 +173,7 @@ macro_rules! define_dep_nodes { } } - #[inline] + #[inline(always)] pub fn is_input(&self) -> bool { match *self { $( @@ -180,7 +182,7 @@ macro_rules! define_dep_nodes { } } - #[inline] + #[inline(always)] pub fn is_eval_always(&self) -> bool { match *self { $( @@ -190,7 +192,7 @@ macro_rules! define_dep_nodes { } #[allow(unreachable_code)] - #[inline] + #[inline(always)] pub fn has_params(&self) -> bool { match *self { $( @@ -230,6 +232,7 @@ macro_rules! define_dep_nodes { impl DepNode { #[allow(unreachable_code, non_snake_case)] + #[inline(always)] pub fn new<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, dep: DepConstructor<'gcx>) -> DepNode @@ -299,11 +302,11 @@ macro_rules! define_dep_nodes { /// Construct a DepNode from the given DepKind and DefPathHash. This /// method will assert that the given DepKind actually requires a /// single DefId/DefPathHash parameter. - #[inline] + #[inline(always)] pub fn from_def_path_hash(kind: DepKind, def_path_hash: DefPathHash) -> DepNode { - assert!(kind.can_reconstruct_query_key() && kind.has_params()); + debug_assert!(kind.can_reconstruct_query_key() && kind.has_params()); DepNode { kind, hash: def_path_hash.0, @@ -313,9 +316,9 @@ macro_rules! define_dep_nodes { /// Create a new, parameterless DepNode. This method will assert /// that the DepNode corresponding to the given DepKind actually /// does not require any parameters. - #[inline] + #[inline(always)] pub fn new_no_params(kind: DepKind) -> DepNode { - assert!(!kind.has_params()); + debug_assert!(!kind.has_params()); DepNode { kind, hash: Fingerprint::ZERO, @@ -381,7 +384,7 @@ macro_rules! define_dep_nodes { #[allow(dead_code, non_upper_case_globals)] pub mod label_strs { $( - pub const $variant: &'static str = stringify!($variant); + pub const $variant: &str = stringify!($variant); )* } ); @@ -418,14 +421,14 @@ impl fmt::Debug for DepNode { impl DefPathHash { - #[inline] + #[inline(always)] pub fn to_dep_node(self, kind: DepKind) -> DepNode { DepNode::from_def_path_hash(kind, self) } } impl DefId { - #[inline] + #[inline(always)] pub fn to_dep_node(self, tcx: TyCtxt<'_, '_, '_>, kind: DepKind) -> DepNode { DepNode::from_def_path_hash(kind, tcx.def_path_hash(self)) } @@ -449,10 +452,10 @@ define_dep_nodes!( <'tcx> // Represents the `Krate` as a whole (the `hir::Krate` value) (as // distinct from the krate module). This is basically a hash of // the entire krate, so if you read from `Krate` (e.g., by calling - // `tcx.hir.krate()`), we will have to assume that any change + // `tcx.hir().krate()`), we will have to assume that any change // means that you need to be recompiled. This is because the // `Krate` value gives you access to all other items. To avoid - // this fate, do not call `tcx.hir.krate()`; instead, prefer + // this fate, do not call `tcx.hir().krate()`; instead, prefer // wrappers like `tcx.visit_all_items_in_krate()`. If there is no // suitable wrapper, you can use `tcx.dep_graph.ignore()` to gain // access to the krate, but you must remember to add suitable @@ -666,6 +669,7 @@ define_dep_nodes!( <'tcx> [] TypeOpNormalizeFnSig(CanonicalTypeOpNormalizeGoal<'tcx, FnSig<'tcx>>), [] SubstituteNormalizeAndTestPredicates { key: (DefId, &'tcx Substs<'tcx>) }, + [] MethodAutoderefSteps(CanonicalTyGoal<'tcx>), [input] TargetFeaturesWhitelist, @@ -733,7 +737,7 @@ impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for DefIndex { const CAN_RECONSTRUCT_QUERY_KEY: bool = true; fn to_fingerprint(&self, tcx: TyCtxt<'_, '_, '_>) -> Fingerprint { - tcx.hir.definitions().def_path_hash(*self).0 + tcx.hir().definitions().def_path_hash(*self).0 } fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String { diff --git a/src/librustc/dep_graph/dep_tracking_map.rs b/src/librustc/dep_graph/dep_tracking_map.rs index a674b5df639..da7dabf6e18 100644 --- a/src/librustc/dep_graph/dep_tracking_map.rs +++ b/src/librustc/dep_graph/dep_tracking_map.rs @@ -65,7 +65,7 @@ impl MemoizationMap for RefCell> { /// /// ``` /// fn type_of_item(..., item: &hir::Item) -> Ty<'tcx> { - /// let item_def_id = ccx.tcx.hir.local_def_id(it.id); + /// let item_def_id = ccx.tcx.hir().local_def_id(it.id); /// ccx.tcx.item_types.memoized(item_def_id, || { /// ccx.tcx.dep_graph.read(DepNode::Hir(item_def_id)); // (*) /// compute_type_of_item(ccx, item) diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 96590c1fc72..3dc6f761ec9 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -47,7 +47,7 @@ trait Foo where Self: Sized { We cannot create an object of type `Box` or `&Foo` since in this case `Self` would not be `Sized`. -Generally, `Self : Sized` is used to indicate that the trait should not be used +Generally, `Self: Sized` is used to indicate that the trait should not be used as a trait object. If the trait comes from your own crate, consider removing this restriction. @@ -217,9 +217,9 @@ trait Trait { ``` If this is not an option, consider replacing the type parameter with another -trait object (e.g. if `T: OtherTrait`, use `on: Box`). If the number -of types you intend to feed to this method is limited, consider manually listing -out the methods of different types. +trait object (e.g., if `T: OtherTrait`, use `on: Box`). If the +number of types you intend to feed to this method is limited, consider manually +listing out the methods of different types. ### Method has no receiver @@ -642,7 +642,7 @@ struct Foo; // error: duplicate lang item found: `arc` ``` Lang items are already implemented in the standard library. Unless you are -writing a free-standing application (e.g. a kernel), you do not need to provide +writing a free-standing application (e.g., a kernel), you do not need to provide them yourself. You can build a free-standing crate by adding `#![no_std]` to the crate @@ -699,7 +699,7 @@ This error appears when the curly braces contain an identifier which doesn't match with any of the type parameters or the string `Self`. This might happen if you misspelled a type parameter, or if you intended to use literal curly braces. If it is the latter, escape the curly braces with a second curly brace -of the same type; e.g. a literal `{` is `{{`. +of the same type; e.g., a literal `{` is `{{`. "##, E0231: r##" @@ -832,7 +832,7 @@ extern "C" { E0271: r##" This is because of a type mismatch between the associated type of some -trait (e.g. `T::Bar`, where `T` implements `trait Quux { type Bar; }`) +trait (e.g., `T::Bar`, where `T` implements `trait Quux { type Bar; }`) and another type `U` that is required to be equal to `T::Bar`, but is not. Examples follow. @@ -1622,7 +1622,7 @@ representation of enums isn't strictly defined in Rust, and this attribute won't work on enums. `#[repr(simd)]` will give a struct consisting of a homogeneous series of machine -types (i.e. `u8`, `i32`, etc) a representation that permits vectorization via +types (i.e., `u8`, `i32`, etc) a representation that permits vectorization via SIMD. This doesn't make much sense for enums since they don't consist of a single list of data. "##, diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index 020012d756a..5ff533fe34b 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -100,7 +100,7 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { /// Check any attribute. fn check_attributes(&self, item: &hir::Item, target: Target) { if target == Target::Fn || target == Target::Const { - self.tcx.codegen_fn_attrs(self.tcx.hir.local_def_id(item.id)); + self.tcx.codegen_fn_attrs(self.tcx.hir().local_def_id(item.id)); } else if let Some(a) = item.attrs.iter().find(|a| a.check_name("target_feature")) { self.tcx.sess.struct_span_err(a.span, "attribute should be applied to a function") .span_label(item.span, "not a function") @@ -352,7 +352,7 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for CheckAttrVisitor<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir) + NestedVisitorMap::OnlyBodies(&self.tcx.hir()) } fn visit_item(&mut self, item: &'tcx hir::Item) { @@ -375,7 +375,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckAttrVisitor<'a, 'tcx> { pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let mut checker = CheckAttrVisitor { tcx }; - tcx.hir.krate().visit_all_item_likes(&mut checker.as_deep_visitor()); + tcx.hir().krate().visit_all_item_likes(&mut checker.as_deep_visitor()); } fn is_c_like_enum(item: &hir::Item) -> bool { diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index 50922ee601d..fb3c3dec7c2 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -46,7 +46,7 @@ pub enum NonMacroAttrKind { pub enum Def { // Type namespace Mod(DefId), - Struct(DefId), // DefId refers to NodeId of the struct itself + Struct(DefId), // `DefId` refers to `NodeId` of the struct itself Union(DefId), Enum(DefId), Variant(DefId), @@ -63,27 +63,27 @@ pub enum Def { PrimTy(hir::PrimTy), TyParam(DefId), SelfTy(Option /* trait */, Option /* impl */), - ToolMod, // e.g. `rustfmt` in `#[rustfmt::skip]` + ToolMod, // e.g., `rustfmt` in `#[rustfmt::skip]` // Value namespace Fn(DefId), Const(DefId), Static(DefId, bool /* is_mutbl */), - StructCtor(DefId, CtorKind), // DefId refers to NodeId of the struct's constructor - VariantCtor(DefId, CtorKind), // DefId refers to the enum variant - SelfCtor(DefId /* impl */), // DefId refers to the impl + StructCtor(DefId, CtorKind), // `DefId` refers to `NodeId` of the struct's constructor + VariantCtor(DefId, CtorKind), // `DefId` refers to the enum variant + SelfCtor(DefId /* impl */), // `DefId` refers to the impl Method(DefId), AssociatedConst(DefId), Local(ast::NodeId), - Upvar(ast::NodeId, // node id of closed over local - usize, // index in the freevars list of the closure + Upvar(ast::NodeId, // `NodeId` of closed over local + usize, // index in the `freevars` list of the closure ast::NodeId), // expr node that creates the closure Label(ast::NodeId), // Macro namespace Macro(DefId, MacroKind), - NonMacroAttr(NonMacroAttrKind), // e.g. `#[inline]` or `#[rustfmt::skip]` + NonMacroAttr(NonMacroAttrKind), // e.g., `#[inline]` or `#[rustfmt::skip]` // Both namespaces Err, @@ -170,6 +170,7 @@ impl PerNS { impl ::std::ops::Index for PerNS { type Output = T; + fn index(&self, ns: Namespace) -> &T { match ns { ValueNS => &self.value_ns, @@ -238,6 +239,7 @@ impl CtorKind { ast::VariantData::Struct(..) => CtorKind::Fictive, } } + pub fn from_hir(vdata: &hir::VariantData) -> CtorKind { match *vdata { hir::VariantData::Tuple(..) => CtorKind::Fn, diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index d9963f23a15..f7e2c7036f6 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -131,7 +131,7 @@ impl<'this, 'tcx> NestedVisitorMap<'this, 'tcx> { /// Each method of the Visitor trait is a hook to be potentially /// overridden. Each method's default implementation recursively visits /// the substructure of the input via the corresponding `walk` method; -/// e.g. the `visit_mod` method by default calls `intravisit::walk_mod`. +/// e.g., the `visit_mod` method by default calls `intravisit::walk_mod`. /// /// Note that this visitor does NOT visit nested items by default /// (this is why the module is called `intravisit`, to distinguish it @@ -493,7 +493,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { item.id) } ItemKind::Mod(ref module) => { - // visit_mod() takes care of visiting the Item's NodeId + // `visit_mod()` takes care of visiting the `Item`'s `NodeId`. visitor.visit_mod(module, item.span, item.id) } ItemKind::ForeignMod(ref foreign_module) => { @@ -518,7 +518,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { } ItemKind::Enum(ref enum_definition, ref type_parameters) => { visitor.visit_generics(type_parameters); - // visit_enum_def() takes care of visiting the Item's NodeId + // `visit_enum_def()` takes care of visiting the `Item`'s `NodeId`. visitor.visit_enum_def(enum_definition, type_parameters, item.id, item.span) } ItemKind::Impl( @@ -877,7 +877,7 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai } pub fn walk_trait_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_item_ref: &'v TraitItemRef) { - // NB: Deliberately force a compilation error if/when new fields are added. + // N.B., deliberately force a compilation error if/when new fields are added. let TraitItemRef { id, ident, ref kind, span: _, ref defaultness } = *trait_item_ref; visitor.visit_nested_trait_item(id); visitor.visit_ident(ident); @@ -886,7 +886,7 @@ pub fn walk_trait_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_item_ref: } pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem) { - // NB: Deliberately force a compilation error if/when new fields are added. + // N.B., deliberately force a compilation error if/when new fields are added. let ImplItem { id: _, hir_id: _, @@ -932,7 +932,7 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt } pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, impl_item_ref: &'v ImplItemRef) { - // NB: Deliberately force a compilation error if/when new fields are added. + // N.B., deliberately force a compilation error if/when new fields are added. let ImplItemRef { id, ident, ref kind, span: _, ref vis, ref defaultness } = *impl_item_ref; visitor.visit_nested_impl_item(id); visitor.visit_ident(ident); diff --git a/src/librustc/hir/itemlikevisit.rs b/src/librustc/hir/itemlikevisit.rs index a62000e10c7..f8bc764572f 100644 --- a/src/librustc/hir/itemlikevisit.rs +++ b/src/librustc/hir/itemlikevisit.rs @@ -19,7 +19,7 @@ use super::intravisit::Visitor; /// /// 1. **Shallow visit**: Get a simple callback for every item (or item-like thing) in the HIR. /// - Example: find all items with a `#[foo]` attribute on them. -/// - How: Implement `ItemLikeVisitor` and call `tcx.hir.krate().visit_all_item_likes()`. +/// - How: Implement `ItemLikeVisitor` and call `tcx.hir().krate().visit_all_item_likes()`. /// - Pro: Efficient; just walks the lists of item-like things, not the nodes themselves. /// - Con: Don't get information about nesting /// - Con: Don't have methods for specific bits of HIR, like "on @@ -29,7 +29,7 @@ use super::intravisit::Visitor; /// within one another. /// - Example: Examine each expression to look for its type and do some check or other. /// - How: Implement `intravisit::Visitor` and use -/// `tcx.hir.krate().visit_all_item_likes(visitor.as_deep_visitor())`. Within +/// `tcx.hir().krate().visit_all_item_likes(visitor.as_deep_visitor())`. Within /// your `intravisit::Visitor` impl, implement methods like /// `visit_expr()`; don't forget to invoke /// `intravisit::walk_visit_expr()` to keep walking the subparts. @@ -43,7 +43,7 @@ use super::intravisit::Visitor; /// - How: Implement `intravisit::Visitor` and override the /// `nested_visit_map()` methods to return /// `NestedVisitorMap::All`. Walk your crate with -/// `intravisit::walk_crate()` invoked on `tcx.hir.krate()`. +/// `intravisit::walk_crate()` invoked on `tcx.hir().krate()`. /// - Pro: Visitor methods for any kind of HIR node, not just item-like things. /// - Pro: Preserves nesting information /// - Con: Does not integrate well into dependency tracking. diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index dc8baa112bb..6958801d865 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -72,7 +72,7 @@ use syntax::ptr::P; use syntax::source_map::{self, respan, CompilerDesugaringKind, Spanned}; use syntax::std_inject; use syntax::symbol::{keywords, Symbol}; -use syntax::tokenstream::{Delimited, TokenStream, TokenTree}; +use syntax::tokenstream::{TokenStream, TokenTree}; use syntax::parse::token::Token; use syntax::visit::{self, Visitor}; use syntax_pos::{Span, MultiSpan}; @@ -82,7 +82,7 @@ const HIR_ID_COUNTER_LOCKED: u32 = 0xFFFFFFFF; pub struct LoweringContext<'a> { crate_root: Option<&'static str>, - // Use to assign ids to hir nodes that do not directly correspond to an ast node + // Used to assign ids to HIR nodes that do not directly correspond to an AST node. sess: &'a Session, cstore: &'a dyn CrateStore, @@ -114,10 +114,10 @@ pub struct LoweringContext<'a> { anonymous_lifetime_mode: AnonymousLifetimeMode, // Used to create lifetime definitions from in-band lifetime usages. - // e.g. `fn foo(x: &'x u8) -> &'x u8` to `fn foo<'x>(x: &'x u8) -> &'x u8` + // e.g., `fn foo(x: &'x u8) -> &'x u8` to `fn foo<'x>(x: &'x u8) -> &'x u8` // When a named lifetime is encountered in a function or impl header and // has not been defined - // (i.e. it doesn't appear in the in_scope_lifetimes list), it is added + // (i.e., it doesn't appear in the in_scope_lifetimes list), it is added // to this list. The results of this list are then added to the list of // lifetime definitions in the corresponding impl or function generics. lifetimes_to_define: Vec<(Span, ParamName)>, @@ -149,7 +149,7 @@ pub trait Resolver { is_value: bool, ) -> hir::Path; - /// Obtain the resolution for a node id + /// Obtain the resolution for a node-id. fn get_resolution(&mut self, id: NodeId) -> Option; /// Obtain the possible resolutions for the given `use` statement. @@ -159,8 +159,8 @@ pub trait Resolver { /// This should only return `None` during testing. fn definitions(&mut self) -> &mut Definitions; - /// Given suffix ["b","c","d"], creates a HIR path for `[::crate_root]::b::c::d` and resolves - /// it based on `is_value`. + /// Given suffix `["b", "c", "d"]`, creates a HIR path for `[::crate_root]::b::c::d` and + /// resolves it based on `is_value`. fn resolve_str_path( &mut self, span: Span, @@ -185,7 +185,7 @@ enum ImplTraitContext<'a> { /// /// We optionally store a `DefId` for the parent item here so we can look up necessary /// information later. It is `None` when no information about the context should be stored, - /// e.g. for consts and statics. + /// e.g., for consts and statics. Existential(Option), /// `impl Trait` is not accepted in this position. @@ -358,8 +358,8 @@ impl<'a> LoweringContext<'a> { fn lower_crate(mut self, c: &Crate) -> hir::Crate { /// Full-crate AST visitor that inserts into a fresh /// `LoweringContext` any information that may be - /// needed from arbitrary locations in the crate. - /// E.g. The number of lifetime generic parameters + /// needed from arbitrary locations in the crate, + /// e.g., the number of lifetime generic parameters /// declared for every type and trait definition. struct MiscCollector<'lcx, 'interner: 'lcx> { lctx: &'lcx mut LoweringContext<'interner>, @@ -512,7 +512,7 @@ impl<'a> LoweringContext<'a> { debug ); } - // Always allocate the first HirId for the owner itself + // Always allocate the first `HirId` for the owner itself. self.lower_node_id_with_owner(owner, owner) } @@ -536,7 +536,7 @@ impl<'a> LoweringContext<'a> { let existing_hir_id = self.node_id_to_hir_id[ast_node_id]; if existing_hir_id == hir::DUMMY_HIR_ID { - // Generate a new HirId + // Generate a new `HirId`. let hir_id = alloc_hir_id(self); self.node_id_to_hir_id[ast_node_id] = hir_id; LoweredNodeId { @@ -573,12 +573,12 @@ impl<'a> LoweringContext<'a> { ret } - /// This method allocates a new HirId for the given NodeId and stores it in - /// the LoweringContext's NodeId => HirId map. - /// Take care not to call this method if the resulting HirId is then not + /// This method allocates a new `HirId` for the given `NodeId` and stores it in + /// the `LoweringContext`'s `NodeId => HirId` map. + /// Take care not to call this method if the resulting `HirId` is then not /// actually used in the HIR, as that would trigger an assertion in the - /// HirIdValidator later on, which makes sure that all NodeIds got mapped - /// properly. Calling the method twice with the same NodeId is fine though. + /// `HirIdValidator` later on, which makes sure that all `NodeId`s got mapped + /// properly. Calling the method twice with the same `NodeId` is fine though. fn lower_node_id(&mut self, ast_node_id: NodeId) -> LoweredNodeId { self.lower_node_id_generic(ast_node_id, |this| { let &mut (def_index, ref mut local_id_counter) = @@ -743,7 +743,7 @@ impl<'a> LoweringContext<'a> { ), }; - // Add a definition for the in-band lifetime def + // Add a definition for the in-band lifetime def. self.resolver.definitions().create_def_with_parent( parent_id.index, def_node_id, @@ -1067,7 +1067,7 @@ impl<'a> LoweringContext<'a> { fn lower_attr(&mut self, attr: &Attribute) -> Attribute { // Note that we explicitly do not walk the path. Since we don't really // lower attributes (we use the AST version) there is nowhere to keep - // the HirIds. We don't actually need HIR version of attributes anyway. + // the `HirId`s. We don't actually need HIR version of attributes anyway. Attribute { id: attr.id, style: attr.style, @@ -1088,12 +1088,10 @@ impl<'a> LoweringContext<'a> { fn lower_token_tree(&mut self, tree: TokenTree) -> TokenStream { match tree { TokenTree::Token(span, token) => self.lower_token(token, span), - TokenTree::Delimited(span, delimited) => TokenTree::Delimited( + TokenTree::Delimited(span, delim, tts) => TokenTree::Delimited( span, - Delimited { - delim: delimited.delim, - tts: self.lower_token_stream(delimited.tts.into()).into(), - }, + delim, + self.lower_token_stream(tts.into()).into(), ).into(), } } @@ -1201,7 +1199,7 @@ impl<'a> LoweringContext<'a> { None, P(hir::Path { def: self.expect_full_def(t.id), - segments: hir_vec![hir::PathSegment::from_ident(keywords::SelfType.ident())], + segments: hir_vec![hir::PathSegment::from_ident(keywords::SelfUpper.ident())], span: t.span, }), )), @@ -1246,7 +1244,7 @@ impl<'a> LoweringContext<'a> { } ImplTraitContext::Universal(in_band_ty_params) => { self.lower_node_id(def_node_id); - // Add a definition for the in-band Param + // Add a definition for the in-band `Param`. let def_index = self .resolver .definitions() @@ -1257,7 +1255,7 @@ impl<'a> LoweringContext<'a> { bounds, ImplTraitContext::Universal(in_band_ty_params), ); - // Set the name to `impl Bound1 + Bound2` + // Set the name to `impl Bound1 + Bound2`. let ident = Ident::from_str(&pprust::ty_to_string(t)).with_span_pos(span); in_band_ty_params.push(hir::GenericParam { id: def_node_id, @@ -1365,7 +1363,7 @@ impl<'a> LoweringContext<'a> { impl_trait_fn: fn_def_id, }); let exist_ty_id = lctx.lower_node_id(exist_ty_node_id); - // Generate an `existential type Foo: Trait;` declaration + // Generate an `existential type Foo: Trait;` declaration. trace!("creating existential type with id {:#?}", exist_ty_id); trace!("exist ty def index: {:#?}", exist_ty_def_index); @@ -1384,7 +1382,7 @@ impl<'a> LoweringContext<'a> { // does not actually exist in the AST. lctx.items.insert(exist_ty_id.node_id, exist_ty_item); - // `impl Trait` now just becomes `Foo<'a, 'b, ..>` + // `impl Trait` now just becomes `Foo<'a, 'b, ..>`. hir::TyKind::Def(hir::ItemId { id: exist_ty_id.node_id }, lifetimes) }) } @@ -1397,7 +1395,7 @@ impl<'a> LoweringContext<'a> { ) -> (HirVec, HirVec) { // This visitor walks over impl trait bounds and creates defs for all lifetimes which // appear in the bounds, excluding lifetimes that are created within the bounds. - // e.g. 'a, 'b, but not 'c in `impl for<'c> SomeTrait<'a, 'b, 'c>` + // E.g., `'a`, `'b`, but not `'c` in `impl for<'c> SomeTrait<'a, 'b, 'c>`. struct ImplTraitLifetimeCollector<'r, 'a: 'r> { context: &'r mut LoweringContext<'a>, parent: DefIndex, @@ -1429,7 +1427,7 @@ impl<'a> LoweringContext<'a> { } fn visit_ty(&mut self, t: &'v hir::Ty) { - // Don't collect elided lifetimes used inside of `fn()` syntax + // Don't collect elided lifetimes used inside of `fn()` syntax. if let hir::TyKind::BareFn(_) = t.node { let old_collect_elided_lifetimes = self.collect_elided_lifetimes; self.collect_elided_lifetimes = false; @@ -1459,10 +1457,10 @@ impl<'a> LoweringContext<'a> { } fn visit_generic_param(&mut self, param: &'v hir::GenericParam) { - // Record the introduction of 'a in `for<'a> ...` + // Record the introduction of 'a in `for<'a> ...`. if let hir::GenericParamKind::Lifetime { .. } = param.kind { // Introduce lifetimes one at a time so that we can handle - // cases like `fn foo<'d>() -> impl for<'a, 'b: 'a, 'c: 'b + 'd>` + // cases like `fn foo<'d>() -> impl for<'a, 'b: 'a, 'c: 'b + 'd>`. let lt_name = hir::LifetimeName::Param(param.name); self.currently_bound_lifetimes.push(lt_name); } @@ -1475,7 +1473,7 @@ impl<'a> LoweringContext<'a> { hir::LifetimeName::Implicit | hir::LifetimeName::Underscore => { if self.collect_elided_lifetimes { // Use `'_` for both implicit and underscore lifetimes in - // `abstract type Foo<'_>: SomeTrait<'_>;` + // `abstract type Foo<'_>: SomeTrait<'_>;`. hir::LifetimeName::Underscore } else { return; @@ -1648,7 +1646,7 @@ impl<'a> LoweringContext<'a> { { ParenthesizedGenericArgs::Ok } - // Avoid duplicated errors + // Avoid duplicated errors. Def::Err => ParenthesizedGenericArgs::Ok, // An error Def::Struct(..) @@ -1689,7 +1687,7 @@ impl<'a> LoweringContext<'a> { }); // Simple case, either no projections, or only fully-qualified. - // E.g. `std::mem::size_of` or `::Item`. + // E.g., `std::mem::size_of` or `::Item`. if resolution.unresolved_segments() == 0 { return hir::QPath::Resolved(qself, path); } @@ -1697,11 +1695,11 @@ impl<'a> LoweringContext<'a> { // Create the innermost type that we're projecting from. let mut ty = if path.segments.is_empty() { // If the base path is empty that means there exists a - // syntactical `Self`, e.g. `&i32` in `<&i32>::clone`. + // syntactical `Self`, e.g., `&i32` in `<&i32>::clone`. qself.expect("missing QSelf for ::...") } else { // Otherwise, the base path is an implicit `Self` type path, - // e.g. `Vec` in `Vec::new` or `::Item` in + // e.g., `Vec` in `Vec::new` or `::Item` in // `::Item::default`. let new_id = self.next_id(); P(self.ty_path(new_id, p.span, hir::QPath::Resolved(qself, path))) @@ -1709,7 +1707,7 @@ impl<'a> LoweringContext<'a> { // Anything after the base path are associated "extensions", // out of which all but the last one are associated types, - // e.g. for `std::vec::Vec::::IntoIter::Item::clone`: + // e.g., for `std::vec::Vec::::IntoIter::Item::clone`: // * base path is `std::vec::Vec` // * "extensions" are `IntoIter`, `Item` and `clone` // * type nodes are: @@ -1739,7 +1737,7 @@ impl<'a> LoweringContext<'a> { ty = P(self.ty_path(new_id, p.span, qpath)); } - // Should've returned in the for loop above. + // We should've returned in the for loop above. span_bug!( p.span, "lower_qpath: no final extension segment in {}..{}", @@ -1838,11 +1836,11 @@ impl<'a> LoweringContext<'a> { let no_bindings = generic_args.bindings.is_empty(); let (incl_angl_brckt, insertion_span, suggestion) = if no_ty_args && no_bindings { // If there are no (non-implicit) generic args or associated-type - // bindings, our suggestion includes the angle brackets + // bindings, our suggestion includes the angle brackets. (true, path_span.shrink_to_hi(), format!("<{}>", anon_lt_suggestion)) } else { // Otherwise—sorry, this is kind of gross—we need to infer the - // place to splice in the `'_, ` from the generics that do exist + // place to splice in the `'_, ` from the generics that do exist. let first_generic_span = first_generic_span .expect("already checked that type args or bindings exist"); (false, first_generic_span.shrink_to_lo(), format!("{}, ", anon_lt_suggestion)) @@ -2096,14 +2094,15 @@ impl<'a> LoweringContext<'a> { return_impl_trait_id: NodeId, ) -> hir::FunctionRetTy { // Get lifetimes used in the input arguments to the function. Our output type must also - // have the same lifetime. FIXME(cramertj) multiple different lifetimes are not allowed - // because `impl Trait + 'a + 'b` doesn't allow for capture `'a` and `'b` where neither - // is a subset of the other. We really want some new lifetime that is a subset of all input - // lifetimes, but that doesn't exist at the moment. + // have the same lifetime. + // FIXME(cramertj): multiple different lifetimes are not allowed because + // `impl Trait + 'a + 'b` doesn't allow for capture `'a` and `'b` where neither is a subset + // of the other. We really want some new lifetime that is a subset of all input lifetimes, + // but that doesn't exist at the moment. struct AsyncFnLifetimeCollector<'r, 'a: 'r> { context: &'r mut LoweringContext<'a>, - // Lifetimes bound by HRTB + // Lifetimes bound by HRTB. currently_bound_lifetimes: Vec, // Whether to count elided lifetimes. // Disabled inside of `Fn` or `fn` syntax. @@ -2133,7 +2132,7 @@ impl<'a> LoweringContext<'a> { } fn visit_ty(&mut self, t: &'v hir::Ty) { - // Don't collect elided lifetimes used inside of `fn()` syntax + // Don't collect elided lifetimes used inside of `fn()` syntax. if let &hir::TyKind::BareFn(_) = &t.node { let old_collect_elided_lifetimes = self.collect_elided_lifetimes; self.collect_elided_lifetimes = false; @@ -2424,8 +2423,8 @@ impl<'a> LoweringContext<'a> { GenericParamKind::Type { ref default, .. } => { // Don't expose `Self` (recovered "keyword used as ident" parse error). // `rustc::ty` expects `Self` to be only used for a trait's `Self`. - // Instead, use gensym("Self") to create a distinct name that looks the same. - let ident = if param.ident.name == keywords::SelfType.name() { + // Instead, use `gensym("Self")` to create a distinct name that looks the same. + let ident = if param.ident.name == keywords::SelfUpper.name() { param.ident.gensym() } else { param.ident @@ -2467,7 +2466,7 @@ impl<'a> LoweringContext<'a> { -> hir::Generics { // Collect `?Trait` bounds in where clause and move them to parameter definitions. - // FIXME: This could probably be done with less rightward drift. Also looks like two control + // FIXME: this could probably be done with less rightward drift. Also looks like two control // paths where report_error is called are also the only paths that advance to after // the match statement, so the error reporting could probably just be moved there. let mut add_bounds: NodeMap> = Default::default(); @@ -2563,7 +2562,7 @@ impl<'a> LoweringContext<'a> { .iter() .filter_map(|bound| match *bound { // Ignore `?Trait` bounds. - // Tthey were copied into type parameters already. + // They were copied into type parameters already. GenericBound::Trait(_, TraitBoundModifier::Maybe) => None, _ => Some(this.lower_param_bound( bound, @@ -2662,7 +2661,7 @@ impl<'a> LoweringContext<'a> { id: self.lower_node_id(f.id).node_id, ident: match f.ident { Some(ident) => ident, - // FIXME(jseyfried) positional field hygiene + // FIXME(jseyfried): positional field hygiene None => Ident::new(Symbol::intern(&index.to_string()), f.span), }, vis: self.lower_visibility(&f.vis, None), @@ -2946,7 +2945,7 @@ impl<'a> LoweringContext<'a> { } // [1] `defaultness.has_value()` is never called for an `impl`, always `true` in order to - // not cause an assertion failure inside the `lower_defaultness` function + // not cause an assertion failure inside the `lower_defaultness` function. } fn lower_use_tree( @@ -2981,7 +2980,7 @@ impl<'a> LoweringContext<'a> { // Correctly resolve `self` imports if path.segments.len() > 1 - && path.segments.last().unwrap().ident.name == keywords::SelfValue.name() + && path.segments.last().unwrap().ident.name == keywords::SelfLower.name() { let _ = path.segments.pop(); if rename.is_none() { @@ -3190,7 +3189,7 @@ impl<'a> LoweringContext<'a> { /// Paths like the visibility path in `pub(super) use foo::{bar, baz}` are repeated /// many times in the HIR tree; for each occurrence, we need to assign distinct - /// node-ids. (See e.g. #56128.) + /// node-ids. (See e.g., #56128.) fn renumber_segment_ids(&mut self, path: &P) -> P { debug!("renumber_segment_ids(path = {:?})", path); let mut path = path.clone(); @@ -3780,7 +3779,7 @@ impl<'a> LoweringContext<'a> { let else_opt = else_opt.as_ref().map(|els| { match els.node { ExprKind::IfLet(..) => { - // wrap the if-let expr in a block + // Wrap the `if let` expr in a block. let span = els.span; let els = P(self.lower_expr(els)); let LoweredNodeId { node_id, hir_id } = self.next_id(); @@ -3871,7 +3870,7 @@ impl<'a> LoweringContext<'a> { let fn_decl = self.lower_fn_decl(&outer_decl, None, false, None); self.with_new_scopes(|this| { - // FIXME(cramertj) allow `async` non-`move` closures with + // FIXME(cramertj): allow `async` non-`move` closures with arguments. if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() { @@ -3883,13 +3882,13 @@ impl<'a> LoweringContext<'a> { are not currently supported", ) .help("consider using `let` statements to manually capture \ - variables by reference before entering an \ - `async move` closure") + variables by reference before entering an \ + `async move` closure") .emit(); } // Transform `async |x: u8| -> X { ... }` into - // `|x: u8| future_from_generator(|| -> X { ... })` + // `|x: u8| future_from_generator(|| -> X { ... })`. let body_id = this.lower_body(Some(&outer_decl), |this| { let async_ret_ty = if let FunctionRetTy::Ty(ty) = &decl.output { Some(&**ty) @@ -3972,7 +3971,7 @@ impl<'a> LoweringContext<'a> { ExprKind::Index(ref el, ref er) => { hir::ExprKind::Index(P(self.lower_expr(el)), P(self.lower_expr(er))) } - // Desugar `..=` to `std::ops::RangeInclusive::new(, )` + // Desugar `..=` into `std::ops::RangeInclusive::new(, )`. ExprKind::Range(Some(ref e1), Some(ref e2), RangeLimits::Closed) => { let id = self.next_id(); let e1 = self.lower_expr(e1); @@ -4106,11 +4105,11 @@ impl<'a> LoweringContext<'a> { ), ExprKind::Paren(ref ex) => { let mut ex = self.lower_expr(ex); - // include parens in span, but only if it is a super-span. + // Include parens in span, but only if it is a super-span. if e.span.contains(ex.span) { ex.span = e.span; } - // merge attributes into the inner expression. + // Merge attributes into the inner expression. let mut attrs = e.attrs.clone(); attrs.extend::>(ex.attrs.into()); ex.attrs = attrs; @@ -4128,8 +4127,8 @@ impl<'a> LoweringContext<'a> { hir::ExprKind::Yield(P(expr)) } - // Desugar ExprIfLet - // From: `if let = []` + // Desugar `ExprIfLet` + // from: `if let = []` ExprKind::IfLet(ref pats, ref sub_expr, ref body, ref else_opt) => { // to: // @@ -4173,8 +4172,8 @@ impl<'a> LoweringContext<'a> { ) } - // Desugar ExprWhileLet - // From: `[opt_ident]: while let = ` + // Desugar `ExprWhileLet` + // from: `[opt_ident]: while let = ` ExprKind::WhileLet(ref pats, ref sub_expr, ref body, opt_label) => { // to: // @@ -4223,12 +4222,12 @@ impl<'a> LoweringContext<'a> { self.lower_label(opt_label), hir::LoopSource::WhileLet, ); - // add attributes to the outer returned expr node + // Add attributes to the outer returned expr node. loop_expr } - // Desugar ExprForLoop - // From: `[opt_ident]: for in ` + // Desugar `ExprForLoop` + // from: `[opt_ident]: for in ` ExprKind::ForLoop(ref pat, ref head, ref body, opt_label) => { // to: // @@ -4386,21 +4385,21 @@ impl<'a> LoweringContext<'a> { )); // `{ let _result = ...; _result }` - // underscore prevents an unused_variables lint if the head diverges + // Underscore prevents an `unused_variables` lint if the head diverges. let result_ident = self.str_to_ident("_result"); let (let_stmt, let_stmt_binding) = self.stmt_let(e.span, false, result_ident, match_expr); let result = P(self.expr_ident(e.span, result_ident, let_stmt_binding)); let block = P(self.block_all(e.span, hir_vec![let_stmt], Some(result))); - // add the attributes to the outer returned expr node + // Add the attributes to the outer returned expr node. return self.expr_block(block, e.attrs.clone()); } - // Desugar ExprKind::Try - // From: `?` + // Desugar `ExprKind::Try` + // from: `?` ExprKind::Try(ref sub_expr) => { - // to: + // into: // // match Try::into_result() { // Ok(val) => #[allow(unreachable_code)] val, @@ -4414,7 +4413,7 @@ impl<'a> LoweringContext<'a> { let unstable_span = self.allow_internal_unstable(CompilerDesugaringKind::QuestionMark, e.span); - // Try::into_result() + // `Try::into_result()` let discr = { // expand let sub_expr = self.lower_expr(sub_expr); @@ -4425,9 +4424,9 @@ impl<'a> LoweringContext<'a> { P(self.expr_call(e.span, path, hir_vec![sub_expr])) }; - // #[allow(unreachable_code)] + // `#[allow(unreachable_code)]` let attr = { - // allow(unreachable_code) + // `allow(unreachable_code)` let allow = { let allow_ident = Ident::from_str("allow").with_span_pos(e.span); let uc_ident = Ident::from_str("unreachable_code").with_span_pos(e.span); @@ -4438,7 +4437,7 @@ impl<'a> LoweringContext<'a> { }; let attrs = vec![attr]; - // Ok(val) => #[allow(unreachable_code)] val, + // `Ok(val) => #[allow(unreachable_code)] val,` let ok_arm = { let val_ident = self.str_to_ident("val"); let val_pat = self.pat_ident(e.span, val_ident); @@ -4453,8 +4452,8 @@ impl<'a> LoweringContext<'a> { self.arm(hir_vec![ok_pat], val_expr) }; - // Err(err) => #[allow(unreachable_code)] - // return Try::from_error(From::from(err)), + // `Err(err) => #[allow(unreachable_code)] + // return Try::from_error(From::from(err)),` let err_arm = { let err_ident = self.str_to_ident("err"); let err_local = self.pat_ident(e.span, err_ident); @@ -5014,7 +5013,7 @@ impl<'a> LoweringContext<'a> { /// error, depending on the mode. fn elided_path_lifetimes(&mut self, span: Span, count: usize) -> P<[hir::Lifetime]> { match self.anonymous_lifetime_mode { - // NB. We intentionally ignore the create-parameter mode here + // N.B., We intentionally ignore the create-parameter mode here // and instead "pass through" to resolve-lifetimes, which will then // report an error. This is because we don't want to support // impl elision for deprecated forms like diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs index 1ab1c7d3fc5..40904eaa5db 100644 --- a/src/librustc/hir/map/blocks.rs +++ b/src/librustc/hir/map/blocks.rs @@ -13,7 +13,7 @@ //! it captures a common set of attributes that all "function-like //! things" (represented by `FnLike` instances) share. For example, //! all `FnLike` instances have a type signature (be it explicit or -//! inferred). And all `FnLike` instances have a body, i.e. the code +//! inferred). And all `FnLike` instances have a body, i.e., the code //! that is run when the function-like thing it represents is invoked. //! //! With the above abstraction in place, one can treat the program @@ -34,7 +34,7 @@ use syntax_pos::Span; /// More specifically, it is one of either: /// /// - A function item, -/// - A closure expr (i.e. an ExprKind::Closure), or +/// - A closure expr (i.e., an ExprKind::Closure), or /// - The default implementation for a trait method. /// /// To construct one, use the `Code::from_node` function. diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index eb9bd183fd9..d5031efae57 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -150,10 +150,9 @@ impl Decodable for DefPathTable { } } - /// The definition table containing node definitions. -/// It holds the DefPathTable for local DefIds/DefPaths and it also stores a -/// mapping from NodeIds to local DefIds. +/// It holds the `DefPathTable` for local `DefId`s/`DefPath`s and it also stores a +/// mapping from `NodeId`s to local `DefId`s. #[derive(Clone, Default)] pub struct Definitions { table: DefPathTable, diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc/hir/map/hir_id_validator.rs index ac4119dc372..58d1a780f12 100644 --- a/src/librustc/hir/map/hir_id_validator.rs +++ b/src/librustc/hir/map/hir_id_validator.rs @@ -100,7 +100,7 @@ impl<'a, 'hir: 'a> HirIdValidator<'a, 'hir> { if max != self.hir_ids_seen.len() - 1 { // Collect the missing ItemLocalIds - let missing: Vec<_> = (0 .. max as u32 + 1) + let missing: Vec<_> = (0 ..= max as u32) .filter(|&i| !self.hir_ids_seen.contains_key(&ItemLocalId::from_u32(i))) .collect(); diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index ef777abfbc4..de8a375ca6d 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -159,6 +159,13 @@ impl Forest { self.dep_graph.read(DepNode::new_no_params(DepKind::Krate)); &self.krate } + + /// This is internally in the depedency tracking system. + /// Use the `krate` method to ensure your dependency on the + /// crate is tracked. + pub fn untracked_krate<'hir>(&'hir self) -> &'hir Crate { + &self.krate + } } /// Represents a mapping from Node IDs to AST elements and their parent @@ -286,9 +293,7 @@ impl<'hir> Map<'hir> { match node { Node::Item(item) => { - let def_id = || { - self.local_def_id(item.id) - }; + let def_id = || self.local_def_id(item.id); match item.node { ItemKind::Static(_, m, _) => Some(Def::Static(def_id(), m == MutMutable)), @@ -383,7 +388,7 @@ impl<'hir> Map<'hir> { pub fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem { self.read(id.node_id); - // NB: intentionally bypass `self.forest.krate()` so that we + // N.B., intentionally bypass `self.forest.krate()` so that we // do not trigger a read of the whole krate here self.forest.krate.trait_item(id) } @@ -391,7 +396,7 @@ impl<'hir> Map<'hir> { pub fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem { self.read(id.node_id); - // NB: intentionally bypass `self.forest.krate()` so that we + // N.B., intentionally bypass `self.forest.krate()` so that we // do not trigger a read of the whole krate here self.forest.krate.impl_item(id) } @@ -399,7 +404,7 @@ impl<'hir> Map<'hir> { pub fn body(&self, id: BodyId) -> &'hir Body { self.read(id.node_id); - // NB: intentionally bypass `self.forest.krate()` so that we + // N.B., intentionally bypass `self.forest.krate()` so that we // do not trigger a read of the whole krate here self.forest.krate.body(id) } @@ -413,7 +418,7 @@ impl<'hir> Map<'hir> { } /// Returns the `NodeId` that corresponds to the definition of - /// which this is the body of, i.e. a `fn`, `const` or `static` + /// which this is the body of, i.e., a `fn`, `const` or `static` /// item (possibly associated), a closure, or a `hir::AnonConst`. pub fn body_owner(&self, BodyId { node_id }: BodyId) -> NodeId { let parent = self.get_parent_node(node_id); @@ -475,7 +480,7 @@ impl<'hir> Map<'hir> { pub fn ty_param_name(&self, id: NodeId) -> Name { match self.get(id) { - Node::Item(&Item { node: ItemKind::Trait(..), .. }) => keywords::SelfType.name(), + Node::Item(&Item { node: ItemKind::Trait(..), .. }) => keywords::SelfUpper.name(), Node::GenericParam(param) => param.name.ident().name, _ => bug!("ty_param_name: {} not a type parameter", self.node_to_string(id)), } @@ -484,7 +489,7 @@ impl<'hir> Map<'hir> { pub fn trait_impls(&self, trait_did: DefId) -> &'hir [NodeId] { self.dep_graph.read(DepNode::new_no_params(DepKind::AllLocalTraitImpls)); - // NB: intentionally bypass `self.forest.krate()` so that we + // N.B., intentionally bypass `self.forest.krate()` so that we // do not trigger a read of the whole krate here self.forest.krate.trait_impls.get(&trait_did).map_or(&[], |xs| &xs[..]) } @@ -492,7 +497,7 @@ impl<'hir> Map<'hir> { pub fn trait_auto_impl(&self, trait_did: DefId) -> Option { self.dep_graph.read(DepNode::new_no_params(DepKind::AllLocalTraitImpls)); - // NB: intentionally bypass `self.forest.krate()` so that we + // N.B., intentionally bypass `self.forest.krate()` so that we // do not trigger a read of the whole krate here self.forest.krate.trait_auto_impl.get(&trait_did).cloned() } @@ -565,14 +570,14 @@ impl<'hir> Map<'hir> { result } - /// Similar to get_parent, returns the parent node id or id if there is no - /// parent. Note that the parent may be CRATE_NODE_ID, which is not itself + /// Similar to `get_parent`; returns the parent node-id, or own `id` if there is + /// no parent. Note that the parent may be `CRATE_NODE_ID`, which is not itself /// present in the map -- so passing the return value of get_parent_node to /// get may actually panic. /// This function returns the immediate parent in the AST, whereas get_parent /// returns the enclosing item. Note that this might not be the actual parent /// node in the AST - some kinds of nodes are not in the map and these will - /// never appear as the parent_node. So you can always walk the parent_nodes + /// never appear as the parent_node. So you can always walk the `parent_nodes` /// from a node to the root of the ast (unless you get the same id back here /// that can happen if the id is not in the map itself or is just weird). pub fn get_parent_node(&self, id: NodeId) -> NodeId { @@ -608,7 +613,7 @@ impl<'hir> Map<'hir> { /// If there is some error when walking the parents (e.g., a node does not /// have a parent in the map or a node can't be found), then we return the - /// last good node id we found. Note that reaching the crate root (id == 0), + /// last good node id we found. Note that reaching the crate root (`id == 0`), /// is not an error, since items in the crate module have the crate root as /// parent. fn walk_parent_nodes(&self, @@ -644,7 +649,7 @@ impl<'hir> Map<'hir> { } } - /// Retrieve the NodeId for `id`'s enclosing method, unless there's a + /// Retrieve the `NodeId` for `id`'s enclosing method, unless there's a /// `while` or `loop` before reaching it, as block tail returns are not /// available in them. /// @@ -691,7 +696,7 @@ impl<'hir> Map<'hir> { self.walk_parent_nodes(id, match_fn, match_non_returning_block).ok() } - /// Retrieve the NodeId for `id`'s parent item, or `id` itself if no + /// Retrieve the `NodeId` for `id`'s parent item, or `id` itself if no /// parent item is in this map. The "parent item" is the closest parent node /// in the HIR which is recorded by the map and is an item, either an item /// in a module, trait, or impl. @@ -708,13 +713,13 @@ impl<'hir> Map<'hir> { } } - /// Returns the DefId 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 { self.local_def_id(self.get_module_parent_node(id)) } - /// Returns the NodeId of `id`'s nearest module parent, or `id` itself if no + /// 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 { @@ -727,7 +732,7 @@ impl<'hir> Map<'hir> { } /// Returns the nearest enclosing scope. A scope is an item or block. - /// FIXME it is not clear to me that all items qualify as scopes - statics + /// FIXME: it is not clear to me that all items qualify as scopes -- statics /// and associated types probably shouldn't, for example. Behavior in this /// regard should be expected to be highly unstable. pub fn get_enclosing_scope(&self, id: NodeId) -> Option { @@ -1258,8 +1263,8 @@ fn node_id_to_string(map: &Map<'_>, id: NodeId, include_id: bool) -> String { } pub fn describe_def(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Option { - if let Some(node_id) = tcx.hir.as_local_node_id(def_id) { - tcx.hir.describe_def(node_id) + if let Some(node_id) = tcx.hir().as_local_node_id(def_id) { + tcx.hir().describe_def(node_id) } else { bug!("Calling local describe_def query provider for upstream DefId: {:?}", def_id) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 1674320165e..156d55b9e2f 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// The Rust HIR. +// HIR datatypes. See the [rustc guide] for more info. +//! +//! [rustc guide]: https://rust-lang.github.io/rustc-guide/hir.html pub use self::BlockCheckMode::*; pub use self::CaptureClause::*; @@ -71,7 +73,7 @@ pub mod print; /// A HirId uniquely identifies a node in the HIR of the current crate. It is /// composed of the `owner`, which is the DefIndex of the directly enclosing -/// hir::Item, hir::TraitItem, or hir::ImplItem (i.e. the closest "item-like"), +/// hir::Item, hir::TraitItem, or hir::ImplItem (i.e., the closest "item-like"), /// and the `local_id` which is unique within the given owner. /// /// This two-level structure makes for more stable values: One can move an item @@ -181,7 +183,7 @@ pub enum ParamName { Plain(Ident), /// Synthetic name generated when user elided a lifetime in an impl header, - /// e.g. the lifetimes in cases like these: + /// e.g., the lifetimes in cases like these: /// /// impl Foo for &u32 /// impl Foo<'_> for u32 @@ -197,7 +199,7 @@ pub enum ParamName { /// Indicates an illegal name was given and an error has been /// repored (so we should squelch other derived errors). Occurs - /// when e.g. `'_` is used in the wrong place. + /// when e.g., `'_` is used in the wrong place. Error, } @@ -222,7 +224,7 @@ pub enum LifetimeName { /// User-given names or fresh (synthetic) names. Param(ParamName), - /// User typed nothing. e.g. the lifetime in `&u32`. + /// User typed nothing. e.g., the lifetime in `&u32`. Implicit, /// Indicates an error during lowering (usually `'_` in wrong place) @@ -311,7 +313,7 @@ pub struct Path { impl Path { pub fn is_global(&self) -> bool { - !self.segments.is_empty() && self.segments[0].ident.name == keywords::CrateRoot.name() + !self.segments.is_empty() && self.segments[0].ident.name == keywords::PathRoot.name() } } @@ -351,7 +353,7 @@ pub struct PathSegment { /// Whether to infer remaining type parameters, if any. /// This only applies to expression and pattern paths, and /// out of those only the segments with no type parameters - /// to begin with, e.g. `Vec::new` is `>::new::<..>`. + /// to begin with, e.g., `Vec::new` is `>::new::<..>`. pub infer_types: bool, } @@ -388,7 +390,7 @@ impl PathSegment { } // FIXME: hack required because you can't create a static - // GenericArgs, so you can't just return a &GenericArgs. + // `GenericArgs`, so you can't just return a `&GenericArgs`. pub fn with_generic_args(&self, f: F) -> R where F: FnOnce(&GenericArgs) -> R { @@ -514,17 +516,17 @@ pub type GenericBounds = HirVec; #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)] pub enum LifetimeParamKind { - // Indicates that the lifetime definition was explicitly declared, like: - // `fn foo<'a>(x: &'a u8) -> &'a u8 { x }` + // Indicates that the lifetime definition was explicitly declared (e.g., in + // `fn foo<'a>(x: &'a u8) -> &'a u8 { x }`). Explicit, // Indicates that the lifetime definition was synthetically added - // as a result of an in-band lifetime usage like: - // `fn foo(x: &'a u8) -> &'a u8 { x }` + // as a result of an in-band lifetime usage (e.g., in + // `fn foo(x: &'a u8) -> &'a u8 { x }`). InBand, - // Indication that the lifetime was elided like both cases here: - // `fn foo(x: &u8) -> &'_ u8 { x }` + // Indication that the lifetime was elided (e.g., in both cases in + // `fn foo(x: &u8) -> &'_ u8 { x }`). Elided, // Indication that the lifetime name was somehow in error. @@ -533,7 +535,7 @@ pub enum LifetimeParamKind { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum GenericParamKind { - /// A lifetime definition, eg `'a: 'b + 'c + 'd`. + /// A lifetime definition (e.g., `'a: 'b + 'c + 'd`). Lifetime { kind: LifetimeParamKind, }, @@ -637,11 +639,11 @@ impl WhereClause { /// A single predicate in a `where` clause #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum WherePredicate { - /// A type binding, eg `for<'c> Foo: Send+Clone+'c` + /// A type binding (e.g., `for<'c> Foo: Send + Clone + 'c`). BoundPredicate(WhereBoundPredicate), - /// A lifetime predicate, e.g. `'a: 'b+'c` + /// A lifetime predicate (e.g., `'a: 'b + 'c`). RegionPredicate(WhereRegionPredicate), - /// An equality predicate (unsupported) + /// An equality predicate (unsupported). EqPredicate(WhereEqPredicate), } @@ -667,7 +669,7 @@ pub struct WhereBoundPredicate { pub bounds: GenericBounds, } -/// A lifetime predicate, e.g. `'a: 'b+'c` +/// A lifetime predicate, e.g., `'a: 'b+'c` #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct WhereRegionPredicate { pub span: Span, @@ -675,7 +677,7 @@ pub struct WhereRegionPredicate { pub bounds: GenericBounds, } -/// An equality predicate (unsupported), e.g. `T=int` +/// An equality predicate (unsupported), e.g., `T=int` #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct WhereEqPredicate { pub id: NodeId, @@ -697,7 +699,7 @@ pub struct Crate { pub span: Span, pub exported_macros: HirVec, - // NB: We use a BTreeMap here so that `visit_all_items` iterates + // N.B., we use a BTreeMap here so that `visit_all_items` iterates // over the ids in increasing order. In principle it should not // matter what order we visit things in, but in *practice* it // does, because it can affect the order in which errors are @@ -932,11 +934,11 @@ pub enum PatKind { /// A fresh binding `ref mut binding @ OPT_SUBPATTERN`. /// The `NodeId` is the canonical ID for the variable being bound, - /// e.g. in `Ok(x) | Err(x)`, both `x` use the same canonical ID, + /// e.g., in `Ok(x) | Err(x)`, both `x` use the same canonical ID, /// which is the pattern ID of the first `x`. Binding(BindingAnnotation, NodeId, Ident, Option>), - /// A struct or struct variant pattern, e.g. `Variant {x, y, ..}`. + /// A struct or struct variant pattern, e.g., `Variant {x, y, ..}`. /// The `bool` is `true` in the presence of a `..`. Struct(QPath, HirVec>, bool), @@ -954,11 +956,11 @@ pub enum PatKind { Tuple(HirVec>, Option), /// A `box` pattern Box(P), - /// A reference pattern, e.g. `&mut (a, b)` + /// A reference pattern, e.g., `&mut (a, b)` Ref(P, Mutability), /// A literal Lit(P), - /// A range pattern, e.g. `1...2` or `1..2` + /// A range pattern, e.g., `1...2` or `1..2` Range(P, P, RangeEnd), /// `[a, b, ..i, y, z]` is represented as: /// `PatKind::Slice(box [a, b], Some(i), box [y, z])` @@ -1319,8 +1321,8 @@ pub enum BodyOwnerKind { /// A constant (expression) that's not an item or associated item, /// but needs its own `DefId` for type-checking, const-eval, etc. -/// These are usually found nested inside types (e.g. array lengths) -/// or expressions (e.g. repeat counts), and also used to define +/// These are usually found nested inside types (e.g., array lengths) +/// or expressions (e.g., repeat counts), and also used to define /// explicit discriminant values for enum variants. #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)] pub struct AnonConst { @@ -1541,12 +1543,12 @@ pub enum QPath { /// Path to a definition, optionally "fully-qualified" with a `Self` /// type, if the path points to an associated item in a trait. /// - /// E.g. an unqualified path like `Clone::clone` has `None` for `Self`, + /// e.g., an unqualified path like `Clone::clone` has `None` for `Self`, /// while ` as Clone>::clone` has `Some(Vec)` for `Self`, /// even though they both have the same two-segment `Clone::clone` `Path`. Resolved(Option>, P), - /// Type-related paths, e.g. `::default` or `::Output`. + /// Type-related paths, e.g., `::default` or `::Output`. /// Will be resolved by type-checking to an associated item. /// /// UFCS source paths can desugar into this, with `Vec::new` turning into @@ -1633,7 +1635,7 @@ pub enum CaptureClause { CaptureByRef, } -// NB: If you change this, you'll probably want to change the corresponding +// N.B., if you change this, you'll probably want to change the corresponding // type structure in middle/ty.rs as well. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct MutTy { @@ -1792,14 +1794,14 @@ pub enum TyKind { Ptr(MutTy), /// A reference (`&'a T` or `&'a mut T`) Rptr(Lifetime, MutTy), - /// A bare function (e.g. `fn(usize) -> bool`) + /// A bare function (e.g., `fn(usize) -> bool`) BareFn(P), /// The never type (`!`) Never, /// A tuple (`(A, B, C, D,...)`) Tup(HirVec), /// A path to a type definition (`module::module::...::Type`), or an - /// associated type, e.g. ` as Trait>::Type` or `::Target`. + /// associated type, e.g., ` as Trait>::Type` or `::Target`. /// /// Type parameters may be stored in each `PathSegment`. Path(QPath), @@ -1814,7 +1816,7 @@ pub enum TyKind { TraitObject(HirVec, Lifetime), /// Unused for now Typeof(AnonConst), - /// TyKind::Infer means the type should be inferred instead of it having been + /// `TyKind::Infer` means the type should be inferred instead of it having been /// specified. This can appear anywhere in a type. Infer, /// Placeholder for a type that has failed to be defined. @@ -2017,7 +2019,7 @@ pub struct VariantKind { pub name: Name, pub attrs: HirVec, pub data: VariantData, - /// Explicit discriminant, eg `Foo = 1` + /// Explicit discriminant, e.g., `Foo = 1` pub disr_expr: Option, } @@ -2025,15 +2027,15 @@ pub type Variant = Spanned; #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)] pub enum UseKind { - /// One import, e.g. `use foo::bar` or `use foo::bar as baz`. + /// One import, e.g., `use foo::bar` or `use foo::bar as baz`. /// Also produced for each element of a list `use`, e.g. // `use foo::{a, b}` lowers to `use foo::a; use foo::b;`. Single, - /// Glob import, e.g. `use foo::*`. + /// Glob import, e.g., `use foo::*`. Glob, - /// Degenerate list import, e.g. `use foo::{a, b}` produces + /// Degenerate list import, e.g., `use foo::{a, b}` produces /// an additional `use foo::{}` for performing checks such as /// unstable feature gating. May be removed in the future. ListStem, @@ -2196,7 +2198,7 @@ pub struct FnHeader { pub enum ItemKind { /// An `extern crate` item, with optional *original* crate name if the crate was renamed. /// - /// E.g. `extern crate foo` or `extern crate foo_bar as foo` + /// e.g., `extern crate foo` or `extern crate foo_bar as foo` ExternCrate(Option), /// `use foo::bar::*;` or `use foo::bar::baz as quux;` @@ -2218,15 +2220,15 @@ pub enum ItemKind { ForeignMod(ForeignMod), /// Module-level inline assembly (from global_asm!) GlobalAsm(P), - /// A type alias, e.g. `type Foo = Bar` + /// A type alias, e.g., `type Foo = Bar` Ty(P, Generics), - /// An existential type definition, e.g. `existential type Foo: Bar;` + /// An existential type definition, e.g., `existential type Foo: Bar;` Existential(ExistTy), - /// An enum definition, e.g. `enum Foo {C, D}` + /// An enum definition, e.g., `enum Foo {C, D}` Enum(EnumDef, Generics), - /// A struct definition, e.g. `struct Foo {x: A}` + /// A struct definition, e.g., `struct Foo {x: A}` Struct(VariantData, Generics), - /// A union definition, e.g. `union Foo {x: A, y: B}` + /// A union definition, e.g., `union Foo {x: A, y: B}` Union(VariantData, Generics), /// Represents a Trait Declaration Trait(IsAuto, Unsafety, Generics, GenericBounds, HirVec), diff --git a/src/librustc/hir/pat_util.rs b/src/librustc/hir/pat_util.rs index 8a714a5fbd8..d6816d3b81b 100644 --- a/src/librustc/hir/pat_util.rs +++ b/src/librustc/hir/pat_util.rs @@ -101,7 +101,7 @@ impl hir::Pat { } /// Checks if the pattern contains any patterns that bind something to - /// an ident, e.g. `foo`, or `Foo(foo)` or `foo @ Bar(..)`. + /// an ident, e.g., `foo`, or `Foo(foo)` or `foo @ Bar(..)`. pub fn contains_bindings(&self) -> bool { let mut contains_bindings = false; self.walk(|p| { @@ -116,7 +116,7 @@ impl hir::Pat { } /// Checks if the pattern contains any patterns that bind something to - /// an ident or wildcard, e.g. `foo`, or `Foo(_)`, `foo @ Bar(..)`, + /// an ident or wildcard, e.g., `foo`, or `Foo(_)`, `foo @ Bar(..)`, pub fn contains_bindings_or_wild(&self) -> bool { let mut contains_bindings = false; self.walk(|p| { diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 9a0ceddcf1b..5c6845181af 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -65,7 +65,7 @@ pub trait PpAnn { pub struct NoAnn; impl PpAnn for NoAnn {} -pub const NO_ANN: &'static dyn PpAnn = &NoAnn; +pub const NO_ANN: &dyn PpAnn = &NoAnn; impl PpAnn for hir::Crate { fn try_fetch_item(&self, item: ast::NodeId) -> Option<&hir::Item> { @@ -1622,8 +1622,7 @@ impl<'a> State<'a> { if i > 0 { self.s.word("::")? } - if segment.ident.name != keywords::CrateRoot.name() && - segment.ident.name != keywords::DollarCrate.name() { + if segment.ident.name != keywords::PathRoot.name() { self.print_ident(segment.ident)?; segment.with_generic_args(|generic_args| { self.print_generic_args(generic_args, segment.infer_types, @@ -1636,8 +1635,7 @@ impl<'a> State<'a> { } pub fn print_path_segment(&mut self, segment: &hir::PathSegment) -> io::Result<()> { - if segment.ident.name != keywords::CrateRoot.name() && - segment.ident.name != keywords::DollarCrate.name() { + if segment.ident.name != keywords::PathRoot.name() { self.print_ident(segment.ident)?; segment.with_generic_args(|generic_args| { self.print_generic_args(generic_args, segment.infer_types, false) @@ -1664,8 +1662,7 @@ impl<'a> State<'a> { if i > 0 { self.s.word("::")? } - if segment.ident.name != keywords::CrateRoot.name() && - segment.ident.name != keywords::DollarCrate.name() { + if segment.ident.name != keywords::PathRoot.name() { self.print_ident(segment.ident)?; segment.with_generic_args(|generic_args| { self.print_generic_args(generic_args, @@ -2448,8 +2445,8 @@ fn bin_op_to_assoc_op(op: hir::BinOpKind) -> AssocOp { } } -/// Expressions that syntactically contain an "exterior" struct literal i.e. not surrounded by any -/// parens or other delimiters, e.g. `X { y: 1 }`, `X { y: 1 }.method()`, `foo == X { y: 1 }` and +/// Expressions that syntactically contain an "exterior" struct literal i.e., not surrounded by any +/// parens or other delimiters, e.g., `X { y: 1 }`, `X { y: 1 }.method()`, `foo == X { y: 1 }` and /// `X { y: 1 } == foo` all do, but `(X { y: 1 }) == foo` does not. fn contains_exterior_struct_lit(value: &hir::Expr) -> bool { match value.node { diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs index 7c623a1874e..799c2df8a53 100644 --- a/src/librustc/ich/hcx.rs +++ b/src/librustc/ich/hcx.rs @@ -45,7 +45,7 @@ fn compute_ignored_attr_names() -> FxHashSet { /// This is the context state available during incr. comp. hashing. It contains /// enough information to transform DefIds and HirIds into stable DefPaths (i.e. /// a reference to the TyCtxt) and it holds a few caches for speeding up various -/// things (e.g. each DefId/DefPath is only hashed once). +/// things (e.g., each DefId/DefPath is only hashed once). #[derive(Clone)] pub struct StableHashingContext<'a> { sess: &'a Session, @@ -86,6 +86,7 @@ impl<'a> StableHashingContext<'a> { // The `krate` here is only used for mapping BodyIds to Bodies. // Don't use it for anything else or you'll run the risk of // leaking data out of the tracking system. + #[inline] pub fn new(sess: &'a Session, krate: &'a hir::Crate, definitions: &'a Definitions, diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs index d98bb82aaba..d82020f59a1 100644 --- a/src/librustc/ich/impls_mir.rs +++ b/src/librustc/ich/impls_mir.rs @@ -46,7 +46,8 @@ impl_stable_hash_for!(enum mir::BorrowKind { impl_stable_hash_for!(enum mir::UnsafetyViolationKind { General, - MinConstFn, + GeneralAndConstFn, + GatedConstFnCall, ExternStatic(lint_node_id), BorrowPacked(lint_node_id), }); @@ -193,52 +194,19 @@ for mir::TerminatorKind<'gcx> { impl_stable_hash_for!(struct mir::Statement<'tcx> { source_info, kind }); -impl<'a, 'gcx> HashStable> -for mir::StatementKind<'gcx> { - fn hash_stable(&self, - hcx: &mut StableHashingContext<'a>, - hasher: &mut StableHasher) { - mem::discriminant(self).hash_stable(hcx, hasher); - - match *self { - mir::StatementKind::Assign(ref place, ref rvalue) => { - place.hash_stable(hcx, hasher); - rvalue.hash_stable(hcx, hasher); - } - mir::StatementKind::FakeRead(ref cause, ref place) => { - cause.hash_stable(hcx, hasher); - place.hash_stable(hcx, hasher); - } - mir::StatementKind::SetDiscriminant { ref place, variant_index } => { - place.hash_stable(hcx, hasher); - variant_index.hash_stable(hcx, hasher); - } - mir::StatementKind::StorageLive(ref place) | - mir::StatementKind::StorageDead(ref place) => { - place.hash_stable(hcx, hasher); - } - mir::StatementKind::EscapeToRaw(ref place) => { - place.hash_stable(hcx, hasher); - } - mir::StatementKind::Retag { fn_entry, ref place } => { - fn_entry.hash_stable(hcx, hasher); - place.hash_stable(hcx, hasher); - } - mir::StatementKind::AscribeUserType(ref place, ref variance, ref c_ty) => { - place.hash_stable(hcx, hasher); - variance.hash_stable(hcx, hasher); - c_ty.hash_stable(hcx, hasher); - } - mir::StatementKind::Nop => {} - mir::StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => { - asm.hash_stable(hcx, hasher); - outputs.hash_stable(hcx, hasher); - inputs.hash_stable(hcx, hasher); - } - } - } -} +impl_stable_hash_for!(impl<'gcx> for enum mir::StatementKind<'gcx> [ mir::StatementKind ] { + Assign(place, rvalue), + FakeRead(cause, place), + SetDiscriminant { place, variant_index }, + StorageLive(place), + StorageDead(place), + Retag(retag_kind, place), + AscribeUserType(place, variance, c_ty), + Nop, + InlineAsm { asm, outputs, inputs }, +}); +impl_stable_hash_for!(enum mir::RetagKind { FnEntry, TwoPhase, Raw, Default }); impl_stable_hash_for!(enum mir::FakeReadCause { ForMatchGuard, ForMatchedPlace, ForLet }); impl<'a, 'gcx> HashStable> for mir::Place<'gcx> { @@ -503,6 +471,7 @@ impl_stable_hash_for!(struct mir::ClosureOutlivesRequirement<'tcx> { impl_stable_hash_for!(enum mir::ConstraintCategory { Return, + Yield, UseAsConst, UseAsStatic, TypeAnnotation, diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index b629fb820b3..3211937d3dd 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -134,14 +134,10 @@ impl_stable_hash_for!(struct ::syntax::attr::Stability { const_stability }); -impl<'a> HashStable> -for ::syntax::edition::Edition { - fn hash_stable(&self, - hcx: &mut StableHashingContext<'a>, - hasher: &mut StableHasher) { - mem::discriminant(self).hash_stable(hcx, hasher); - } -} +impl_stable_hash_for!(enum ::syntax::edition::Edition { + Edition2015, + Edition2018, +}); impl<'a> HashStable> for ::syntax::attr::StabilityLevel { @@ -269,10 +265,10 @@ for tokenstream::TokenTree { span.hash_stable(hcx, hasher); hash_token(token, hcx, hasher); } - tokenstream::TokenTree::Delimited(span, ref delimited) => { + tokenstream::TokenTree::Delimited(span, delim, ref tts) => { span.hash_stable(hcx, hasher); - std_hash::Hash::hash(&delimited.delim, hasher); - for sub_tt in delimited.stream().trees() { + std_hash::Hash::hash(&delim, hasher); + for sub_tt in tts.stream().trees() { sub_tt.hash_stable(hcx, hasher); } } @@ -417,13 +413,14 @@ impl_stable_hash_for!(enum ::syntax_pos::hygiene::CompilerDesugaringKind { impl_stable_hash_for!(enum ::syntax_pos::FileName { Real(pb), Macros(s), - QuoteExpansion, - Anon, - MacroExpansion, - ProcMacroSourceCode, - CliCrateAttr, - CfgSpec, - Custom(s) + QuoteExpansion(s), + Anon(s), + MacroExpansion(s), + ProcMacroSourceCode(s), + CliCrateAttr(s), + CfgSpec(s), + Custom(s), + DocTest(pb, line), }); impl<'a> HashStable> for SourceFile { diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index e6a7c20f793..56da6b719f4 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -338,7 +338,7 @@ impl_stable_hash_for!( ); impl_stable_hash_for!( - impl<'tcx, M> for enum mir::interpret::AllocType<'tcx, M> [ mir::interpret::AllocType ] { + impl<'tcx> for enum mir::interpret::AllocKind<'tcx> [ mir::interpret::AllocKind ] { Function(instance), Static(def_id), Memory(mem), diff --git a/src/librustc/ich/mod.rs b/src/librustc/ich/mod.rs index 9751c560acd..fc2f1ee6ff8 100644 --- a/src/librustc/ich/mod.rs +++ b/src/librustc/ich/mod.rs @@ -24,15 +24,15 @@ mod impls_misc; mod impls_ty; mod impls_syntax; -pub const ATTR_DIRTY: &'static str = "rustc_dirty"; -pub const ATTR_CLEAN: &'static str = "rustc_clean"; -pub const ATTR_IF_THIS_CHANGED: &'static str = "rustc_if_this_changed"; -pub const ATTR_THEN_THIS_WOULD_NEED: &'static str = "rustc_then_this_would_need"; -pub const ATTR_PARTITION_REUSED: &'static str = "rustc_partition_reused"; -pub const ATTR_PARTITION_CODEGENED: &'static str = "rustc_partition_codegened"; -pub const ATTR_EXPECTED_CGU_REUSE: &'static str = "rustc_expected_cgu_reuse"; +pub const ATTR_DIRTY: &str = "rustc_dirty"; +pub const ATTR_CLEAN: &str = "rustc_clean"; +pub const ATTR_IF_THIS_CHANGED: &str = "rustc_if_this_changed"; +pub const ATTR_THEN_THIS_WOULD_NEED: &str = "rustc_then_this_would_need"; +pub const ATTR_PARTITION_REUSED: &str = "rustc_partition_reused"; +pub const ATTR_PARTITION_CODEGENED: &str = "rustc_partition_codegened"; +pub const ATTR_EXPECTED_CGU_REUSE: &str = "rustc_expected_cgu_reuse"; -pub const IGNORED_ATTRIBUTES: &'static [&'static str] = &[ +pub const IGNORED_ATTRIBUTES: &[&str] = &[ "cfg", ATTR_IF_THIS_CHANGED, ATTR_THEN_THIS_WOULD_NEED, diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs index 8d2b1d74c55..2a8a340ab54 100644 --- a/src/librustc/infer/canonical/query_response.rs +++ b/src/librustc/infer/canonical/query_response.rs @@ -36,6 +36,7 @@ use traits::{Obligation, ObligationCause, PredicateObligation}; use ty::fold::TypeFoldable; use ty::subst::{Kind, UnpackedKind}; use ty::{self, BoundVar, Lift, Ty, TyCtxt}; +use util::captures::Captures; impl<'cx, 'gcx, 'tcx> InferCtxtBuilder<'cx, 'gcx, 'tcx> { /// The "main method" for a canonicalized trait query. Given the @@ -116,6 +117,31 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { Ok(Lrc::new(canonical_result)) } + /// A version of `make_canonicalized_query_response` that does + /// not pack in obligations, for contexts that want to drop + /// pending obligations instead of treating them as an ambiguity (e.g. + /// typeck "probing" contexts). + /// + /// If you DO want to keep track of pending obligations (which + /// include all region obligations, so this includes all cases + /// that care about regions) with this function, you have to + /// do it yourself, by e.g. having them be a part of the answer. + pub fn make_query_response_ignoring_pending_obligations( + &self, + inference_vars: CanonicalVarValues<'tcx>, + answer: T + ) -> Canonical<'gcx, QueryResponse<'gcx, >::Lifted>> + where + T: Debug + Lift<'gcx> + TypeFoldable<'tcx>, + { + self.canonicalize_response(&QueryResponse { + var_values: inference_vars, + region_constraints: vec![], + certainty: Certainty::Proven, // Ambiguities are OK! + value: answer, + }) + } + /// Helper for `make_canonicalized_query_response` that does /// everything up until the final canonicalization. fn make_query_response( @@ -527,32 +553,30 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { param_env: ty::ParamEnv<'tcx>, unsubstituted_region_constraints: &'a [QueryRegionConstraint<'tcx>], result_subst: &'a CanonicalVarValues<'tcx>, - ) -> impl Iterator> + 'a { - Box::new( - unsubstituted_region_constraints - .iter() - .map(move |constraint| { - let constraint = substitute_value(self.tcx, result_subst, constraint); - let &ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below + ) -> impl Iterator> + 'a + Captures<'gcx> { + unsubstituted_region_constraints + .iter() + .map(move |constraint| { + let constraint = substitute_value(self.tcx, result_subst, constraint); + let &ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below - Obligation::new( - cause.clone(), - param_env, - match k1.unpack() { - UnpackedKind::Lifetime(r1) => ty::Predicate::RegionOutlives( - ty::Binder::bind( - ty::OutlivesPredicate(r1, r2) - ) - ), - UnpackedKind::Type(t1) => ty::Predicate::TypeOutlives( - ty::Binder::bind( - ty::OutlivesPredicate(t1, r2) - ) - ), - } - ) - }) - ) as Box> + Obligation::new( + cause.clone(), + param_env, + match k1.unpack() { + UnpackedKind::Lifetime(r1) => ty::Predicate::RegionOutlives( + ty::Binder::bind( + ty::OutlivesPredicate(r1, r2) + ) + ), + UnpackedKind::Type(t1) => ty::Predicate::TypeOutlives( + ty::Binder::bind( + ty::OutlivesPredicate(t1, r2) + ) + ), + } + ) + }) } /// Given two sets of values for the same set of canonical variables, unify them. diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index f13210926a7..833da67d3f1 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -347,6 +347,10 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, ' self.infcx.tcx } + fn trait_object_mode(&self) -> relate::TraitObjectMode { + self.infcx.trait_object_mode() + } + fn tag(&self) -> &'static str { "Generalizer" } @@ -371,7 +375,7 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, ' if self.ambient_variance == ty::Variance::Invariant { // Avoid fetching the variance if we are in an invariant // context; no need, and it can induce dependency cycles - // (e.g. #41849). + // (e.g., #41849). relate::relate_substs(self, None, a_subst, b_subst) } else { let opt_variances = self.tcx().variances_of(item_def_id); diff --git a/src/librustc/infer/equate.rs b/src/librustc/infer/equate.rs index c7b5ddb8341..caa120fa267 100644 --- a/src/librustc/infer/equate.rs +++ b/src/librustc/infer/equate.rs @@ -39,6 +39,10 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() } + fn trait_object_mode(&self) -> relate::TraitObjectMode { + self.fields.infcx.trait_object_mode() + } + fn a_is_expected(&self) -> bool { self.a_is_expected } fn relate_item_substs(&mut self, @@ -47,9 +51,9 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> b_subst: &'tcx Substs<'tcx>) -> RelateResult<'tcx, &'tcx Substs<'tcx>> { - // NB: Once we are equating types, we don't care about + // N.B., once we are equating types, we don't care about // variance, so don't try to lookup the variance here. This - // also avoids some cycles (e.g. #41849) since looking up + // also avoids some cycles (e.g., #41849) since looking up // variance requires computing types which can require // performing trait matching (which then performs equality // unification). diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 59a490f4a01..d213a5c5618 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -97,7 +97,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { ) }; let span = scope.span(self, region_scope_tree); - let tag = match self.hir.find(scope.node_id(self, region_scope_tree)) { + let tag = match self.hir().find(scope.node_id(self, region_scope_tree)) { Some(Node::Block(_)) => "block", Some(Node::Expr(expr)) => match expr.node { hir::ExprKind::Call(..) => "call", @@ -190,8 +190,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let cm = self.sess.source_map(); let scope = region.free_region_binding_scope(self); - let node = self.hir.as_local_node_id(scope).unwrap_or(DUMMY_NODE_ID); - let tag = match self.hir.find(node) { + let node = self.hir().as_local_node_id(scope).unwrap_or(DUMMY_NODE_ID); + let tag = match self.hir().find(node) { Some(Node::Block(_)) | Some(Node::Expr(_)) => "body", Some(Node::Item(it)) => Self::item_scope_tag(&it), Some(Node::TraitItem(it)) => Self::trait_item_scope_tag(&it), @@ -200,8 +200,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { }; let (prefix, span) = match *region { ty::ReEarlyBound(ref br) => { - let mut sp = cm.def_span(self.hir.span(node)); - if let Some(param) = self.hir + let mut sp = cm.def_span(self.hir().span(node)); + if let Some(param) = self.hir() .get_generics(scope) .and_then(|generics| generics.get_named(&br.name)) { @@ -213,8 +213,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { bound_region: ty::BoundRegion::BrNamed(_, ref name), .. }) => { - let mut sp = cm.def_span(self.hir.span(node)); - if let Some(param) = self.hir + let mut sp = cm.def_span(self.hir().span(node)); + if let Some(param) = self.hir() .get_generics(scope) .and_then(|generics| generics.get_named(&name)) { @@ -225,15 +225,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { ty::ReFree(ref fr) => match fr.bound_region { ty::BrAnon(idx) => ( format!("the anonymous lifetime #{} defined on", idx + 1), - self.hir.span(node), + self.hir().span(node), ), ty::BrFresh(_) => ( "an anonymous lifetime defined on".to_owned(), - self.hir.span(node), + self.hir().span(node), ), _ => ( format!("the lifetime {} as defined on", fr.bound_region), - cm.def_span(self.hir.span(node)), + cm.def_span(self.hir().span(node)), ), }, _ => bug!(), @@ -1083,7 +1083,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // the expected type argument. if !param.is_self() { let type_param = generics.type_param(param, self.tcx); - let hir = &self.tcx.hir; + let hir = &self.tcx.hir(); hir.as_local_node_id(type_param.def_id).map(|id| { // Get the `hir::Param` to verify whether it already has any bounds. // We do this to avoid suggesting code that ends up as `T: 'a'b`, @@ -1095,7 +1095,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let sp = hir.span(id); // `sp` only covers `T`, change it so that it covers // `T:` when appropriate - let sp = if has_bounds { + let is_impl_trait = bound_kind.to_string().starts_with("impl "); + let sp = if has_bounds && !is_impl_trait { sp.to(self.tcx .sess .source_map() @@ -1103,7 +1104,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } else { sp }; - (sp, has_bounds) + (sp, has_bounds, is_impl_trait) }) } else { None @@ -1136,25 +1137,33 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { fn binding_suggestion<'tcx, S: fmt::Display>( err: &mut DiagnosticBuilder<'tcx>, - type_param_span: Option<(Span, bool)>, + type_param_span: Option<(Span, bool, bool)>, bound_kind: GenericKind<'tcx>, sub: S, ) { - let consider = &format!( - "consider adding an explicit lifetime bound `{}: {}`...", - bound_kind, sub + let consider = format!( + "consider adding an explicit lifetime bound {}", + if type_param_span.map(|(_, _, is_impl_trait)| is_impl_trait).unwrap_or(false) { + format!(" `{}` to `{}`...", sub, bound_kind) + } else { + format!("`{}: {}`...", bound_kind, sub) + }, ); - if let Some((sp, has_lifetimes)) = type_param_span { - let tail = if has_lifetimes { " + " } else { "" }; - let suggestion = format!("{}: {}{}", bound_kind, sub, tail); + if let Some((sp, has_lifetimes, is_impl_trait)) = type_param_span { + let suggestion = if is_impl_trait { + format!("{} + {}", bound_kind, sub) + } else { + let tail = if has_lifetimes { " + " } else { "" }; + format!("{}: {}{}", bound_kind, sub, tail) + }; err.span_suggestion_short_with_applicability( sp, - consider, + &consider, suggestion, Applicability::MaybeIncorrect, // Issue #41966 ); } else { - err.help(consider); + err.help(&consider); } } @@ -1315,8 +1324,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { format!(" for lifetime parameter `{}` in coherence check", name) } infer::UpvarRegion(ref upvar_id, _) => { - let var_node_id = self.tcx.hir.hir_to_node_id(upvar_id.var_path.hir_id); - let var_name = self.tcx.hir.name(var_node_id); + let var_node_id = self.tcx.hir().hir_to_node_id(upvar_id.var_path.hir_id); + let var_name = self.tcx.hir().name(var_node_id); format!(" for capture of `{}` by closure", var_name) } infer::NLL(..) => bug!("NLL variable found in lexical phase"), diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs index efb316243fa..4064df0a09d 100644 --- a/src/librustc/infer/error_reporting/need_type_info.rs +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -109,13 +109,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let mut local_visitor = FindLocalByTypeVisitor { infcx: &self, target_ty: &ty, - hir_map: &self.tcx.hir, + hir_map: &self.tcx.hir(), found_local_pattern: None, found_arg_pattern: None, }; if let Some(body_id) = body_id { - let expr = self.tcx.hir.expect_expr(body_id.node_id); + let expr = self.tcx.hir().expect_expr(body_id.node_id); local_visitor.visit_expr(expr); } 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 10a2d179dd5..df0dcbed30a 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 @@ -30,7 +30,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { /// { x.push(y); } /// ``` /// The function returns the nested type corresponding to the anonymous region - /// for e.g. `&u8` and Vec<`&u8`. + /// for e.g., `&u8` and Vec<`&u8`. pub(super) fn find_anon_type( &self, region: Region<'tcx>, @@ -38,8 +38,8 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { ) -> Option<(&hir::Ty, &hir::FnDecl)> { 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) { + if let Some(node_id) = self.tcx.hir().as_local_node_id(def_id) { + let fndecl = match self.tcx.hir().get(node_id) { Node::Item(&hir::Item { node: hir::ItemKind::Fn(ref fndecl, ..), .. @@ -97,14 +97,14 @@ struct FindNestedTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { // associated with the anonymous region we are looking for. bound_region: ty::BoundRegion, // The type where the anonymous lifetime appears - // for e.g. Vec<`&u8`> and <`&u8`> + // for e.g., Vec<`&u8`> and <`&u8`> found_type: Option<&'gcx hir::Ty>, current_index: ty::DebruijnIndex, } impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindNestedTypeVisitor<'a, 'gcx, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir) + NestedVisitorMap::OnlyBodies(&self.tcx.hir()) } fn visit_ty(&mut self, arg: &'gcx hir::Ty) { @@ -124,7 +124,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindNestedTypeVisitor<'a, 'gcx, 'tcx> { hir::TyKind::Rptr(ref lifetime, _) => { // the lifetime of the TyRptr - let hir_id = self.tcx.hir.node_to_hir_id(lifetime.id); + let hir_id = self.tcx.hir().node_to_hir_id(lifetime.id); match (self.tcx.named_region(hir_id), self.bound_region) { // Find the index of the anonymous region that was part of the // error. We will then search the function parameters for a bound @@ -150,7 +150,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindNestedTypeVisitor<'a, 'gcx, 'tcx> { // region at the right depth with the same index (Some(rl::Region::EarlyBound(_, id, _)), ty::BrNamed(def_id, _)) => { debug!( - "EarlyBound self.infcx.tcx.hir.local_def_id(id)={:?} \ + "EarlyBound self.infcx.tcx.hir().local_def_id(id)={:?} \ def_id={:?}", id, def_id @@ -172,7 +172,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindNestedTypeVisitor<'a, 'gcx, 'tcx> { "FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}", debruijn_index ); - debug!("self.infcx.tcx.hir.local_def_id(id)={:?}", id); + debug!("self.infcx.tcx.hir().local_def_id(id)={:?}", id); debug!("def_id={:?}", def_id); if debruijn_index == self.current_index && id == def_id { self.found_type = Some(arg); @@ -227,11 +227,11 @@ struct TyPathVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { impl<'a, 'gcx, 'tcx> Visitor<'gcx> for TyPathVisitor<'a, 'gcx, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir) + NestedVisitorMap::OnlyBodies(&self.tcx.hir()) } fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) { - let hir_id = self.tcx.hir.node_to_hir_id(lifetime.id); + let hir_id = self.tcx.hir().node_to_hir_id(lifetime.id); match (self.tcx.named_region(hir_id), self.bound_region) { // the lifetime of the TyPath! (Some(rl::Region::LateBoundAnon(debruijn_index, anon_index)), ty::BrAnon(br_index)) => { @@ -243,7 +243,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for TyPathVisitor<'a, 'gcx, 'tcx> { (Some(rl::Region::EarlyBound(_, id, _)), ty::BrNamed(def_id, _)) => { debug!( - "EarlyBound self.infcx.tcx.hir.local_def_id(id)={:?} \ + "EarlyBound self.infcx.tcx.hir().local_def_id(id)={:?} \ def_id={:?}", id, def_id diff --git a/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs b/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs index 7a92b3084ba..4c3fbc79646 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs @@ -56,7 +56,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { // closure, provide a specific message pointing this out. if let (&SubregionOrigin::BindingTypeIsNotValidAtDecl(ref external_span), &RegionKind::ReFree(ref free_region)) = (&sub_origin, sup_region) { - let hir = &self.tcx.hir; + let hir = &self.tcx.hir(); if let Some(node_id) = hir.as_local_node_id(free_region.scope) { if let Node::Expr(Expr { node: Closure(_, _, _, closure_span, None), 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 013c02f75b8..e5c2c75a3f3 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/util.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/util.rs @@ -60,7 +60,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { _ => return None, // not a free region }; - let hir = &self.tcx.hir; + let hir = &self.tcx.hir(); if let Some(node_id) = hir.as_local_node_id(id) { if let Some(body_id) = hir.maybe_body_owned_by(node_id) { let body = hir.body(body_id); diff --git a/src/librustc/infer/error_reporting/note.rs b/src/librustc/infer/error_reporting/note.rs index a539c321af3..f5ac39ae838 100644 --- a/src/librustc/infer/error_reporting/note.rs +++ b/src/librustc/infer/error_reporting/note.rs @@ -41,8 +41,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { "...so that reference does not outlive borrowed content"); } infer::ReborrowUpvar(span, ref upvar_id) => { - let var_node_id = self.tcx.hir.hir_to_node_id(upvar_id.var_path.hir_id); - let var_name = self.tcx.hir.name(var_node_id); + let var_node_id = self.tcx.hir().hir_to_node_id(upvar_id.var_path.hir_id); + let var_name = self.tcx.hir().name(var_node_id); err.span_note(span, &format!("...so that closure can access `{}`", var_name)); } @@ -61,7 +61,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { err.span_note(span, &format!("...so that captured variable `{}` does not outlive the \ enclosing closure", - self.tcx.hir.name(id))); + self.tcx.hir().name(id))); } infer::IndexSlice(span) => { err.span_note(span, "...so that slice is not indexed outside the lifetime"); @@ -174,8 +174,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { err } infer::ReborrowUpvar(span, ref upvar_id) => { - let var_node_id = self.tcx.hir.hir_to_node_id(upvar_id.var_path.hir_id); - let var_name = self.tcx.hir.name(var_node_id); + let var_node_id = self.tcx.hir().hir_to_node_id(upvar_id.var_path.hir_id); + let var_name = self.tcx.hir().name(var_node_id); let mut err = struct_span_err!(self.tcx.sess, span, E0313, @@ -232,7 +232,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { E0474, "captured variable `{}` does not outlive the \ enclosing closure", - self.tcx.hir.name(id)); + self.tcx.hir().name(id)); self.tcx.note_and_explain_region(region_scope_tree, &mut err, "captured variable is valid for ", sup, ""); self.tcx.note_and_explain_region(region_scope_tree, &mut err, diff --git a/src/librustc/infer/glb.rs b/src/librustc/infer/glb.rs index 8968c5949b6..ba21ebb49eb 100644 --- a/src/librustc/infer/glb.rs +++ b/src/librustc/infer/glb.rs @@ -15,7 +15,7 @@ use super::Subtype; use traits::ObligationCause; use ty::{self, Ty, TyCtxt}; -use ty::relate::{Relate, RelateResult, TypeRelation}; +use ty::relate::{self, Relate, RelateResult, TypeRelation}; /// "Greatest lower bound" (common subtype) pub struct Glb<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> { @@ -36,6 +36,10 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> { fn tag(&self) -> &'static str { "Glb" } + fn trait_object_mode(&self) -> relate::TraitObjectMode { + self.fields.infcx.trait_object_mode() + } + fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() } fn a_is_expected(&self) -> bool { self.a_is_expected } diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index cf91b858076..c8cd11c8198 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -542,7 +542,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// Pops the placeholder regions found in `placeholder_map` from the region /// inference context. Whenever you create placeholder regions via /// `replace_bound_vars_with_placeholders`, they must be popped before you - /// commit the enclosing snapshot (if you do not commit, e.g. within a + /// commit the enclosing snapshot (if you do not commit, e.g., within a /// probe or as a result of an error, then this is not necessary, as /// popping happens as part of the rollback). /// diff --git a/src/librustc/infer/lexical_region_resolve/graphviz.rs b/src/librustc/infer/lexical_region_resolve/graphviz.rs index a210d63f129..512e57d810a 100644 --- a/src/librustc/infer/lexical_region_resolve/graphviz.rs +++ b/src/librustc/infer/lexical_region_resolve/graphviz.rs @@ -31,9 +31,8 @@ use std::borrow::Cow; use std::collections::hash_map::Entry::Vacant; use std::collections::btree_map::BTreeMap; use std::env; -use std::fs::File; +use std::fs; use std::io; -use std::io::prelude::*; use std::sync::atomic::{AtomicBool, Ordering}; fn print_help_message() { @@ -268,5 +267,5 @@ fn dump_region_data_to<'a, 'gcx, 'tcx>(region_rels: &RegionRelations<'a, 'gcx, ' debug!("dump_region_data calling render"); let mut v = Vec::new(); dot::render(&g, &mut v).unwrap(); - File::create(path).and_then(|mut f| f.write_all(&v)) + fs::write(path, &v) } diff --git a/src/librustc/infer/lub.rs b/src/librustc/infer/lub.rs index 8875b4169dd..80fad447b46 100644 --- a/src/librustc/infer/lub.rs +++ b/src/librustc/infer/lub.rs @@ -15,7 +15,7 @@ use super::Subtype; use traits::ObligationCause; use ty::{self, Ty, TyCtxt}; -use ty::relate::{Relate, RelateResult, TypeRelation}; +use ty::relate::{self, Relate, RelateResult, TypeRelation}; /// "Least upper bound" (common supertype) pub struct Lub<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> { @@ -36,6 +36,10 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> { fn tag(&self) -> &'static str { "Lub" } + fn trait_object_mode(&self) -> relate::TraitObjectMode { + self.fields.infcx.trait_object_mode() + } + fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() } fn a_is_expected(&self) -> bool { self.a_is_expected } diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index d8beae45b0a..7ce59b1d9d7 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -35,9 +35,9 @@ use syntax_pos::{self, Span}; use traits::{self, ObligationCause, PredicateObligations, TraitEngine}; use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric}; use ty::fold::TypeFoldable; -use ty::relate::RelateResult; +use ty::relate::{RelateResult, TraitObjectMode}; use ty::subst::{Kind, Substs}; -use ty::{self, GenericParamDefKind, Ty, TyCtxt}; +use ty::{self, GenericParamDefKind, Ty, TyCtxt, CtxtInterners}; use ty::{FloatVid, IntVid, TyVid}; use util::nodemap::FxHashMap; @@ -182,6 +182,9 @@ pub struct InferCtxt<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { // This flag is true while there is an active snapshot. in_snapshot: Cell, + // The TraitObjectMode used here, + trait_object_mode: TraitObjectMode, + // A set of constraints that regionck must validate. Each // constraint has the form `T:'a`, meaning "some type `T` must // outlive the lifetime 'a". These constraints derive from @@ -219,7 +222,7 @@ pub struct InferCtxt<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { /// `UniverseIndex::root()` but grows from there as we enter /// universal quantifiers. /// - /// NB: At present, we exclude the universal quantifiers on the + /// N.B., at present, we exclude the universal quantifiers on the /// item we are type-checking, and just consider those names as /// part of the root universe. So this would only get incremented /// when we enter into a higher-ranked (`for<..>`) type or trait @@ -471,7 +474,9 @@ impl fmt::Display for FixupError { pub struct InferCtxtBuilder<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { global_tcx: TyCtxt<'a, 'gcx, 'gcx>, arena: SyncDroplessArena, + interners: Option>, fresh_tables: Option>>, + trait_object_mode: TraitObjectMode, } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> { @@ -479,7 +484,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> { InferCtxtBuilder { global_tcx: self, arena: SyncDroplessArena::default(), + interners: None, fresh_tables: None, + trait_object_mode: TraitObjectMode::NoSquash, } } } @@ -492,6 +499,12 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> { self } + pub fn with_trait_object_mode(mut self, mode: TraitObjectMode) -> Self { + debug!("with_trait_object_mode: setting mode to {:?}", mode); + self.trait_object_mode = mode; + self + } + /// Given a canonical value `C` as a starting point, create an /// inference context that contains each of the bound values /// within instantiated as a fresh variable. The `f` closure is @@ -518,14 +531,19 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> { pub fn enter(&'tcx mut self, f: impl for<'b> FnOnce(InferCtxt<'b, 'gcx, 'tcx>) -> R) -> R { let InferCtxtBuilder { global_tcx, + trait_object_mode, ref arena, + ref mut interners, ref fresh_tables, } = *self; let in_progress_tables = fresh_tables.as_ref(); - global_tcx.enter_local(arena, |tcx| { + // Check that we haven't entered before + assert!(interners.is_none()); + global_tcx.enter_local(arena, interners, |tcx| { f(InferCtxt { tcx, in_progress_tables, + trait_object_mode, projection_cache: Default::default(), type_variables: RefCell::new(type_variable::TypeVariableTable::new()), int_unification_table: RefCell::new(ut::UnificationTable::new()), @@ -607,6 +625,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.in_snapshot.get() } + pub fn trait_object_mode(&self) -> TraitObjectMode { + self.trait_object_mode + } + pub fn freshen>(&self, t: T) -> T { t.fold_with(&mut self.freshener()) } @@ -732,7 +754,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { region_obligations_snapshot: self.region_obligations.borrow().len(), universe: self.universe(), was_in_snapshot: in_snapshot, - // Borrow tables "in progress" (i.e. during typeck) + // Borrow tables "in progress" (i.e., during typeck) // to ban writes from within a snapshot to them. _in_progress_tables: self.in_progress_tables.map(|tables| tables.borrow()), } @@ -1047,7 +1069,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // type parameter definition. The substitutions are // for actual parameters that may be referred to by // the default of this type parameter, if it exists. - // E.g. `struct Foo(...);` when + // e.g., `struct Foo(...);` when // used in a path such as `Foo::::new()` will // use an inference variable for `C` with `[T, U]` // as the substitutions for the default, `(T, U)`. @@ -1253,6 +1275,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.inlined_shallow_resolve(typ) } + pub fn root_var(&self, var: ty::TyVid) -> ty::TyVid { + self.type_variables.borrow_mut().root_var(var) + } + pub fn resolve_type_vars_if_possible(&self, value: &T) -> T where T: TypeFoldable<'tcx>, @@ -1261,7 +1287,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { * Where possible, replaces type/int/float variables in * `value` with their final value. Note that region variables * are unaffected. If a type variable has not been unified, it - * is left as is. This is an idempotent operation that does + * is left as is. This is an idempotent operation that does * not affect inference state in any way and so you can do it * at will. */ @@ -1298,7 +1324,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /*! * Attempts to resolve all type/region variables in * `value`. Region inference must have been run already (e.g., - * by calling `resolve_regions_and_report_errors`). If some + * by calling `resolve_regions_and_report_errors`). If some * variable was never unified, an `Err` results. * * This method is idempotent, but it not typically not invoked @@ -1331,7 +1357,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let actual_ty = self.resolve_type_vars_if_possible(&actual_ty); debug!("type_error_struct_with_diag({:?}, {:?})", sp, actual_ty); - // Don't report an error if actual type is Error. + // Don't report an error if actual type is `Error`. if actual_ty.references_error() { return self.tcx.sess.diagnostic().struct_dummy(); } diff --git a/src/librustc/infer/nll_relate/mod.rs b/src/librustc/infer/nll_relate/mod.rs index 972ba16f7e2..0ce0eb9a1ab 100644 --- a/src/librustc/infer/nll_relate/mod.rs +++ b/src/librustc/infer/nll_relate/mod.rs @@ -15,7 +15,7 @@ //! //! Here are the key differences: //! -//! - This code may choose to bypass some checks (e.g. the occurs check) +//! - This code may choose to bypass some checks (e.g., the occurs check) //! in the case where we know that there are no unbound type inference //! variables. This is the case for NLL, because at NLL time types are fully //! inferred up-to regions. @@ -97,7 +97,7 @@ pub trait TypeRelatingDelegate<'tcx> { /// region that is instantiated existentially. This creates an /// inference variable, typically. /// - /// So e.g. if you have `for<'a> fn(..) <: for<'b> fn(..)`, then + /// So e.g., if you have `for<'a> fn(..) <: for<'b> fn(..)`, then /// we will invoke this method to instantiate `'a` with an /// inference variable (though `'b` would be instantiated first, /// as a placeholder). @@ -107,7 +107,7 @@ pub trait TypeRelatingDelegate<'tcx> { /// higher-ranked region that is instantiated universally. /// This creates a new region placeholder, typically. /// - /// So e.g. if you have `for<'a> fn(..) <: for<'b> fn(..)`, then + /// So e.g., if you have `for<'a> fn(..) <: for<'b> fn(..)`, then /// we will invoke this method to instantiate `'b` with a /// placeholder region. fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx>; @@ -382,6 +382,13 @@ where self.infcx.tcx } + fn trait_object_mode(&self) -> relate::TraitObjectMode { + // squashing should only be done in coherence, not NLL + assert_eq!(self.infcx.trait_object_mode(), + relate::TraitObjectMode::NoSquash); + relate::TraitObjectMode::NoSquash + } + fn tag(&self) -> &'static str { "nll::subtype" } @@ -696,6 +703,13 @@ where self.infcx.tcx } + fn trait_object_mode(&self) -> relate::TraitObjectMode { + // squashing should only be done in coherence, not NLL + assert_eq!(self.infcx.trait_object_mode(), + relate::TraitObjectMode::NoSquash); + relate::TraitObjectMode::NoSquash + } + fn tag(&self) -> &'static str { "nll::generalizer" } diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index fda9817cc88..44c5fe5acaa 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -691,13 +691,13 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> { // let x = || foo(); // returns the Opaque assoc with `foo` // } // ``` - if let Some(opaque_node_id) = tcx.hir.as_local_node_id(def_id) { + if let Some(opaque_node_id) = tcx.hir().as_local_node_id(def_id) { let parent_def_id = self.parent_def_id; let def_scope_default = || { - let opaque_parent_node_id = tcx.hir.get_parent(opaque_node_id); - parent_def_id == tcx.hir.local_def_id(opaque_parent_node_id) + let opaque_parent_node_id = tcx.hir().get_parent(opaque_node_id); + parent_def_id == tcx.hir().local_def_id(opaque_parent_node_id) }; - let in_definition_scope = match tcx.hir.find(opaque_node_id) { + let in_definition_scope = match tcx.hir().find(opaque_node_id) { Some(Node::Item(item)) => match item.node { // impl trait hir::ItemKind::Existential(hir::ExistTy { @@ -725,7 +725,7 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> { }, _ => bug!( "expected (impl) item, found {}", - tcx.hir.node_to_string(opaque_node_id), + tcx.hir().node_to_string(opaque_node_id), ), }; if in_definition_scope { @@ -761,7 +761,7 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> { ); // Use the same type variable if the exact same Opaque appears more - // than once in the return type (e.g. if it's passed to a type alias). + // than once in the return type (e.g., if it's passed to a type alias). if let Some(opaque_defn) = self.opaque_types.get(&def_id) { return opaque_defn.concrete_ty; } @@ -783,7 +783,7 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> { ); // make sure that we are in fact defining the *entire* type - // e.g. `existential type Foo: Bar;` needs to be + // e.g., `existential type Foo: Bar;` needs to be // defined by a function like `fn foo() -> Foo`. debug!( "instantiate_opaque_types: param_env: {:#?}", @@ -848,16 +848,16 @@ pub fn may_define_existential_type( opaque_node_id: ast::NodeId, ) -> bool { let mut node_id = tcx - .hir + .hir() .as_local_node_id(def_id) .unwrap(); // named existential types can be defined by any siblings or // children of siblings - let mod_id = tcx.hir.get_parent(opaque_node_id); + let mod_id = tcx.hir().get_parent(opaque_node_id); // so we walk up the node tree until we hit the root or the parent // of the opaque type while node_id != mod_id && node_id != ast::CRATE_NODE_ID { - node_id = tcx.hir.get_parent(node_id); + node_id = tcx.hir().get_parent(node_id); } // syntactically we are allowed to define the concrete type node_id == mod_id diff --git a/src/librustc/infer/outlives/obligations.rs b/src/librustc/infer/outlives/obligations.rs index 502a5828f3e..7b21a6992a7 100644 --- a/src/librustc/infer/outlives/obligations.rs +++ b/src/librustc/infer/outlives/obligations.rs @@ -408,7 +408,7 @@ where // Remove outlives bounds that we get from the environment but // which are also deducable from the trait. This arises (cc - // #55756) in cases where you have e.g. `>::Item: + // #55756) in cases where you have e.g., `>::Item: // 'a` in the environment but `trait Foo<'b> { type Item: 'b // }` in the trait definition. approx_env_bounds.retain(|bound| { diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index af1b6964b81..9cac73dfab0 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -60,7 +60,7 @@ pub struct RegionConstraintCollector<'tcx> { /// which can never be rolled back. undo_log: Vec>, - /// The number of open snapshots, i.e. those that haven't been committed or + /// The number of open snapshots, i.e., those that haven't been committed or /// rolled back. num_open_snapshots: usize, @@ -607,7 +607,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> { // never overwrite an existing (constraint, origin) - only insert one if it isn't // present in the map yet. This prevents origins from outside the snapshot being - // replaced with "less informative" origins e.g. during calls to `can_eq` + // replaced with "less informative" origins e.g., during calls to `can_eq` let in_snapshot = self.in_snapshot(); let undo_log = &mut self.undo_log; self.data.constraints.entry(constraint).or_insert_with(|| { diff --git a/src/librustc/infer/sub.rs b/src/librustc/infer/sub.rs index 3b0f9a5e545..ef2ef3f8a86 100644 --- a/src/librustc/infer/sub.rs +++ b/src/librustc/infer/sub.rs @@ -15,7 +15,7 @@ use traits::Obligation; use ty::{self, Ty, TyCtxt}; use ty::TyVar; use ty::fold::TypeFoldable; -use ty::relate::{Cause, Relate, RelateResult, TypeRelation}; +use ty::relate::{self, Cause, Relate, RelateResult, TypeRelation}; use std::mem; /// Ensures `a` is made a subtype of `b`. Returns `a` on success. @@ -43,6 +43,10 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> for Sub<'combine, 'infcx, 'gcx, 'tcx> { fn tag(&self) -> &'static str { "Sub" } + fn trait_object_mode(&self) -> relate::TraitObjectMode { + self.fields.infcx.trait_object_mode() + } + fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.infcx.tcx } fn a_is_expected(&self) -> bool { self.a_is_expected } diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs index 5624961ea6e..b7aac23b955 100644 --- a/src/librustc/infer/type_variable.rs +++ b/src/librustc/infer/type_variable.rs @@ -175,7 +175,7 @@ impl<'tcx> TypeVariableTable<'tcx> { /// Creates a new type variable. /// /// - `diverging`: indicates if this is a "diverging" type - /// variable, e.g. one created as the type of a `return` + /// variable, e.g., one created as the type of a `return` /// expression. The code in this module doesn't care if a /// variable is diverging, but the main Rust type-checker will /// sometimes "unify" such variables with the `!` or `()` types. diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index ddb0c5bf22a..b76fb0ed08c 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -60,10 +60,12 @@ #![feature(slice_sort_by_cached_key)] #![feature(specialization)] #![feature(unboxed_closures)] +#![feature(thread_local)] #![feature(trace_macros)] #![feature(trusted_len)] #![feature(vec_remove_item)] #![feature(step_trait)] +#![feature(stmt_expr_attributes)] #![feature(integer_atomics)] #![feature(test)] #![feature(in_band_lifetimes)] @@ -119,7 +121,7 @@ extern crate test; #[macro_use] mod macros; -// NB: This module needs to be declared first so diagnostics are +// N.B., this module needs to be declared first so diagnostics are // registered before they are used. pub mod diagnostics; diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 22f2023eefb..0cde9ebf654 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -174,7 +174,7 @@ declare_lint! { declare_lint! { pub LEGACY_DIRECTORY_OWNERSHIP, Deny, - "non-inline, non-`#[path]` modules (e.g. `mod foo;`) were erroneously allowed in some files \ + "non-inline, non-`#[path]` modules (e.g., `mod foo;`) were erroneously allowed in some files \ not named `mod.rs`" } @@ -208,6 +208,12 @@ declare_lint! { "potentially-conflicting impls were erroneously allowed" } +declare_lint! { + pub ORDER_DEPENDENT_TRAIT_OBJECTS, + Deny, + "trait-object types were treated as different depending on marker-trait order" +} + declare_lint! { pub BAD_REPR, Warn, @@ -309,19 +315,19 @@ declare_lint! { declare_lint! { pub INTRA_DOC_LINK_RESOLUTION_FAILURE, Warn, - "warn about documentation intra links resolution failure" + "failures in resolving intra-doc link targets" } declare_lint! { pub MISSING_DOC_CODE_EXAMPLES, Allow, - "warn about missing code example in an item's documentation" + "detects publicly-exported items without code samples in their documentation" } declare_lint! { pub PRIVATE_DOC_TESTS, Allow, - "warn about doc test in private item" + "detects code samples in docs of private items not documented by rustdoc" } declare_lint! { @@ -365,8 +371,15 @@ pub mod parser { } } +declare_lint! { + pub DEPRECATED_IN_FUTURE, + Allow, + "detects use of items that will be deprecated in a future version", + report_in_external_macro: true +} + /// Does nothing as a lint pass, but registers some `Lint`s -/// which are used by other parts of the compiler. +/// that are used by other parts of the compiler. #[derive(Copy, Clone)] pub struct HardwiredLints; @@ -405,6 +418,7 @@ impl LintPass for HardwiredLints { PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES, LATE_BOUND_LIFETIME_ARGUMENTS, INCOHERENT_FUNDAMENTAL_IMPLS, + ORDER_DEPENDENT_TRAIT_OBJECTS, DEPRECATED, UNUSED_UNSAFE, UNUSED_MUT, @@ -427,6 +441,7 @@ impl LintPass for HardwiredLints { MACRO_USE_EXTERN_CRATE, MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS, parser::QUESTION_MARK_MACRO_SEP, + DEPRECATED_IN_FUTURE, ) } } @@ -463,7 +478,7 @@ impl BuiltinLintDiagnostics { Ok(ref s) => { // FIXME(Manishearth) ideally the emitting code // can tell us whether or not this is global - let opt_colon = if s.trim_left().starts_with("::") { + let opt_colon = if s.trim_start().starts_with("::") { "" } else { "::" diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 469d77403a3..131dedb9888 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -42,11 +42,12 @@ use util::nodemap::FxHashMap; use std::default::Default as StdDefault; use syntax::ast; use syntax::edition; -use syntax_pos::{MultiSpan, Span, symbol::LocalInternedString}; +use syntax_pos::{MultiSpan, Span, symbol::{LocalInternedString, Symbol}}; use errors::DiagnosticBuilder; use hir; use hir::def_id::LOCAL_CRATE; use hir::intravisit as hir_visit; +use syntax::util::lev_distance::find_best_match_for_name; use syntax::visit as ast_visit; /// Information about the registered lints. @@ -139,8 +140,8 @@ struct LintGroup { pub enum CheckLintNameResult<'a> { Ok(&'a [LintId]), - /// Lint doesn't exist - NoLint, + /// Lint doesn't exist. Potentially contains a suggestion for a correct lint name. + NoLint(Option), /// The lint is either renamed or removed. This is the warning /// message, and an optional new name (`None` if removed). Warning(String, Option), @@ -359,8 +360,14 @@ impl LintStore { CheckLintNameResult::Warning(ref msg, _) => { Some(sess.struct_warn(msg)) }, - CheckLintNameResult::NoLint => { - Some(struct_err!(sess, E0602, "unknown lint: `{}`", lint_name)) + CheckLintNameResult::NoLint(suggestion) => { + let mut err = struct_err!(sess, E0602, "unknown lint: `{}`", lint_name); + + if let Some(suggestion) = suggestion { + err.help(&format!("did you mean: `{}`", suggestion)); + } + + Some(err) } CheckLintNameResult::Tool(result) => match result { Err((Some(_), new_name)) => Some(sess.struct_warn(&format!( @@ -464,7 +471,16 @@ impl LintStore { match self.by_name.get(&complete_name) { None => match self.lint_groups.get(&*complete_name) { // Now we are sure, that this lint exists nowhere - None => CheckLintNameResult::NoLint, + None => { + let symbols = self.by_name.keys() + .map(|name| Symbol::intern(&name)) + .collect::>(); + + let suggestion = + find_best_match_for_name(symbols.iter(), &lint_name.to_lowercase(), None); + + CheckLintNameResult::NoLint(suggestion) + } Some(LintGroup { lint_ids, depr, .. }) => { // Reaching this would be weird, but let's cover this case anyway if let Some(LintAlias { name, silent }) = depr { @@ -484,7 +500,7 @@ impl LintStore { Some(&Id(ref id)) => { CheckLintNameResult::Tool(Err((Some(slice::from_ref(id)), complete_name))) } - _ => CheckLintNameResult::NoLint, + _ => CheckLintNameResult::NoLint(None), } } } @@ -774,7 +790,7 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> { where F: FnOnce(&mut Self), { let old_param_env = self.param_env; - self.param_env = self.tcx.param_env(self.tcx.hir.local_def_id(id)); + self.param_env = self.tcx.param_env(self.tcx.hir().local_def_id(id)); f(self); self.param_env = old_param_env; } @@ -797,13 +813,13 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { /// items in the context of the outer item, so enable /// deep-walking. fn nested_visit_map<'this>(&'this mut self) -> hir_visit::NestedVisitorMap<'this, 'tcx> { - hir_visit::NestedVisitorMap::All(&self.tcx.hir) + hir_visit::NestedVisitorMap::All(&self.tcx.hir()) } fn visit_nested_body(&mut self, body: hir::BodyId) { let old_tables = self.tables; self.tables = self.tcx.body_tables(body); - let body = self.tcx.hir.body(body); + let body = self.tcx.hir().body(body); self.visit_body(body); self.tables = old_tables; } @@ -866,7 +882,7 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { // in order for `check_fn` to be able to use them. let old_tables = self.tables; self.tables = self.tcx.body_tables(body_id); - let body = self.tcx.hir.body(body_id); + let body = self.tcx.hir().body(body_id); run_lints!(self, check_fn, fk, decl, body, span, id); hir_visit::walk_fn(self, fk, decl, body_id, span, id); run_lints!(self, check_fn_post, fk, decl, body, span, id); @@ -1191,7 +1207,7 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> { pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE); - let krate = tcx.hir.krate(); + let krate = tcx.hir().krate(); let passes = tcx.sess.lint_store.borrow_mut().late_passes.take(); let passes = { @@ -1270,7 +1286,7 @@ pub fn check_ast_crate( // // Rustdoc runs everybody-loops before the early lints and removes // function bodies, so it's totally possible for linted - // node ids to not exist (e.g. macros defined within functions for the + // node ids to not exist (e.g., macros defined within functions for the // unused_macro lint) anymore. So we only run this check // when we're not in rustdoc mode. (see issue #47639) if !sess.opts.actually_rustdoc { diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index cfb9f04c4c6..9ab8e89df72 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -66,7 +66,7 @@ impl LintLevelSets { for &(ref lint_name, level) in &sess.opts.lint_opts { store.check_lint_name_cmdline(sess, &lint_name, level); - // If the cap is less than this specified level, e.g. if we've got + // If the cap is less than this specified level, e.g., if we've got // `--cap-lints allow` but we've also got `-D foo` then we ignore // this specification as the lint cap will set it to allow anyway. let level = cmp::min(level, self.lint_cap); @@ -191,7 +191,7 @@ impl<'a> LintLevelsBuilder<'a> { /// * It'll validate all lint-related attributes in `attrs` /// * It'll mark all lint-related attributes as used /// * Lint levels will be updated based on the attributes provided - /// * Lint attributes are validated, e.g. a #[forbid] can't be switched to + /// * Lint attributes are validated, e.g., a #[forbid] can't be switched to /// #[allow] /// /// Don't forget to call `pop`! @@ -385,7 +385,7 @@ impl<'a> LintLevelsBuilder<'a> { } err.emit(); } - CheckLintNameResult::NoLint => { + CheckLintNameResult::NoLint(suggestion) => { let lint = builtin::UNKNOWN_LINTS; let (level, src) = self.sets.get_lint_level(lint, self.cur, @@ -398,22 +398,17 @@ impl<'a> LintLevelsBuilder<'a> { src, Some(li.span.into()), &msg); - if name.as_str().chars().any(|c| c.is_uppercase()) { - let name_lower = name.as_str().to_lowercase().to_string(); - if let CheckLintNameResult::NoLint = - store.check_lint_name(&name_lower, tool_name) { - db.emit(); - } else { - db.span_suggestion_with_applicability( - li.span, - "lowercase the lint name", - name_lower, - Applicability::MachineApplicable - ).emit(); - } - } else { - db.emit(); + + if let Some(suggestion) = suggestion { + db.span_suggestion_with_applicability( + li.span, + "did you mean", + suggestion.to_string(), + Applicability::MachineApplicable, + ); } + + db.emit(); } } } diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 4b878b86252..7a8aa7e362a 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -67,7 +67,7 @@ pub struct Lint { /// `declare_lint!()` invocations to follow the convention of upper-case /// statics without repeating the name. /// - /// The name is written with underscores, e.g. "unused_imports". + /// The name is written with underscores, e.g., "unused_imports". /// On the command line, underscores become dashes. pub name: &'static str, @@ -76,7 +76,7 @@ pub struct Lint { /// Description of the lint or the issue it detects. /// - /// e.g. "imports that are never used" + /// e.g., "imports that are never used" pub desc: &'static str, /// Starting at the given edition, default to the given lint level. If this is `None`, then use @@ -173,7 +173,7 @@ pub type LintArray = Vec<&'static Lint>; pub trait LintPass { /// Get descriptions of the lints this `LintPass` object can emit. /// - /// NB: there is no enforcement that the object only emits lints it registered. + /// N.B., there is no enforcement that the object only emits lints it registered. /// And some `rustc` internal `LintPass`es register lints to be emitted by other /// parts of the compiler. If you want enforced access restrictions for your /// `Lint`, make it a private `static` item in its own module. @@ -643,7 +643,7 @@ fn lint_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cnum: CrateNum) levels: LintLevelSets::builder(tcx.sess), tcx: tcx, }; - let krate = tcx.hir.krate(); + let krate = tcx.hir().krate(); builder.with_lint_attrs(ast::CRATE_NODE_ID, &krate.attrs, |builder| { intravisit::walk_crate(builder, krate); @@ -665,7 +665,7 @@ impl<'a, 'tcx> LintLevelMapBuilder<'a, 'tcx> { where F: FnOnce(&mut Self) { let push = self.levels.push(attrs); - self.levels.register_id(self.tcx.hir.definitions().node_to_hir_id(id)); + self.levels.register_id(self.tcx.hir().definitions().node_to_hir_id(id)); f(self); self.levels.pop(push); } @@ -673,7 +673,7 @@ impl<'a, 'tcx> LintLevelMapBuilder<'a, 'tcx> { impl<'a, 'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> { - intravisit::NestedVisitorMap::All(&self.tcx.hir) + intravisit::NestedVisitorMap::All(&self.tcx.hir()) } fn visit_item(&mut self, it: &'tcx hir::Item) { diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 4720bb29549..c7f93512cd8 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -59,7 +59,7 @@ pub enum DepKind { /// A dependency that is only used for its macros. MacrosOnly, /// A dependency that is always injected into the dependency list and so - /// doesn't need to be linked to an rlib, e.g. the injected allocator. + /// doesn't need to be linked to an rlib, e.g., the injected allocator. Implicit, /// A dependency that is required by an rlib version of this crate. /// Ordinary `extern crate`s result in `Explicit` dependencies. diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 282b5d13e2c..934d7c12be5 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -35,7 +35,7 @@ use syntax_pos; // may need to be marked as live. fn should_explore<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) -> bool { - match tcx.hir.find(node_id) { + match tcx.hir().find(node_id) { Some(Node::Item(..)) | Some(Node::ImplItem(..)) | Some(Node::ForeignItem(..)) | @@ -59,7 +59,7 @@ struct MarkSymbolVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { fn check_def_id(&mut self, def_id: DefId) { - if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) { + if let Some(node_id) = self.tcx.hir().as_local_node_id(def_id) { if should_explore(self.tcx, node_id) { self.worklist.push(node_id); } @@ -68,7 +68,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { } fn insert_def_id(&mut self, def_id: DefId) { - if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) { + if let Some(node_id) = self.tcx.hir().as_local_node_id(def_id) { debug_assert!(!should_explore(self.tcx, node_id)); self.live_symbols.insert(node_id); } @@ -137,7 +137,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { continue } - if let Some(ref node) = self.tcx.hir.find(id) { + if let Some(ref node) = self.tcx.hir().find(id) { self.live_symbols.insert(id); self.visit_node(node); } @@ -153,7 +153,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { Node::Item(item) => { match item.node { hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => { - let def_id = self.tcx.hir.local_def_id(item.id); + let def_id = self.tcx.hir().local_def_id(item.id); let def = self.tcx.adt_def(def_id); self.repr_has_repr_c = def.repr.c(); @@ -166,6 +166,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { hir::ItemKind::Fn(..) | hir::ItemKind::Ty(..) | hir::ItemKind::Static(..) + | hir::ItemKind::Existential(..) | hir::ItemKind::Const(..) => { intravisit::walk_item(self, &item); } @@ -205,7 +206,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { fn visit_nested_body(&mut self, body: hir::BodyId) { let old_tables = self.tables; self.tables = self.tcx.body_tables(body); - let body = self.tcx.hir.body(body); + let body = self.tcx.hir().body(body); self.visit_body(body); self.tables = old_tables; } @@ -306,11 +307,11 @@ fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_, '_, '_>, return true; } - let def_id = tcx.hir.local_def_id(id); + let def_id = tcx.hir().local_def_id(id); let cg_attrs = tcx.codegen_fn_attrs(def_id); // #[used], #[no_mangle], #[export_name], etc also keeps the item alive - // forcefully, e.g. for placing it in a specific section. + // forcefully, e.g., for placing it in a specific section. if cg_attrs.contains_extern_indicator() || cg_attrs.flags.contains(CodegenFnAttrFlags::USED) { return true; @@ -468,7 +469,7 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> { } fn should_warn_about_field(&mut self, field: &hir::StructField) -> bool { - let field_type = self.tcx.type_of(self.tcx.hir.local_def_id(field.id)); + let field_type = self.tcx.type_of(self.tcx.hir().local_def_id(field.id)); !field.is_positional() && !self.symbol_is_live(field.id, None) && !field_type.is_phantom_data() @@ -509,11 +510,11 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> { // This is done to handle the case where, for example, the static // method of a private type is used, but the type itself is never // called directly. - let def_id = self.tcx.hir.local_def_id(id); + let def_id = self.tcx.hir().local_def_id(id); let inherent_impls = self.tcx.inherent_impls(def_id); for &impl_did in inherent_impls.iter() { for &item_did in &self.tcx.associated_item_def_ids(impl_did)[..] { - if let Some(item_node_id) = self.tcx.hir.as_local_node_id(item_did) { + if let Some(item_node_id) = self.tcx.hir().as_local_node_id(item_did) { if self.live_symbols.contains(&item_node_id) { return true; } @@ -546,7 +547,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> { /// an error. We could do this also by checking the parents, but /// this is how the code is setup and it seems harmless enough. fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::All(&self.tcx.hir) + NestedVisitorMap::All(&self.tcx.hir()) } fn visit_item(&mut self, item: &'tcx hir::Item) { @@ -647,7 +648,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> { pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE); - let krate = tcx.hir.krate(); + let krate = tcx.hir().krate(); let live_symbols = find_live(tcx, access_levels, krate); let mut visitor = DeadVisitor { tcx, diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs index 549a848a39d..5e75f119aef 100644 --- a/src/librustc/middle/dependency_format.rs +++ b/src/librustc/middle/dependency_format.rs @@ -201,7 +201,7 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // static libraries. // // If the crate hasn't been included yet and it's not actually required - // (e.g. it's an allocator) then we skip it here as well. + // (e.g., it's an allocator) then we skip it here as well. for &cnum in tcx.crates().iter() { let src = tcx.used_crate_source(cnum); if src.dylib.is_none() && @@ -306,7 +306,7 @@ fn attempt_static<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option EntryPointType { match item.node { @@ -98,7 +98,7 @@ fn entry_point_type(item: &Item, at_root: bool) -> EntryPointType { EntryPointType::MainAttr } else if item.name == "main" { if at_root { - // This is a top-level function so can be 'main' + // This is a top-level function so can be 'main'. EntryPointType::MainNamed } else { EntryPointType::OtherMain diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 5b92bfe6ad3..f1bc37d03e5 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -622,7 +622,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { match local.init { None => { local.pat.each_binding(|_, hir_id, span, _| { - let node_id = self.mc.tcx.hir.hir_to_node_id(hir_id); + let node_id = self.mc.tcx.hir().hir_to_node_id(hir_id); self.delegate.decl_without_init(node_id, span); }) } @@ -813,7 +813,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { self.consume_expr(&arm.body); } - /// Walks a pat that occurs in isolation (i.e. top-level of fn + /// Walks a pat that occurs in isolation (i.e., top-level of fn /// arg or let binding. *Not* a match arm or nested pat.) fn walk_irrefutable_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat) { let mut mode = Unknown; @@ -851,7 +851,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } /// The core driver for walking a pattern; `match_mode` must be - /// established up front, e.g. via `determine_pat_move_mode` (see + /// established up front, e.g., via `determine_pat_move_mode` (see /// also `walk_irrefutable_pat` for patterns that stand alone). fn walk_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat, match_mode: MatchMode) { debug!("walk_pat(cmt_discr={:?}, pat={:?})", cmt_discr, pat); @@ -935,8 +935,8 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { self.tcx().with_freevars(closure_expr.id, |freevars| { for freevar in freevars { - let var_hir_id = self.tcx().hir.node_to_hir_id(freevar.var_id()); - let closure_def_id = self.tcx().hir.local_def_id(closure_expr.id); + let var_hir_id = self.tcx().hir().node_to_hir_id(freevar.var_id()); + let closure_def_id = self.tcx().hir().local_def_id(closure_expr.id); let upvar_id = ty::UpvarId { var_path: ty::UpvarPath { hir_id: var_hir_id }, closure_expr_id: closure_def_id.to_local(), @@ -973,7 +973,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { -> mc::McResult> { // Create the cmt for the variable being borrowed, from the // caller's perspective - let var_hir_id = self.tcx().hir.node_to_hir_id(upvar.var_id()); + let var_hir_id = self.tcx().hir().node_to_hir_id(upvar.var_id()); let var_ty = self.mc.node_ty(var_hir_id)?; self.mc.cat_def(closure_hir_id, closure_span, var_ty, upvar.def) } diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index d2be0e4dcb9..fa34c2e63da 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -23,7 +23,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let mut visitor = ItemVisitor { tcx, }; - tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor()); + tcx.hir().krate().visit_all_item_likes(&mut visitor.as_deep_visitor()); } struct ItemVisitor<'a, 'tcx: 'a> { @@ -134,8 +134,8 @@ impl<'a, 'tcx> Visitor<'tcx> for ItemVisitor<'a, 'tcx> { } fn visit_nested_body(&mut self, body_id: hir::BodyId) { - let owner_def_id = self.tcx.hir.body_owner_def_id(body_id); - let body = self.tcx.hir.body(body_id); + let owner_def_id = self.tcx.hir().body_owner_def_id(body_id); + let body = self.tcx.hir().body(body_id); let param_env = self.tcx.param_env(owner_def_id); let tables = self.tcx.typeck_tables_of(owner_def_id); ExprVisitor { tcx: self.tcx, param_env, tables }.visit_body(body); diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index e7a8baf7383..cfcc7c83719 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -13,9 +13,9 @@ // Language items are items that represent concepts intrinsic to the language // itself. Examples are: // -// * Traits that specify "kinds"; e.g. "Sync", "Send". +// * Traits that specify "kinds"; e.g., "Sync", "Send". // -// * Traits that represent operators; e.g. "Add", "Sub", "Index". +// * Traits that represent operators; e.g., "Add", "Sub", "Index". // // * Functions called by the compiler itself. @@ -108,7 +108,7 @@ impl<'a, 'v, 'tcx> ItemLikeVisitor<'v> for LanguageItemCollector<'a, 'tcx> { match self.item_refs.get(&*value.as_str()).cloned() { // Known lang item with attribute on correct target. Some((item_index, expected_target)) if actual_target == expected_target => { - let def_id = self.tcx.hir.local_def_id(item.id); + let def_id = self.tcx.hir().local_def_id(item.id); self.collect_item(item_index, def_id); }, // Known lang item with attribute on incorrect target. @@ -171,7 +171,7 @@ impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> { if let Some(original_def_id) = self.items.items[item_index] { if original_def_id != item_def_id { let name = LangItem::from_u32(item_index as u32).unwrap().name(); - let mut err = match self.tcx.hir.span_if_local(item_def_id) { + let mut err = match self.tcx.hir().span_if_local(item_def_id) { Some(span) => struct_span_err!( self.tcx.sess, span, @@ -183,7 +183,7 @@ impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> { self.tcx.crate_name(item_def_id.krate), name)), }; - if let Some(span) = self.tcx.hir.span_if_local(original_def_id) { + if let Some(span) = self.tcx.hir().span_if_local(original_def_id) { span_note!(&mut err, span, "first defined here."); } else { err.note(&format!("first defined in crate `{}`.", @@ -221,7 +221,7 @@ pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItems { collector.collect_item(item_index, def_id); } } - tcx.hir.krate().visit_all_item_likes(&mut collector); + tcx.hir().krate().visit_all_item_likes(&mut collector); let LanguageItemCollector { mut items, .. } = collector; weak_lang_items::check_crate(tcx, &mut items); items @@ -301,6 +301,7 @@ language_item_table! { DerefTraitLangItem, "deref", deref_trait, Target::Trait; DerefMutTraitLangItem, "deref_mut", deref_mut_trait, Target::Trait; + ReceiverTraitLangItem, "receiver", receiver_trait, Target::Trait; FnTraitLangItem, "fn", fn_trait, Target::Trait; FnMutTraitLangItem, "fn_mut", fn_mut_trait, Target::Trait; diff --git a/src/librustc/middle/lib_features.rs b/src/librustc/middle/lib_features.rs index 7d65d412e01..8934c7ebb2a 100644 --- a/src/librustc/middle/lib_features.rs +++ b/src/librustc/middle/lib_features.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Detecting lib features (i.e. features that are not lang features). +// Detecting lib features (i.e., features that are not lang features). // -// These are declared using stability attributes (e.g. `#[stable (..)]` +// These are declared using stability attributes (e.g., `#[stable (..)]` // and `#[unstable (..)]`), but are not declared in one single location // (unlike lang features), which means we need to collect them instead. @@ -61,7 +61,7 @@ impl<'a, 'tcx> LibFeatureCollector<'a, 'tcx> { fn extract(&self, attr: &Attribute) -> Option<(Symbol, Option, Span)> { let stab_attrs = vec!["stable", "unstable", "rustc_const_unstable"]; - // Find a stability attribute (i.e. `#[stable (..)]`, `#[unstable (..)]`, + // Find a stability attribute (i.e., `#[stable (..)]`, `#[unstable (..)]`, // `#[rustc_const_unstable (..)]`). if let Some(stab_attr) = stab_attrs.iter().find(|stab_attr| { attr.check_name(stab_attr) @@ -140,7 +140,7 @@ impl<'a, 'tcx> LibFeatureCollector<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for LibFeatureCollector<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::All(&self.tcx.hir) + NestedVisitorMap::All(&self.tcx.hir()) } fn visit_attribute(&mut self, attr: &'tcx Attribute) { @@ -152,6 +152,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LibFeatureCollector<'a, 'tcx> { pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LibFeatures { let mut collector = LibFeatureCollector::new(tcx); - intravisit::walk_crate(&mut collector, tcx.hir.krate()); + intravisit::walk_crate(&mut collector, tcx.hir().krate()); collector.lib_features } diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 54a0192d2e8..d1d2fa298a6 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -176,7 +176,7 @@ fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt<'_, '_, '_>) -> Strin impl<'a, 'tcx> Visitor<'tcx> for IrMaps<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir) + NestedVisitorMap::OnlyBodies(&self.tcx.hir()) } fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl, @@ -190,7 +190,7 @@ impl<'a, 'tcx> Visitor<'tcx> for IrMaps<'a, 'tcx> { } pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - tcx.hir.krate().visit_all_item_likes(&mut IrMaps::new(tcx).as_deep_visitor()); + tcx.hir().krate().visit_all_item_likes(&mut IrMaps::new(tcx).as_deep_visitor()); tcx.sess.abort_if_errors(); } @@ -362,8 +362,8 @@ fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>, // Don't run unused pass for #[derive()] if let FnKind::Method(..) = fk { - let parent = ir.tcx.hir.get_parent(id); - if let Some(Node::Item(i)) = ir.tcx.hir.find(parent) { + let parent = ir.tcx.hir().get_parent(id); + if let Some(Node::Item(i)) = ir.tcx.hir().find(parent) { if i.attrs.iter().any(|a| a.check_name("automatically_derived")) { return; } @@ -372,7 +372,7 @@ fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>, debug!("creating fn_maps: {:?}", &fn_maps as *const IrMaps<'_, '_>); - let body = ir.tcx.hir.body(body_id); + let body = ir.tcx.hir().body(body_id); for arg in &body.arguments { arg.pat.each_binding(|_bm, hir_id, _x, ident| { @@ -476,7 +476,7 @@ fn visit_expr<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, expr: &'tcx Expr) { call_caps.extend(freevars.iter().filter_map(|fv| { if let Def::Local(rv) = fv.def { let fv_ln = ir.add_live_node(FreeVarNode(fv.span)); - let var_hid = ir.tcx.hir.node_to_hir_id(rv); + let var_hid = ir.tcx.hir().node_to_hir_id(rv); Some(CaptureInfo { ln: fv_ln, var_hid }) } else { None @@ -554,7 +554,7 @@ struct RWUTable { /// 65 bits of data into 32; in the uncommon cases, it expands the 65 bits /// in 96. /// - /// More compact representations are possible -- e.g. use only 2 bits per + /// More compact representations are possible -- e.g., use only 2 bits per /// packed `RWU` and make the secondary table a HashMap that maps from /// indices to `RWU`s -- but this one strikes a good balance between size /// and speed. @@ -924,7 +924,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // effectively a return---this only occurs in `for` loops, // where the body is really a closure. - debug!("compute: using id for body, {}", self.ir.tcx.hir.node_to_pretty_string(body.id)); + debug!("compute: using id for body, {}", self.ir.tcx.hir().node_to_pretty_string(body.id)); let exit_ln = self.s.exit_ln; @@ -1021,7 +1021,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode) -> LiveNode { - debug!("propagate_through_expr: {}", self.ir.tcx.hir.node_to_pretty_string(expr.id)); + debug!("propagate_through_expr: {}", self.ir.tcx.hir().node_to_pretty_string(expr.id)); match expr.node { // Interesting cases with control flow or which gen/kill @@ -1035,7 +1035,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprKind::Closure(.., blk_id, _, _) => { debug!("{} is an ExprKind::Closure", - self.ir.tcx.hir.node_to_pretty_string(expr.id)); + self.ir.tcx.hir().node_to_pretty_string(expr.id)); // The next-node for a break is the successor of the entire // loop. The next-node for a continue is the top of this loop. @@ -1197,8 +1197,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } hir::ExprKind::Call(ref f, ref args) => { - // FIXME(canndrew): This is_never should really be an is_uninhabited - let succ = if self.tables.expr_ty(expr).is_never() { + let m = self.ir.tcx.hir().get_module_parent(expr.id); + let succ = if self.ir.tcx.is_ty_uninhabited_from(m, self.tables.expr_ty(expr)) { self.s.exit_ln } else { succ @@ -1208,8 +1208,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } hir::ExprKind::MethodCall(.., ref args) => { - // FIXME(canndrew): This is_never should really be an is_uninhabited - let succ = if self.tables.expr_ty(expr).is_never() { + let m = self.ir.tcx.hir().get_module_parent(expr.id); + let succ = if self.ir.tcx.is_ty_uninhabited_from(m, self.tables.expr_ty(expr)) { self.s.exit_ln } else { succ @@ -1356,7 +1356,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { let ln = self.live_node(hir_id, span); if acc != 0 { self.init_from_succ(ln, succ); - let var_hid = self.ir.tcx.hir.node_to_hir_id(nid); + let var_hid = self.ir.tcx.hir().node_to_hir_id(nid); let var = self.variable(var_hid, span); self.acc(ln, var, acc); } @@ -1413,7 +1413,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } } debug!("propagate_through_loop: using id for loop body {} {}", - expr.id, self.ir.tcx.hir.node_to_pretty_string(body.id)); + expr.id, self.ir.tcx.hir().node_to_pretty_string(body.id)); let break_ln = succ; let cont_ln = ln; @@ -1547,7 +1547,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // mutable, then check for a reassignment to flag the mutability // as being used. let ln = self.live_node(expr.hir_id, expr.span); - let var_hid = self.ir.tcx.hir.node_to_hir_id(nid); + let var_hid = self.ir.tcx.hir().node_to_hir_id(nid); let var = self.variable(var_hid, expr.span); self.warn_about_dead_assign(expr.span, expr.hir_id, ln, var); } @@ -1575,7 +1575,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { let sp = ident.span; let var = self.variable(hir_id, sp); // Ignore unused self. - if ident.name != keywords::SelfValue.name() { + if ident.name != keywords::SelfLower.name() { if !self.warn_about_unused(sp, hir_id, entry_ln, var) { if self.live_on_entry(entry_ln, var).is_none() { self.report_dead_assign(hir_id, sp, var, true); @@ -1657,11 +1657,15 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn report_dead_assign(&self, hir_id: HirId, sp: Span, var: Variable, is_argument: bool) { if let Some(name) = self.should_warn(var) { if is_argument { - self.ir.tcx.lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, sp, - &format!("value passed to `{}` is never read", name)); + self.ir.tcx.struct_span_lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, sp, + &format!("value passed to `{}` is never read", name)) + .help("maybe it is overwritten before being read?") + .emit(); } else { - self.ir.tcx.lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, sp, - &format!("value assigned to `{}` is never read", name)); + self.ir.tcx.struct_span_lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, sp, + &format!("value assigned to `{}` is never read", name)) + .help("maybe it is overwritten before being read?") + .emit(); } } } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index cadf0c42d22..a04914e9774 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -127,7 +127,7 @@ pub enum PointerKind<'tcx> { } // We use the term "interior" to mean "something reachable from the -// base without a pointer dereference", e.g. a field +// base without a pointer dereference", e.g., a field #[derive(Clone, Copy, PartialEq, Eq, Hash)] pub enum InteriorKind { InteriorField(FieldIndex), @@ -153,8 +153,8 @@ impl Hash for FieldIndex { #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] pub enum InteriorOffsetKind { - Index, // e.g. `array_expr[index_expr]` - Pattern, // e.g. `fn foo([_, a, _, _]: [A; 4]) { ... }` + Index, // e.g., `array_expr[index_expr]` + Pattern, // e.g., `fn foo([_, a, _, _]: [A; 4]) { ... }` } #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] @@ -348,7 +348,7 @@ impl MutabilityCategory { fn from_local(tcx: TyCtxt<'_, '_, '_>, tables: &ty::TypeckTables<'_>, id: ast::NodeId) -> MutabilityCategory { - let ret = match tcx.hir.get(id) { + let ret = match tcx.hir().get(id) { Node::Binding(p) => match p.node { PatKind::Binding(..) => { let bm = *tables.pat_binding_modes() @@ -362,7 +362,7 @@ impl MutabilityCategory { } _ => span_bug!(p.span, "expected identifier pattern") }, - _ => span_bug!(tcx.hir.span(id), "expected identifier pattern") + _ => span_bug!(tcx.hir().span(id), "expected identifier pattern") }; debug!("MutabilityCategory::{}(tcx, id={:?}) => {:?}", "from_local", id, ret); @@ -495,9 +495,9 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { // FIXME None if self.is_tainted_by_errors() => Err(()), None => { - let id = self.tcx.hir.hir_to_node_id(id); + let id = self.tcx.hir().hir_to_node_id(id); bug!("no type for node {}: {} in mem_categorization", - id, self.tcx.hir.node_to_string(id)); + id, self.tcx.hir().node_to_string(id)); } } } @@ -770,7 +770,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { fn_node_id: ast::NodeId) -> McResult> { - let fn_hir_id = self.tcx.hir.node_to_hir_id(fn_node_id); + let fn_hir_id = self.tcx.hir().node_to_hir_id(fn_node_id); // An upvar can have up to 3 components. We translate first to a // `Categorization::Upvar`, which is itself a fiction -- it represents the reference to the @@ -815,8 +815,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { ref t => span_bug!(span, "unexpected type for fn in mem_categorization: {:?}", t), }; - let closure_expr_def_id = self.tcx.hir.local_def_id(fn_node_id); - let var_hir_id = self.tcx.hir.node_to_hir_id(var_id); + let closure_expr_def_id = self.tcx.hir().local_def_id(fn_node_id); + let var_hir_id = self.tcx.hir().node_to_hir_id(var_id); let upvar_id = ty::UpvarId { var_path: ty::UpvarPath { hir_id: var_hir_id }, closure_expr_id: closure_expr_def_id.to_local(), @@ -961,7 +961,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { debug!("cat_rvalue_node: promotable = {:?}", promotable); - // Always promote `[T; 0]` (even when e.g. borrowed mutably). + // Always promote `[T; 0]` (even when e.g., borrowed mutably). let promotable = match expr_ty.sty { ty::Array(_, len) if len.assert_usize(self.tcx) == Some(0) => true, _ => promotable, @@ -1504,7 +1504,7 @@ impl<'tcx> cmt_<'tcx> { "non-place".into() } Categorization::Local(vid) => { - if tcx.hir.is_argument(vid) { + if tcx.hir().is_argument(vid) { "argument" } else { "local variable" diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index ab0094df0e2..89814dde262 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -47,7 +47,7 @@ fn item_might_be_inlined(tcx: TyCtxt<'a, 'tcx, 'tcx>, match item.node { hir::ItemKind::Impl(..) | hir::ItemKind::Fn(..) => { - let generics = tcx.generics_of(tcx.hir.local_def_id(item.id)); + let generics = tcx.generics_of(tcx.hir().local_def_id(item.id)); generics.requires_monomorphization(tcx) } _ => false, @@ -58,12 +58,12 @@ fn method_might_be_inlined<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_item: &hir::ImplItem, impl_src: DefId) -> bool { let codegen_fn_attrs = tcx.codegen_fn_attrs(impl_item.hir_id.owner_def_id()); - let generics = tcx.generics_of(tcx.hir.local_def_id(impl_item.id)); + let generics = tcx.generics_of(tcx.hir().local_def_id(impl_item.id)); if codegen_fn_attrs.requests_inline() || generics.requires_monomorphization(tcx) { return true } - if let Some(impl_node_id) = tcx.hir.as_local_node_id(impl_src) { - match tcx.hir.find(impl_node_id) { + if let Some(impl_node_id) = tcx.hir().as_local_node_id(impl_src) { + match tcx.hir().find(impl_node_id) { Some(Node::Item(item)) => item_might_be_inlined(tcx, &item, codegen_fn_attrs), Some(..) | None => @@ -96,7 +96,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> { fn visit_nested_body(&mut self, body: hir::BodyId) { let old_tables = self.tables; self.tables = self.tcx.body_tables(body); - let body = self.tcx.hir.body(body); + let body = self.tcx.hir().body(body); self.visit_body(body); self.tables = old_tables; } @@ -118,7 +118,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> { } Some(def) => { if let Some((node_id, def_id)) = def.opt_def_id().and_then(|def_id| { - self.tcx.hir.as_local_node_id(def_id).map(|node_id| (node_id, def_id)) + self.tcx.hir().as_local_node_id(def_id).map(|node_id| (node_id, def_id)) }) { if self.def_id_represents_local_inlined_item(def_id) { self.worklist.push(node_id); @@ -151,12 +151,12 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { // Returns true if the given def ID represents a local item that is // eligible for inlining and false otherwise. fn def_id_represents_local_inlined_item(&self, def_id: DefId) -> bool { - let node_id = match self.tcx.hir.as_local_node_id(def_id) { + let node_id = match self.tcx.hir().as_local_node_id(def_id) { Some(node_id) => node_id, None => { return false; } }; - match self.tcx.hir.find(node_id) { + match self.tcx.hir().find(node_id) { Some(Node::Item(item)) => { match item.node { hir::ItemKind::Fn(..) => @@ -182,13 +182,13 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { true } else { let impl_did = self.tcx - .hir + .hir() .get_parent_did(node_id); // Check the impl. If the generics on the self // type of the impl require inlining, this method // does too. - let impl_node_id = self.tcx.hir.as_local_node_id(impl_did).unwrap(); - match self.tcx.hir.expect_item(impl_node_id).node { + let impl_node_id = self.tcx.hir().as_local_node_id(impl_did).unwrap(); + match self.tcx.hir().expect_item(impl_node_id).node { hir::ItemKind::Impl(..) => { let generics = self.tcx.generics_of(impl_did); generics.requires_monomorphization(self.tcx) @@ -214,7 +214,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { continue } - if let Some(ref item) = self.tcx.hir.find(search_item) { + if let Some(ref item) = self.tcx.hir().find(search_item) { self.propagate_node(item, search_item); } } @@ -231,7 +231,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { } else { false }; - let def_id = self.tcx.hir.local_def_id(item.id); + let def_id = self.tcx.hir().local_def_id(item.id); let codegen_attrs = self.tcx.codegen_fn_attrs(def_id); let is_extern = codegen_attrs.contains_extern_indicator(); let std_internal = codegen_attrs.flags.contains( @@ -252,7 +252,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { Node::Item(item) => { match item.node { hir::ItemKind::Fn(.., body) => { - let def_id = self.tcx.hir.local_def_id(item.id); + let def_id = self.tcx.hir().local_def_id(item.id); if item_might_be_inlined(self.tcx, &item, self.tcx.codegen_fn_attrs(def_id)) { @@ -305,7 +305,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { self.visit_nested_body(body); } hir::ImplItemKind::Method(_, body) => { - let did = self.tcx.hir.get_parent_did(search_item); + let did = self.tcx.hir().get_parent_did(search_item); if method_might_be_inlined(self.tcx, impl_item, did) { self.visit_nested_body(body) } @@ -326,7 +326,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { Node::MacroDef(_) => {} _ => { bug!("found unexpected thingy in worklist: {}", - self.tcx.hir.node_to_string(search_item)) + self.tcx.hir().node_to_string(search_item)) } } } @@ -351,7 +351,7 @@ impl<'a, 'tcx: 'a> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a, // Anything which has custom linkage gets thrown on the worklist no // matter where it is in the crate, along with "special std symbols" // which are currently akin to allocator symbols. - let def_id = self.tcx.hir.local_def_id(item.id); + let def_id = self.tcx.hir().local_def_id(item.id); let codegen_attrs = self.tcx.codegen_fn_attrs(def_id); if codegen_attrs.contains_extern_indicator() || codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) { @@ -376,7 +376,7 @@ impl<'a, 'tcx: 'a> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a, self.worklist.reserve(provided_trait_methods.len()); for default_method in provided_trait_methods { let node_id = self.tcx - .hir + .hir() .as_local_node_id(default_method.def_id) .unwrap(); self.worklist.push(node_id); @@ -422,7 +422,7 @@ fn reachable_set<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) -> reachable_context.worklist.extend(access_levels.map.iter().map(|(id, _)| *id)); for item in tcx.lang_items().items().iter() { if let Some(did) = *item { - if let Some(node_id) = tcx.hir.as_local_node_id(did) { + if let Some(node_id) = tcx.hir().as_local_node_id(did) { reachable_context.worklist.push(node_id); } } @@ -433,7 +433,7 @@ fn reachable_set<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) -> access_levels, worklist: &mut reachable_context.worklist, }; - tcx.hir.krate().visit_all_item_likes(&mut collect_private_impl_items); + tcx.hir().krate().visit_all_item_likes(&mut collect_private_impl_items); } // Step 2: Mark all symbols that the symbols on the worklist touch. diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 35d1a4dd2cb..9977faf5b2c 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -84,7 +84,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, /// (D9.): DestructionScope for temporaries created during M8. /// (R10.): Remainder scope for block `'b:`, stmt 1 (let y = ...). /// (D11.): DestructionScope for temporaries and bindings from block `'b:`. -/// (D12.): DestructionScope for temporaries created during M1 (e.g. f()). +/// (D12.): DestructionScope for temporaries created during M1 (e.g., f()). /// ``` /// /// Note that while the above picture shows the destruction scopes @@ -155,7 +155,7 @@ pub enum ScopeData { /// everything after that first `let`. (If you want a scope that /// includes EXPR_1 as well, then do not use `Scope::Remainder`, /// but instead another `Scope` that encompasses the whole block, -/// e.g. `Scope::Node`. +/// e.g., `Scope::Node`. /// /// * the subscope with `first_statement_index == 1` is scope of `c`, /// and thus does not include EXPR_2, but covers the `...`. @@ -172,7 +172,7 @@ static_assert!(ASSERT_SCOPE_DATA: mem::size_of::() == 4); impl Scope { /// Returns a item-local id associated with this scope. /// - /// NB: likely to be replaced as API is refined; e.g. pnkfelix + /// N.B., likely to be replaced as API is refined; e.g., pnkfelix /// anticipates `fn entry_node_id` and `fn each_exit_node_id`. pub fn item_local_id(&self) -> hir::ItemLocalId { self.id @@ -181,7 +181,7 @@ impl Scope { pub fn node_id(&self, tcx: TyCtxt<'_, '_, '_>, scope_tree: &ScopeTree) -> ast::NodeId { match scope_tree.root_body { Some(hir_id) => { - tcx.hir.hir_to_node_id(hir::HirId { + tcx.hir().hir_to_node_id(hir::HirId { owner: hir_id.owner, local_id: self.item_local_id() }) @@ -198,9 +198,9 @@ impl Scope { if node_id == ast::DUMMY_NODE_ID { return DUMMY_SP; } - let span = tcx.hir.span(node_id); + let span = tcx.hir().span(node_id); if let ScopeData::Remainder(first_statement_index) = self.data { - if let Node::Block(ref blk) = tcx.hir.get(node_id) { + 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 // `blk`; reuse span of `blk` and shift `lo` @@ -592,10 +592,7 @@ impl<'tcx> ScopeTree { return Some(scope.item_local_id()); } - match self.opt_encl_scope(scope) { - None => return None, - Some(parent) => scope = parent, - } + scope = self.opt_encl_scope(scope)?; } } @@ -663,9 +660,9 @@ impl<'tcx> ScopeTree { -> Scope { let param_owner = tcx.parent_def_id(br.def_id).unwrap(); - let param_owner_id = tcx.hir.as_local_node_id(param_owner).unwrap(); - let scope = tcx.hir.maybe_body_owned_by(param_owner_id).map(|body_id| { - tcx.hir.body(body_id).value.hir_id.local_id + let param_owner_id = tcx.hir().as_local_node_id(param_owner).unwrap(); + let scope = tcx.hir().maybe_body_owned_by(param_owner_id).map(|body_id| { + tcx.hir().body(body_id).value.hir_id.local_id }).unwrap_or_else(|| { // The lifetime was defined on node that doesn't own a body, // which in practice can only mean a trait or an impl, that @@ -674,7 +671,7 @@ impl<'tcx> ScopeTree { "free_scope: {:?} not recognized by the \ region scope tree for {:?} / {:?}", param_owner, - self.root_parent.map(|id| tcx.hir.local_def_id(id)), + self.root_parent.map(|id| tcx.hir().local_def_id(id)), self.root_body.map(|hir_id| DefId::local(hir_id.owner))); // The trait/impl lifetime is in scope for the method's body. @@ -699,9 +696,9 @@ impl<'tcx> ScopeTree { // on the same function that they ended up being freed in. assert_eq!(param_owner, fr.scope); - 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 { id: tcx.hir.body(body_id).value.hir_id.local_id, data: ScopeData::CallSite } + 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 { id: tcx.hir().body(body_id).value.hir_id.local_id, data: ScopeData::CallSite } } /// Checks whether the given scope contains a `yield`. If so, @@ -773,10 +770,10 @@ fn resolve_block<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, blk: // }, other_argument()); // // Each of the statements within the block is a terminating - // scope, and thus a temporary (e.g. the result of calling + // scope, and thus a temporary (e.g., the result of calling // `bar()` in the initializer expression for `let inner = ...;`) // will be cleaned up immediately after its corresponding - // statement (i.e. `let inner = ...;`) executes. + // statement (i.e., `let inner = ...;`) executes. // // On the other hand, temporaries associated with evaluating the // tail expression for the block are assigned lifetimes so that @@ -848,7 +845,7 @@ fn resolve_pat<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, pat: & } fn resolve_stmt<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, stmt: &'tcx hir::Stmt) { - let stmt_id = visitor.tcx.hir.node_to_hir_id(stmt.node.id()).local_id; + let stmt_id = visitor.tcx.hir().node_to_hir_id(stmt.node.id()).local_id; debug!("resolve_stmt(stmt.id={:?})", stmt_id); // Every statement will clean up the temporaries created during @@ -945,7 +942,7 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr: // Manually recurse over closures, because they are the only // case of nested bodies that share the parent environment. hir::ExprKind::Closure(.., body, _, _) => { - let body = visitor.tcx.hir.body(body); + let body = visitor.tcx.hir().body(body); visitor.visit_body(body); } @@ -987,7 +984,7 @@ fn resolve_local<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, // As an exception to the normal rules governing temporary // lifetimes, initializers in a let have a temporary lifetime - // of the enclosing block. This means that e.g. a program + // of the enclosing block. This means that e.g., a program // like the following is legal: // // let ref x = HashMap::new(); @@ -1186,7 +1183,7 @@ fn resolve_local<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, loop { // Note: give all the expressions matching `ET` with the // extended temporary lifetime, not just the innermost rvalue, - // because in codegen if we must compile e.g. `*rvalue()` + // because in codegen if we must compile e.g., `*rvalue()` // into a temporary, we request the temporary scope of the // outer expression. visitor.scope_tree.record_rvalue_scope(expr.hir_id.local_id, blk_scope); @@ -1247,7 +1244,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionResolutionVisitor<'a, 'tcx> { fn visit_body(&mut self, body: &'tcx hir::Body) { let body_id = body.id(); - let owner_id = self.tcx.hir.body_owner(body_id); + let owner_id = self.tcx.hir().body_owner(body_id); debug!("visit_body(id={:?}, span={:?}, body.id={:?}, cx.parent={:?})", owner_id, @@ -1276,7 +1273,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionResolutionVisitor<'a, 'tcx> { // The body of the every fn is a root scope. self.cx.parent = self.cx.var_parent; - if let hir::BodyOwnerKind::Fn = self.tcx.hir.body_owner_kind(owner_id) { + if let hir::BodyOwnerKind::Fn = self.tcx.hir().body_owner_kind(owner_id) { self.visit_expr(&body.value); } else { // Only functions have an outer terminating (drop) scope, while @@ -1284,7 +1281,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionResolutionVisitor<'a, 'tcx> { // according to rvalue lifetime semantics, using the same // syntactical rules used for let initializers. // - // E.g. in `let x = &f();`, the temporary holding the result from + // e.g., in `let x = &f();`, the temporary holding the result from // the `f()` call lives for the entirety of the surrounding block. // // Similarly, `const X: ... = &f();` would have the result of `f()` @@ -1295,7 +1292,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionResolutionVisitor<'a, 'tcx> { // // However, `const Y: ... = g(&f());`, like `let y = g(&f());`, // would *not* let the `f()` temporary escape into an outer scope - // (i.e. `'static`), which means that after `g` returns, it drops, + // (i.e., `'static`), which means that after `g` returns, it drops, // and all the associated destruction scope rules apply. self.cx.var_parent = None; resolve_local(self, None, Some(&body.value)); @@ -1336,8 +1333,8 @@ fn region_scope_tree<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) return tcx.region_scope_tree(closure_base_def_id); } - let id = tcx.hir.as_local_node_id(def_id).unwrap(); - let scope_tree = if let Some(body_id) = tcx.hir.maybe_body_owned_by(id) { + let id = tcx.hir().as_local_node_id(def_id).unwrap(); + let scope_tree = if let Some(body_id) = tcx.hir().maybe_body_owned_by(id) { let mut visitor = RegionResolutionVisitor { tcx, scope_tree: ScopeTree::default(), @@ -1350,16 +1347,16 @@ fn region_scope_tree<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) terminating_scopes: Default::default(), }; - let body = tcx.hir.body(body_id); + let body = tcx.hir().body(body_id); visitor.scope_tree.root_body = Some(body.value.hir_id); // If the item is an associated const or a method, // record its impl/trait parent, as it can also have // lifetime parameters free in this body. - match tcx.hir.get(id) { + match tcx.hir().get(id) { Node::ImplItem(_) | Node::TraitItem(_) => { - visitor.scope_tree.root_parent = Some(tcx.hir.get_parent(id)); + visitor.scope_tree.root_parent = Some(tcx.hir().get_parent(id)); } _ => {} } diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 07054ee99af..571f718f905 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -303,14 +303,14 @@ enum Scope<'a> { /// Lifetimes introduced by a fn are scoped to the call-site for that fn, /// if this is a fn body, otherwise the original definitions are used. /// Unspecified lifetimes are inferred, unless an elision scope is nested, - /// e.g. `(&T, fn(&T) -> &T);` becomes `(&'_ T, for<'a> fn(&'a T) -> &'a T)`. + /// e.g., `(&T, fn(&T) -> &T);` becomes `(&'_ T, for<'a> fn(&'a T) -> &'a T)`. Body { id: hir::BodyId, s: ScopeRef<'a>, }, /// A scope which either determines unspecified lifetimes or errors - /// on them (e.g. due to ambiguity). For more details, see `Elide`. + /// on them (e.g., due to ambiguity). For more details, see `Elide`. Elision { elide: Elide, s: ScopeRef<'a>, @@ -398,19 +398,19 @@ fn resolve_lifetimes<'tcx>( let mut rl = ResolveLifetimes::default(); for (k, v) in named_region_map.defs { - let hir_id = tcx.hir.node_to_hir_id(k); + let hir_id = tcx.hir().node_to_hir_id(k); let map = rl.defs.entry(hir_id.owner_local_def_id()).or_default(); Lrc::get_mut(map).unwrap().insert(hir_id.local_id, v); } for k in named_region_map.late_bound { - let hir_id = tcx.hir.node_to_hir_id(k); + let hir_id = tcx.hir().node_to_hir_id(k); let map = rl.late_bound .entry(hir_id.owner_local_def_id()) .or_default(); Lrc::get_mut(map).unwrap().insert(hir_id.local_id); } for (k, v) in named_region_map.object_lifetime_defaults { - let hir_id = tcx.hir.node_to_hir_id(k); + let hir_id = tcx.hir().node_to_hir_id(k); let map = rl.object_lifetime_defaults .entry(hir_id.owner_local_def_id()) .or_default(); @@ -423,7 +423,7 @@ fn resolve_lifetimes<'tcx>( } fn krate<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) -> NamedRegionMap { - let krate = tcx.hir.krate(); + let krate = tcx.hir().krate(); let mut map = NamedRegionMap { defs: Default::default(), late_bound: Default::default(), @@ -460,7 +460,7 @@ fn sub_items_have_self_param(node: &hir::ItemKind) -> bool { impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::All(&self.tcx.hir) + NestedVisitorMap::All(&self.tcx.hir()) } // We want to nest trait/impl items in their parent, but nothing else. @@ -469,7 +469,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { fn visit_nested_body(&mut self, body: hir::BodyId) { // Each body has their own set of labels, save labels. let saved = replace(&mut self.labels_in_fn, vec![]); - let body = self.tcx.hir.body(body); + let body = self.tcx.hir().body(body); extract_labels(self, body); self.with( Scope::Body { @@ -545,7 +545,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { .iter() .filter_map(|param| match param.kind { GenericParamKind::Lifetime { .. } => { - Some(Region::early(&self.tcx.hir, &mut index, param)) + Some(Region::early(&self.tcx.hir(), &mut index, param)) } GenericParamKind::Type { .. } => { type_count += 1; @@ -596,7 +596,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { .iter() .filter_map(|param| match param.kind { GenericParamKind::Lifetime { .. } => { - Some(Region::late(&self.tcx.hir, param)) + Some(Region::late(&self.tcx.hir(), param)) } _ => None, }) @@ -622,13 +622,13 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { LifetimeName::Implicit => { // If the user does not write *anything*, we // use the object lifetime defaulting - // rules. So e.g. `Box` becomes + // rules. So e.g., `Box` becomes // `Box`. self.resolve_object_lifetime_default(lifetime) } LifetimeName::Underscore => { // If the user writes `'_`, we use the *ordinary* elision - // rules. So the `'_` in e.g. `Box` will be + // rules. So the `'_` in e.g., `Box` will be // resolved the same as the `'_` in `&'_ Foo`. // // cc #48468 @@ -655,7 +655,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // `abstract type MyAnonTy<'b>: MyTrait<'b>;` // ^ ^ this gets resolved in the scope of // the exist_ty generics - let (generics, bounds) = match self.tcx.hir.expect_item(item_id.id).node { + let (generics, bounds) = match self.tcx.hir().expect_item(item_id.id).node { // named existential types are reached via TyKind::Path // this arm is for `impl Trait` in the types of statics, constants and locals hir::ItemKind::Existential(hir::ExistTy { @@ -689,12 +689,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // In the future, this should be fixed and this error should be removed. let def = self.map.defs.get(&lifetime.id).cloned(); if let Some(Region::LateBound(_, def_id, _)) = def { - if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) { + if let Some(node_id) = self.tcx.hir().as_local_node_id(def_id) { // Ensure that the parent of the def is an item, not HRTB - let parent_id = self.tcx.hir.get_parent_node(node_id); + let parent_id = self.tcx.hir().get_parent_node(node_id); let parent_impl_id = hir::ImplItemId { node_id: parent_id }; let parent_trait_id = hir::TraitItemId { node_id: parent_id }; - let krate = self.tcx.hir.forest.krate(); + let krate = self.tcx.hir().forest.krate(); if !(krate.items.contains_key(&parent_id) || krate.impl_items.contains_key(&parent_impl_id) || krate.trait_items.contains_key(&parent_trait_id)) @@ -724,7 +724,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { for param in &generics.params { match param.kind { GenericParamKind::Lifetime { .. } => { - let (name, reg) = Region::early(&self.tcx.hir, &mut index, ¶m); + let (name, reg) = Region::early(&self.tcx.hir(), &mut index, ¶m); if let hir::ParamName::Plain(param_name) = name { if param_name.name == keywords::UnderscoreLifetime.name() { // Pick the elided lifetime "definition" if one exists @@ -790,7 +790,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { Method(ref sig, _) => { let tcx = self.tcx; self.visit_early_late( - Some(tcx.hir.get_parent(trait_item.id)), + Some(tcx.hir().get_parent(trait_item.id)), &sig.decl, &trait_item.generics, |this| intravisit::walk_trait_item(this, trait_item), @@ -806,7 +806,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { .iter() .filter_map(|param| match param.kind { GenericParamKind::Lifetime { .. } => { - Some(Region::early(&self.tcx.hir, &mut index, param)) + Some(Region::early(&self.tcx.hir(), &mut index, param)) } GenericParamKind::Type { .. } => { type_count += 1; @@ -845,7 +845,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { Method(ref sig, _) => { let tcx = self.tcx; self.visit_early_late( - Some(tcx.hir.get_parent(impl_item.id)), + Some(tcx.hir().get_parent(impl_item.id)), &sig.decl, &impl_item.generics, |this| intravisit::walk_impl_item(this, impl_item), @@ -861,7 +861,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { .iter() .filter_map(|param| match param.kind { GenericParamKind::Lifetime { .. } => { - Some(Region::early(&self.tcx.hir, &mut index, param)) + Some(Region::early(&self.tcx.hir(), &mut index, param)) } GenericParamKind::Type { .. } => { next_early_index += 1; @@ -891,7 +891,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { .iter() .filter_map(|param| match param.kind { GenericParamKind::Lifetime { .. } => { - Some(Region::early(&self.tcx.hir, &mut index, param)) + Some(Region::early(&self.tcx.hir(), &mut index, param)) } GenericParamKind::Type { .. } => { next_early_index += 1; @@ -976,7 +976,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { .iter() .filter_map(|param| match param.kind { GenericParamKind::Lifetime { .. } => { - Some(Region::late(&self.tcx.hir, param)) + Some(Region::late(&self.tcx.hir(), param)) } _ => None, }) @@ -1051,7 +1051,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { .iter() .filter_map(|param| match param.kind { GenericParamKind::Lifetime { .. } => { - Some(Region::late(&self.tcx.hir, param)) + Some(Region::late(&self.tcx.hir(), param)) } _ => None, }) @@ -1258,12 +1258,12 @@ fn extract_labels(ctxt: &mut LifetimeContext<'_, '_>, body: &hir::Body) { } => { // FIXME (#24278): non-hygienic comparison if let Some(def) = lifetimes.get(&hir::ParamName::Plain(label.modern())) { - let node_id = tcx.hir.as_local_node_id(def.id().unwrap()).unwrap(); + let node_id = tcx.hir().as_local_node_id(def.id().unwrap()).unwrap(); signal_shadowing_problem( tcx, label.name, - original_lifetime(tcx.hir.span(node_id)), + original_lifetime(tcx.hir().span(node_id)), shadower_label(label.span), ); return; @@ -1279,7 +1279,7 @@ fn compute_object_lifetime_defaults( tcx: TyCtxt<'_, '_, '_>, ) -> NodeMap> { let mut map = NodeMap::default(); - for item in tcx.hir.krate().items.values() { + for item in tcx.hir().krate().items.values() { match item.node { hir::ItemKind::Struct(_, ref generics) | hir::ItemKind::Union(_, ref generics) @@ -1355,7 +1355,7 @@ fn object_lifetime_defaults_for_item( add_bounds(&mut set, ¶m.bounds); - let param_def_id = tcx.hir.local_def_id(param.id); + let param_def_id = tcx.hir().local_def_id(param.id); for predicate in &generics.where_clause.predicates { // Look for `type: ...` where clauses. let data = match *predicate { @@ -1399,7 +1399,7 @@ fn object_lifetime_defaults_for_item( .enumerate() .find(|&(_, (_, lt_name, _))| lt_name == name) .map_or(Set1::Many, |(i, (id, _, origin))| { - let def_id = tcx.hir.local_def_id(id); + let def_id = tcx.hir().local_def_id(id); Set1::One(Region::EarlyBound(i as u32, def_id, origin)) }) } @@ -1492,7 +1492,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let name = lifetime.name.ident(); let mut remove_decl = None; if let Some(parent_def_id) = self.tcx.parent(def_id) { - if let Some(generics) = self.tcx.hir.get_generics(parent_def_id) { + if let Some(generics) = self.tcx.hir().get_generics(parent_def_id) { remove_decl = self.lifetime_deletion_span(name, generics); } } @@ -1513,8 +1513,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } } }; - if let Node::Lifetime(hir_lifetime) = self.tcx.hir.get(lifetime.id) { - if let Some(parent) = self.tcx.hir.find(self.tcx.hir.get_parent(hir_lifetime.id)) { + if let Node::Lifetime(hir_lifetime) = self.tcx.hir().get(lifetime.id) { + if let Some(parent) = self.tcx.hir().find(self.tcx.hir().get_parent(hir_lifetime.id)) { match parent { Node::Item(item) => { if let hir::ItemKind::Fn(decl, _, _, _) = &item.node { @@ -1590,9 +1590,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { match lifetimeuseset { Some(LifetimeUseSet::One(lifetime)) => { - let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap(); + let node_id = self.tcx.hir().as_local_node_id(def_id).unwrap(); debug!("node id first={:?}", node_id); - if let Some((id, span, name)) = match self.tcx.hir.get(node_id) { + if let Some((id, span, name)) = match self.tcx.hir().get(node_id) { Node::Lifetime(hir_lifetime) => Some(( hir_lifetime.id, hir_lifetime.span, @@ -1631,8 +1631,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { debug!("Not one use lifetime"); } None => { - let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap(); - if let Some((id, span, name)) = match self.tcx.hir.get(node_id) { + let node_id = self.tcx.hir().as_local_node_id(def_id).unwrap(); + if let Some((id, span, name)) = match self.tcx.hir().get(node_id) { Node::Lifetime(hir_lifetime) => Some(( hir_lifetime.id, hir_lifetime.span, @@ -1651,7 +1651,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { &format!("lifetime parameter `{}` never used", name), ); if let Some(parent_def_id) = self.tcx.parent(def_id) { - if let Some(generics) = self.tcx.hir.get_generics(parent_def_id) { + if let Some(generics) = self.tcx.hir().get_generics(parent_def_id) { let unused_lt_span = self.lifetime_deletion_span(name, generics); if let Some(span) = unused_lt_span { err.span_suggestion_with_applicability( @@ -1699,10 +1699,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { { insert_late_bound_lifetimes(self.map, decl, generics); - // Find the start of nested early scopes, e.g. in methods. + // Find the start of nested early scopes, e.g., in methods. let mut index = 0; if let Some(parent_id) = parent_id { - let parent = self.tcx.hir.expect_item(parent_id); + let parent = self.tcx.hir().expect_item(parent_id); if sub_items_have_self_param(&parent.node) { index += 1; // Self comes before lifetimes } @@ -1722,9 +1722,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { .filter_map(|param| match param.kind { GenericParamKind::Lifetime { .. } => { if self.map.late_bound.contains(¶m.id) { - Some(Region::late(&self.tcx.hir, param)) + Some(Region::late(&self.tcx.hir(), param)) } else { - Some(Region::early(&self.tcx.hir, &mut index, param)) + Some(Region::early(&self.tcx.hir(), &mut index, param)) } } GenericParamKind::Type { .. } => { @@ -1837,8 +1837,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { if let Region::EarlyBound(..) = def { // Do not free early-bound regions, only late-bound ones. } else if let Some(body_id) = outermost_body { - let fn_id = self.tcx.hir.body_owner(body_id); - match self.tcx.hir.get(fn_id) { + let fn_id = self.tcx.hir().body_owner(body_id); + match self.tcx.hir().get(fn_id) { Node::Item(&hir::Item { node: hir::ItemKind::Fn(..), .. @@ -1851,7 +1851,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { node: hir::ImplItemKind::Method(..), .. }) => { - let scope = self.tcx.hir.local_def_id(fn_id); + let scope = self.tcx.hir().local_def_id(fn_id); def = Region::Free(scope, def.id().unwrap()); } _ => {} @@ -1967,7 +1967,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { }; let map = &self.map; - let unsubst = if let Some(id) = self.tcx.hir.as_local_node_id(def_id) { + let unsubst = if let Some(id) = self.tcx.hir().as_local_node_id(def_id) { &map.object_lifetime_defaults[&id] } else { let tcx = self.tcx; @@ -2061,8 +2061,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { // and whether there's a `self` argument (treated specially). let mut assoc_item_kind = None; let mut impl_self = None; - let parent = self.tcx.hir.get_parent_node(output.id); - let body = match self.tcx.hir.get(parent) { + let parent = self.tcx.hir().get_parent_node(output.id); + let body = match self.tcx.hir().get(parent) { // `fn` definitions and methods. Node::Item(&hir::Item { node: hir::ItemKind::Fn(.., body), @@ -2074,8 +2074,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { .. }) => { if let hir::ItemKind::Trait(.., ref trait_items) = self.tcx - .hir - .expect_item(self.tcx.hir.get_parent(parent)) + .hir() + .expect_item(self.tcx.hir().get_parent(parent)) .node { assoc_item_kind = trait_items @@ -2094,8 +2094,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { .. }) => { if let hir::ItemKind::Impl(.., ref self_ty, ref impl_items) = self.tcx - .hir - .expect_item(self.tcx.hir.get_parent(parent)) + .hir() + .expect_item(self.tcx.hir().get_parent(parent)) .node { impl_self = Some(self_ty); @@ -2396,8 +2396,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } = info; let help_name = if let Some(body) = parent { - let arg = &self.tcx.hir.body(body).arguments[index]; - format!("`{}`", self.tcx.hir.node_to_pretty_string(arg.pat.id)) + let arg = &self.tcx.hir().body(body).arguments[index]; + format!("`{}`", self.tcx.hir().node_to_pretty_string(arg.pat.id)) } else { format!("argument {}", index + 1) }; @@ -2603,12 +2603,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { ref lifetimes, s, .. } => { if let Some(&def) = lifetimes.get(¶m.name.modern()) { - let node_id = self.tcx.hir.as_local_node_id(def.id().unwrap()).unwrap(); + let node_id = self.tcx.hir().as_local_node_id(def.id().unwrap()).unwrap(); signal_shadowing_problem( self.tcx, param.name.ident().name, - original_lifetime(self.tcx.hir.span(node_id)), + original_lifetime(self.tcx.hir().span(node_id)), shadower_lifetime(¶m), ); return; @@ -2675,7 +2675,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { debug!( "insert_lifetime: {} resolved to {:?} span={:?}", - self.tcx.hir.node_to_string(lifetime_ref.id), + self.tcx.hir().node_to_string(lifetime_ref.id), def, self.tcx.sess.source_map().span_to_string(lifetime_ref.span) ); diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 543d1053b55..61341cbc30c 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -13,10 +13,11 @@ pub use self::StabilityLevel::*; -use lint; +use lint::{self, Lint}; +use hir::{self, Item, Generics, StructField, Variant, HirId}; use hir::def::Def; use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE}; -use ty::{self, TyCtxt}; +use hir::intravisit::{self, Visitor, NestedVisitorMap}; use middle::privacy::AccessLevels; use session::{DiagnosticMessageId, Session}; use syntax::symbol::Symbol; @@ -25,12 +26,9 @@ use syntax::ast; use syntax::ast::{NodeId, Attribute}; use syntax::feature_gate::{GateIssue, emit_feature_err}; use syntax::attr::{self, Stability, Deprecation}; +use ty::{self, TyCtxt}; use util::nodemap::{FxHashSet, FxHashMap}; -use hir; -use hir::{Item, Generics, StructField, Variant, HirId}; -use hir::intravisit::{self, Visitor, NestedVisitorMap}; - use std::mem::replace; use std::cmp::Ordering; @@ -188,7 +186,7 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> { } } - let hir_id = self.tcx.hir.node_to_hir_id(id); + let hir_id = self.tcx.hir().node_to_hir_id(id); self.index.stab_map.insert(hir_id, stab); let orig_parent_stab = replace(&mut self.parent_stab, Some(stab)); @@ -198,7 +196,7 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> { debug!("annotate: not found, parent = {:?}", self.parent_stab); if let Some(stab) = self.parent_stab { if stab.level.is_unstable() { - let hir_id = self.tcx.hir.node_to_hir_id(id); + let hir_id = self.tcx.hir().node_to_hir_id(id); self.index.stab_map.insert(hir_id, stab); } } @@ -219,7 +217,7 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> { // -Zforce-unstable-if-unmarked is set. if let Some(stab) = self.parent_stab { if stab.level.is_unstable() { - let hir_id = self.tcx.hir.node_to_hir_id(id); + let hir_id = self.tcx.hir().node_to_hir_id(id); self.index.stab_map.insert(hir_id, stab); } } @@ -230,7 +228,7 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> { } // `Deprecation` is just two pointers, no need to intern it - let hir_id = self.tcx.hir.node_to_hir_id(id); + let hir_id = self.tcx.hir().node_to_hir_id(id); let depr_entry = DeprecationEntry::local(depr, hir_id); self.index.depr_map.insert(hir_id, depr_entry.clone()); @@ -239,7 +237,7 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> { visit_children(self); self.parent_depr = orig_parent_depr; } else if let Some(parent_depr) = self.parent_depr.clone() { - let hir_id = self.tcx.hir.node_to_hir_id(id); + let hir_id = self.tcx.hir().node_to_hir_id(id); self.index.depr_map.insert(hir_id, parent_depr); visit_children(self); } else { @@ -254,7 +252,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { /// nested items in the context of the outer item, so enable /// deep-walking. fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::All(&self.tcx.hir) + NestedVisitorMap::All(&self.tcx.hir()) } fn visit_item(&mut self, i: &'tcx Item) { @@ -333,7 +331,7 @@ struct MissingStabilityAnnotations<'a, 'tcx: 'a> { impl<'a, 'tcx: 'a> MissingStabilityAnnotations<'a, 'tcx> { fn check_missing_stability(&self, id: NodeId, span: Span) { - let hir_id = self.tcx.hir.node_to_hir_id(id); + let hir_id = self.tcx.hir().node_to_hir_id(id); let stab = self.tcx.stability().local_stability(hir_id); let is_error = !self.tcx.sess.opts.test && stab.is_none() && @@ -346,7 +344,7 @@ impl<'a, 'tcx: 'a> MissingStabilityAnnotations<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir) + NestedVisitorMap::OnlyBodies(&self.tcx.hir()) } fn visit_item(&mut self, i: &'tcx Item) { @@ -369,7 +367,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> { } fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) { - let impl_def_id = self.tcx.hir.local_def_id(self.tcx.hir.get_parent(ii.id)); + let impl_def_id = self.tcx.hir().local_def_id(self.tcx.hir().get_parent(ii.id)); if self.tcx.impl_trait_ref(impl_def_id).is_none() { self.check_missing_stability(ii.id, ii.span); } @@ -416,7 +414,7 @@ impl<'a, 'tcx> Index<'tcx> { index.active_features = active_lib_features.iter().map(|&(ref s, _)| s.clone()).collect(); { - let krate = tcx.hir.krate(); + let krate = tcx.hir().krate(); let mut annotator = Annotator { tcx, index: &mut index, @@ -470,14 +468,14 @@ impl<'a, 'tcx> Index<'tcx> { /// features and possibly prints errors. pub fn check_unstable_api_usage<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let mut checker = Checker { tcx }; - tcx.hir.krate().visit_all_item_likes(&mut checker.as_deep_visitor()); + tcx.hir().krate().visit_all_item_likes(&mut checker.as_deep_visitor()); } /// Check whether an item marked with `deprecated(since="X")` is currently -/// deprecated (i.e. whether X is not greater than the current rustc version). +/// deprecated (i.e., whether X is not greater than the current rustc version). pub fn deprecation_in_effect(since: &str) -> bool { fn parse_version(ver: &str) -> Vec { - // We ignore non-integer components of the version (e.g. "nightly"). + // We ignore non-integer components of the version (e.g., "nightly"). ver.split(|c| c == '.' || c == '-').flat_map(|s| s.parse()).collect() } @@ -518,7 +516,7 @@ pub enum EvalResult { } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { - // (See issue #38412) + // See issue #38412. fn skip_stability_check_due_to_privacy(self, mut def_id: DefId) -> bool { // Check if `def_id` is a trait method. match self.describe_def(def_id) { @@ -528,8 +526,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { if let ty::TraitContainer(trait_def_id) = self.associated_item(def_id).container { // Trait methods do not declare visibility (even // for visibility info in cstore). Use containing - // trait instead, so methods of pub traits are - // themselves considered pub. + // trait instead, so methods of `pub` traits are + // themselves considered `pub`. def_id = trait_def_id; } } @@ -539,10 +537,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let visibility = self.visibility(def_id); match visibility { - // must check stability for pub items. + // Must check stability for `pub` items. ty::Visibility::Public => false, - // these are not visible outside crate; therefore + // These are not visible outside crate; therefore // stability markers are irrelevant, if even present. ty::Visibility::Restricted(..) | ty::Visibility::Invisible => true, @@ -564,18 +562,20 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { return EvalResult::Allow; } - let lint_deprecated = |def_id: DefId, id: NodeId, note: Option| { - let path = self.item_path_str(def_id); - + let lint_deprecated = |def_id: DefId, + id: NodeId, + note: Option, + message: &str, + lint: &'static Lint| { let msg = if let Some(note) = note { - format!("use of deprecated item '{}': {}", path, note) + format!("{}: {}", message, note) } else { - format!("use of deprecated item '{}'", path) + format!("{}", message) }; - self.lint_node(lint::builtin::DEPRECATED, id, span, &msg); + self.lint_node(lint, id, span, &msg); if id == ast::DUMMY_NODE_ID { - span_bug!(span, "emitted a deprecated lint with dummy node id: {:?}", def_id); + span_bug!(span, "emitted a {} lint with dummy node id: {:?}", lint.name, def_id); } }; @@ -586,17 +586,39 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // version, then we should display no warning message. let deprecated_in_future_version = if let Some(sym) = depr_entry.attr.since { let since = sym.as_str(); - !deprecation_in_effect(&since) + if !deprecation_in_effect(&since) { + Some(since) + } else { + None + } } else { - false + None }; - let parent_def_id = self.hir.local_def_id(self.hir.get_parent(id)); - let skip = deprecated_in_future_version || - self.lookup_deprecation_entry(parent_def_id) + let parent_def_id = self.hir().local_def_id(self.hir().get_parent(id)); + let skip = self.lookup_deprecation_entry(parent_def_id) .map_or(false, |parent_depr| parent_depr.same_origin(&depr_entry)); - if !skip { - lint_deprecated(def_id, id, depr_entry.attr.note); + + if let Some(since) = deprecated_in_future_version { + let path = self.item_path_str(def_id); + let message = format!("use of item '{}' \ + that will be deprecated in future version {}", + path, + since); + + lint_deprecated(def_id, + id, + depr_entry.attr.note, + &message, + lint::builtin::DEPRECATED_IN_FUTURE); + } else if !skip { + let path = self.item_path_str(def_id); + let message = format!("use of deprecated item '{}'", path); + lint_deprecated(def_id, + id, + depr_entry.attr.note, + &message, + lint::builtin::DEPRECATED); } }; } @@ -616,8 +638,24 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { if let Some(&Stability{rustc_depr: Some(attr::RustcDeprecation { reason, since }), ..}) = stability { if let Some(id) = id { + let path = self.item_path_str(def_id); if deprecation_in_effect(&since.as_str()) { - lint_deprecated(def_id, id, Some(reason)); + let message = format!("use of deprecated item '{}'", path); + lint_deprecated(def_id, + id, + Some(reason), + &message, + lint::builtin::DEPRECATED); + } else { + let message = format!("use of item '{}' \ + that will be deprecated in future version {}", + path, + since); + lint_deprecated(def_id, + id, + Some(reason), + &message, + lint::builtin::DEPRECATED_IN_FUTURE); } } } @@ -628,7 +666,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { return EvalResult::Allow; } - // Issue 38412: private items lack stability markers. + // Issue #38412: private items lack stability markers. if self.skip_stability_check_due_to_privacy(def_id) { return EvalResult::Allow; } @@ -644,7 +682,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // crates also pulled in from crates.io. We want to ideally be // able to compile everything without requiring upstream // modifications, so in the case that this looks like a - // rustc_private crate (e.g. a compiler crate) and we also have + // `rustc_private` crate (e.g., a compiler crate) and we also have // the `-Z force-unstable-if-unmarked` flag present (we're // compiling a compiler crate), then let this missing feature // annotation slide. @@ -717,7 +755,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { /// nested items in the context of the outer item, so enable /// deep-walking. fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir) + NestedVisitorMap::OnlyBodies(&self.tcx.hir()) } fn visit_item(&mut self, item: &'tcx hir::Item) { @@ -726,7 +764,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { // compiler-generated `extern crate` items have a dummy span. if item.span.is_dummy() { return } - let def_id = self.tcx.hir.local_def_id(item.id); + let def_id = self.tcx.hir().local_def_id(item.id); let cnum = match self.tcx.extern_mod_stmt_cnum(def_id) { Some(cnum) => cnum, None => return, @@ -741,7 +779,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { hir::ItemKind::Impl(.., Some(ref t), _, ref impl_item_refs) => { if let Def::Trait(trait_did) = t.path.def { for impl_item_ref in impl_item_refs { - let impl_item = self.tcx.hir.impl_item(impl_item_ref.id); + let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); let trait_item_def_id = self.tcx.associated_items(trait_did) .find(|item| item.ident.name == impl_item.ident.name) .map(|item| item.def_id); @@ -756,7 +794,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { // There's no good place to insert stability check for non-Copy unions, // so semi-randomly perform it here in stability.rs hir::ItemKind::Union(..) if !self.tcx.features().untagged_unions => { - let def_id = self.tcx.hir.local_def_id(item.id); + let def_id = self.tcx.hir().local_def_id(item.id); let adt_def = self.tcx.adt_def(def_id); let ty = self.tcx.type_of(def_id); @@ -780,7 +818,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { } fn visit_path(&mut self, path: &'tcx hir::Path, id: hir::HirId) { - let id = self.tcx.hir.hir_to_node_id(id); + let id = self.tcx.hir().hir_to_node_id(id); if let Some(def_id) = path.def.opt_def_id() { self.tcx.check_stability(def_id, Some(id), path.span) } @@ -794,14 +832,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } -/// Given the list of enabled features that were not language features (i.e. that +/// Given the list of enabled features that were not language features (i.e., that /// were expected to be library features), and the list of features used from /// libraries, identify activated features that don't exist and error about them. pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE); if tcx.stability().staged_api[&LOCAL_CRATE] { - let krate = tcx.hir.krate(); + let krate = tcx.hir().krate(); let mut missing = MissingStabilityAnnotations { tcx, access_levels, diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs index 0d407765c9e..824ccda3dbd 100644 --- a/src/librustc/middle/weak_lang_items.rs +++ b/src/librustc/middle/weak_lang_items.rs @@ -49,7 +49,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, { let mut cx = Context { tcx, items }; - tcx.hir.krate().visit_all_item_likes(&mut cx.as_deep_visitor()); + tcx.hir().krate().visit_all_item_likes(&mut cx.as_deep_visitor()); } verify(tcx, items); } diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 503e0abdbf3..8b16aafd314 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -183,50 +183,14 @@ pub struct EvalError<'tcx> { impl<'tcx> EvalError<'tcx> { pub fn print_backtrace(&mut self) { if let Some(ref mut backtrace) = self.backtrace { - eprintln!("{}", print_backtrace(&mut *backtrace)); + print_backtrace(&mut *backtrace); } } } -fn print_backtrace(backtrace: &mut Backtrace) -> String { - use std::fmt::Write; - +fn print_backtrace(backtrace: &mut Backtrace) { backtrace.resolve(); - - let mut trace_text = "\n\nAn error occurred in miri:\n".to_string(); - write!(trace_text, "backtrace frames: {}\n", backtrace.frames().len()).unwrap(); - 'frames: for (i, frame) in backtrace.frames().iter().enumerate() { - if frame.symbols().is_empty() { - write!(trace_text, " {}: no symbols\n", i).unwrap(); - } - let mut first = true; - for symbol in frame.symbols() { - if first { - write!(trace_text, " {}: ", i).unwrap(); - first = false; - } else { - let len = i.to_string().len(); - write!(trace_text, " {} ", " ".repeat(len)).unwrap(); - } - if let Some(name) = symbol.name() { - write!(trace_text, "{}\n", name).unwrap(); - } else { - write!(trace_text, "\n").unwrap(); - } - write!(trace_text, " at ").unwrap(); - if let Some(file_path) = symbol.filename() { - write!(trace_text, "{}", file_path.display()).unwrap(); - } else { - write!(trace_text, "").unwrap(); - } - if let Some(line) = symbol.lineno() { - write!(trace_text, ":{}\n", line).unwrap(); - } else { - write!(trace_text, "\n").unwrap(); - } - } - } - trace_text + eprintln!("\n\nAn error occurred in miri:\n{:?}", backtrace); } impl<'tcx> From> for EvalError<'tcx> { @@ -238,7 +202,7 @@ impl<'tcx> From> for EvalError<'tcx> { if val == "immediate" { // Print it now - eprintln!("{}", print_backtrace(&mut backtrace)); + print_backtrace(&mut backtrace); None } else { Some(Box::new(backtrace)) @@ -378,7 +342,7 @@ impl<'tcx, O> EvalErrorKind<'tcx, O> { "tried to read from foreign (extern) static", InvalidPointerMath => "attempted to do invalid arithmetic on pointers that would leak base addresses, \ - e.g. comparing pointers into different allocations", + e.g., comparing pointers into different allocations", ReadUndefBytes(_) => "attempted to read undefined bytes", DeadLocal => diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index 9369b6e56f1..d54a1c9bb82 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -41,7 +41,6 @@ use ty::{self, TyCtxt, Instance}; use ty::layout::{self, Size}; use middle::region; use std::io; -use std::hash::Hash; use rustc_serialize::{Encoder, Decodable, Encodable}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::{Lock as Mutex, HashMapExt}; @@ -90,7 +89,7 @@ impl ::rustc_serialize::UseSpecializedEncodable for AllocId {} impl ::rustc_serialize::UseSpecializedDecodable for AllocId {} #[derive(RustcDecodable, RustcEncodable)] -enum AllocKind { +enum AllocDiscriminant { Alloc, Fn, Static, @@ -104,23 +103,23 @@ pub fn specialized_encode_alloc_id< tcx: TyCtxt<'a, 'tcx, 'tcx>, alloc_id: AllocId, ) -> Result<(), E::Error> { - let alloc_type: AllocType<'tcx, &'tcx Allocation> = + let alloc_kind: AllocKind<'tcx> = tcx.alloc_map.lock().get(alloc_id).expect("no value for AllocId"); - match alloc_type { - AllocType::Memory(alloc) => { + match alloc_kind { + AllocKind::Memory(alloc) => { trace!("encoding {:?} with {:#?}", alloc_id, alloc); - AllocKind::Alloc.encode(encoder)?; + AllocDiscriminant::Alloc.encode(encoder)?; alloc.encode(encoder)?; } - AllocType::Function(fn_instance) => { + AllocKind::Function(fn_instance) => { trace!("encoding {:?} with {:#?}", alloc_id, fn_instance); - AllocKind::Fn.encode(encoder)?; + AllocDiscriminant::Fn.encode(encoder)?; fn_instance.encode(encoder)?; } - AllocType::Static(did) => { + AllocKind::Static(did) => { // referring to statics doesn't need to know about their allocations, // just about its DefId - AllocKind::Static.encode(encoder)?; + AllocDiscriminant::Static.encode(encoder)?; did.encode(encoder)?; } } @@ -189,10 +188,10 @@ impl<'s> AllocDecodingSession<'s> { let idx = decoder.read_u32()? as usize; let pos = self.state.data_offsets[idx] as usize; - // Decode the AllocKind now so that we know if we have to reserve an + // Decode the AllocDiscriminant now so that we know if we have to reserve an // AllocId. let (alloc_kind, pos) = decoder.with_position(pos, |decoder| { - let alloc_kind = AllocKind::decode(decoder)?; + let alloc_kind = AllocDiscriminant::decode(decoder)?; Ok((alloc_kind, decoder.position())) })?; @@ -208,7 +207,7 @@ impl<'s> AllocDecodingSession<'s> { ref mut entry @ State::Empty => { // We are allowed to decode match alloc_kind { - AllocKind::Alloc => { + AllocDiscriminant::Alloc => { // If this is an allocation, we need to reserve an // AllocId so we can decode cyclic graphs. let alloc_id = decoder.tcx().alloc_map.lock().reserve(); @@ -217,7 +216,7 @@ impl<'s> AllocDecodingSession<'s> { alloc_id); Some(alloc_id) }, - AllocKind::Fn | AllocKind::Static => { + AllocDiscriminant::Fn | AllocDiscriminant::Static => { // Fns and statics cannot be cyclic and their AllocId // is determined later by interning *entry = State::InProgressNonAlloc( @@ -251,15 +250,15 @@ impl<'s> AllocDecodingSession<'s> { // Now decode the actual data let alloc_id = decoder.with_position(pos, |decoder| { match alloc_kind { - AllocKind::Alloc => { + AllocDiscriminant::Alloc => { let allocation = <&'tcx Allocation as Decodable>::decode(decoder)?; // We already have a reserved AllocId. let alloc_id = alloc_id.unwrap(); trace!("decoded alloc {:?} {:#?}", alloc_id, allocation); - decoder.tcx().alloc_map.lock().set_id_same_memory(alloc_id, allocation); + decoder.tcx().alloc_map.lock().set_alloc_id_same_memory(alloc_id, allocation); Ok(alloc_id) }, - AllocKind::Fn => { + AllocDiscriminant::Fn => { assert!(alloc_id.is_none()); trace!("creating fn alloc id"); let instance = ty::Instance::decode(decoder)?; @@ -267,7 +266,7 @@ impl<'s> AllocDecodingSession<'s> { let alloc_id = decoder.tcx().alloc_map.lock().create_fn_alloc(instance); Ok(alloc_id) }, - AllocKind::Static => { + AllocDiscriminant::Static => { assert!(alloc_id.is_none()); trace!("creating extern static alloc id at"); let did = DefId::decode(decoder)?; @@ -292,39 +291,42 @@ impl fmt::Display for AllocId { } #[derive(Debug, Clone, Eq, PartialEq, Hash, RustcDecodable, RustcEncodable)] -pub enum AllocType<'tcx, M> { +pub enum AllocKind<'tcx> { /// The alloc id is used as a function pointer Function(Instance<'tcx>), /// The alloc id points to a "lazy" static variable that did not get computed (yet). /// This is also used to break the cycle in recursive statics. Static(DefId), /// The alloc id points to memory - Memory(M) + Memory(&'tcx Allocation), } -pub struct AllocMap<'tcx, M> { +pub struct AllocMap<'tcx> { /// Lets you know what an AllocId refers to - id_to_type: FxHashMap>, + id_to_kind: FxHashMap>, - /// Used to ensure that functions and statics only get one associated AllocId - type_interner: FxHashMap, AllocId>, + /// Used to ensure that statics only get one associated AllocId + type_interner: FxHashMap, AllocId>, /// The AllocId to assign to the next requested id. /// Always incremented, never gets smaller. next_id: AllocId, } -impl<'tcx, M: fmt::Debug + Eq + Hash + Clone> AllocMap<'tcx, M> { +impl<'tcx> AllocMap<'tcx> { pub fn new() -> Self { AllocMap { - id_to_type: Default::default(), + id_to_kind: Default::default(), type_interner: Default::default(), next_id: AllocId(0), } } - /// obtains a new allocation ID that can be referenced but does not + /// Obtains a new allocation ID that can be referenced but does not /// yet have an allocation backing it. + /// + /// Make sure to call `set_alloc_id_memory` or `set_alloc_id_same_memory` before returning such + /// an `AllocId` from a query. pub fn reserve( &mut self, ) -> AllocId { @@ -337,53 +339,73 @@ impl<'tcx, M: fmt::Debug + Eq + Hash + Clone> AllocMap<'tcx, M> { next } - fn intern(&mut self, alloc_type: AllocType<'tcx, M>) -> AllocId { - if let Some(&alloc_id) = self.type_interner.get(&alloc_type) { + fn intern(&mut self, alloc_kind: AllocKind<'tcx>) -> AllocId { + if let Some(&alloc_id) = self.type_interner.get(&alloc_kind) { return alloc_id; } let id = self.reserve(); - debug!("creating alloc_type {:?} with id {}", alloc_type, id); - self.id_to_type.insert(id, alloc_type.clone()); - self.type_interner.insert(alloc_type, id); + debug!("creating alloc_kind {:?} with id {}", alloc_kind, id); + self.id_to_kind.insert(id, alloc_kind.clone()); + self.type_interner.insert(alloc_kind, id); id } - // FIXME: Check if functions have identity. If not, we should not intern these, - // but instead create a new id per use. - // Alternatively we could just make comparing function pointers an error. + /// Functions cannot be identified by pointers, as asm-equal functions can get deduplicated + /// by the linker and functions can be duplicated across crates. + /// We thus generate a new `AllocId` for every mention of a function. This means that + /// `main as fn() == main as fn()` is false, while `let x = main as fn(); x == x` is true. pub fn create_fn_alloc(&mut self, instance: Instance<'tcx>) -> AllocId { - self.intern(AllocType::Function(instance)) + let id = self.reserve(); + self.id_to_kind.insert(id, AllocKind::Function(instance)); + id } - pub fn get(&self, id: AllocId) -> Option> { - self.id_to_type.get(&id).cloned() + /// Returns `None` in case the `AllocId` is dangling. An `EvalContext` can still have a + /// local `Allocation` for that `AllocId`, but having such an `AllocId` in a constant is + /// illegal and will likely ICE. + /// This function exists to allow const eval to detect the difference between evaluation- + /// local dangling pointers and allocations in constants/statics. + pub fn get(&self, id: AllocId) -> Option> { + self.id_to_kind.get(&id).cloned() } - pub fn unwrap_memory(&self, id: AllocId) -> M { + /// Panics if the `AllocId` does not refer to an `Allocation` + pub fn unwrap_memory(&self, id: AllocId) -> &'tcx Allocation { match self.get(id) { - Some(AllocType::Memory(mem)) => mem, + Some(AllocKind::Memory(mem)) => mem, _ => bug!("expected allocation id {} to point to memory", id), } } + /// Generate an `AllocId` for a static or return a cached one in case this function has been + /// called on the same static before. pub fn intern_static(&mut self, static_id: DefId) -> AllocId { - self.intern(AllocType::Static(static_id)) + self.intern(AllocKind::Static(static_id)) } - pub fn allocate(&mut self, mem: M) -> AllocId { + /// Intern the `Allocation` and return a new `AllocId`, even if there's already an identical + /// `Allocation` with a different `AllocId`. + // FIXME: is this really necessary? Can we ensure `FOO` and `BAR` being different after codegen + // in `static FOO: u32 = 42; static BAR: u32 = 42;` even if they reuse the same allocation + // inside rustc? + pub fn allocate(&mut self, mem: &'tcx Allocation) -> AllocId { let id = self.reserve(); - self.set_id_memory(id, mem); + self.set_alloc_id_memory(id, mem); id } - pub fn set_id_memory(&mut self, id: AllocId, mem: M) { - if let Some(old) = self.id_to_type.insert(id, AllocType::Memory(mem)) { + /// Freeze an `AllocId` created with `reserve` by pointing it at an `Allocation`. Trying to + /// call this function twice, even with the same `Allocation` will ICE the compiler. + pub fn set_alloc_id_memory(&mut self, id: AllocId, mem: &'tcx Allocation) { + if let Some(old) = self.id_to_kind.insert(id, AllocKind::Memory(mem)) { bug!("tried to set allocation id {}, but it was already existing as {:#?}", id, old); } } - pub fn set_id_same_memory(&mut self, id: AllocId, mem: M) { - self.id_to_type.insert_same(id, AllocType::Memory(mem)); + /// Freeze an `AllocId` created with `reserve` by pointing it at an `Allocation`. May be called + /// twice for the same `(AllocId, Allocation)` pair. + fn set_alloc_id_same_memory(&mut self, id: AllocId, mem: &'tcx Allocation) { + self.id_to_kind.insert_same(id, AllocKind::Memory(mem)); } } diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index 4bcba9d5467..b8d4c5a3751 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -18,7 +18,7 @@ use super::{EvalResult, Pointer, PointerArithmetic, Allocation, AllocId, sign_ex /// Represents the result of a raw const operation, pre-validation. #[derive(Copy, Clone, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Hash)] pub struct RawConst<'tcx> { - // the value lives here, at offset 0, and that allocation definitely is a `AllocType::Memory` + // the value lives here, at offset 0, and that allocation definitely is a `AllocKind::Memory` // (so you can use `AllocMap::unwrap_memory`). pub alloc_id: AllocId, pub ty: Ty<'tcx>, @@ -138,6 +138,14 @@ impl<'tcx, Tag> Scalar { } } + #[inline] + pub fn with_tag(self, new_tag: Tag) -> Self { + match self { + Scalar::Ptr(ptr) => Scalar::Ptr(Pointer { tag: new_tag, ..ptr }), + Scalar::Bits { bits, size } => Scalar::Bits { bits, size }, + } + } + #[inline] pub fn ptr_null(cx: &impl HasDataLayout) -> Self { Scalar::Bits { diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 368f83eb611..dc14450e8d2 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -25,7 +25,7 @@ use rustc_data_structures::graph::{self, GraphPredecessors, GraphSuccessors}; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::MappedReadGuard; -use rustc_serialize as serialize; +use rustc_serialize::{self as serialize}; use smallvec::SmallVec; use std::borrow::Cow; use std::fmt::{self, Debug, Formatter, Write}; @@ -149,6 +149,14 @@ pub struct Mir<'tcx> { /// This is used for the "rust-call" ABI. pub spread_arg: Option, + /// Mark this MIR of a const context other than const functions as having converted a `&&` or + /// `||` expression into `&` or `|` respectively. This is problematic because if we ever stop + /// this conversion from happening and use short circuiting, we will cause the following code + /// to change the value of `x`: `let mut x = 42; false && { x = 55; true };` + /// + /// List of places where control flow was destroyed. Used for error reporting. + pub control_flow_destroyed: Vec<(Span, String)>, + /// A span representing this MIR, for error reporting pub span: Span, @@ -167,6 +175,7 @@ impl<'tcx> Mir<'tcx> { arg_count: usize, upvar_decls: Vec, span: Span, + control_flow_destroyed: Vec<(Span, String)>, ) -> Self { // We need `arg_count` locals, and one for the return place assert!( @@ -191,6 +200,7 @@ impl<'tcx> Mir<'tcx> { spread_arg: None, span, cache: cache::Cache::new(), + control_flow_destroyed, } } @@ -339,7 +349,7 @@ impl<'tcx> Mir<'tcx> { #[inline] pub fn args_iter(&self) -> impl Iterator { let arg_count = self.arg_count; - (1..arg_count + 1).map(Local::new) + (1..=arg_count).map(Local::new) } /// Returns an iterator over all user-defined variables and compiler-generated temporaries (all @@ -421,6 +431,7 @@ impl_stable_hash_for!(struct Mir<'tcx> { arg_count, upvar_decls, spread_arg, + control_flow_destroyed, span, cache }); @@ -556,7 +567,7 @@ pub enum BorrowKind { /// Data is mutable and not aliasable. Mut { /// True if this borrow arose from method-call auto-ref - /// (i.e. `adjustment::Adjust::Borrow`) + /// (i.e., `adjustment::Adjust::Borrow`) allow_two_phase_borrow: bool, }, } @@ -692,7 +703,7 @@ mod binding_form_impl { /// expression; that is, a block like `{ STMT_1; STMT_2; EXPR }`. /// /// It is used to improve diagnostics when such temporaries are -/// involved in borrow_check errors, e.g. explanations of where the +/// involved in borrow_check errors, e.g., explanations of where the /// temporaries come from, when their destructors are run, and/or how /// one might revise the code to satisfy the borrow checker's rules. #[derive(Clone, Debug, RustcEncodable, RustcDecodable)] @@ -701,7 +712,7 @@ pub struct BlockTailInfo { /// expression is ignored by the block's expression context. /// /// Examples include `{ ...; tail };` and `let _ = { ...; tail };` - /// but not e.g. `let _x = { ...; tail };` + /// but not e.g., `let _x = { ...; tail };` pub tail_result_is_ignored: bool, } @@ -756,7 +767,7 @@ pub struct LocalDecl<'tcx> { pub ty: Ty<'tcx>, /// If the user manually ascribed a type to this variable, - /// e.g. via `let x: T`, then we carry that type here. The MIR + /// e.g., via `let x: T`, then we carry that type here. The MIR /// borrow checker needs this information since it can affect /// region inference. pub user_ty: UserTypeProjections<'tcx>, @@ -767,7 +778,7 @@ pub struct LocalDecl<'tcx> { /// to generate better debuginfo. pub name: Option, - /// The *syntactic* (i.e. not visibility) source scope the local is defined + /// The *syntactic* (i.e., not visibility) source scope the local is defined /// in. If the local was defined in a let-statement, this /// is *within* the let-statement, rather than outside /// of it. @@ -1745,9 +1756,12 @@ pub enum StatementKind<'tcx> { Assign(Place<'tcx>, Box>), /// This represents all the reading that a pattern match may do - /// (e.g. inspecting constants and discriminant values), and the + /// (e.g., inspecting constants and discriminant values), and the /// kind of pattern it comes from. This is in order to adapt potential /// error messages to these specific patterns. + /// + /// Note that this also is emitted for regular `let` bindings to ensure that locals that are + /// never accessed still get some sanity checks for e.g. `let x: ! = ..;` FakeRead(FakeReadCause, Place<'tcx>), /// Write the discriminant for a variant to the enum Place. @@ -1774,19 +1788,7 @@ pub enum StatementKind<'tcx> { /// by miri and only generated when "-Z mir-emit-retag" is passed. /// See /// for more details. - Retag { - /// `fn_entry` indicates whether this is the initial retag that happens in the - /// function prolog. - fn_entry: bool, - place: Place<'tcx>, - }, - - /// Escape the given reference to a raw pointer, so that it can be accessed - /// without precise provenance tracking. These statements are currently only interpreted - /// by miri and only generated when "-Z mir-emit-retag" is passed. - /// See - /// for more details. - EscapeToRaw(Operand<'tcx>), + Retag(RetagKind, Place<'tcx>), /// Encodes a user's type ascription. These need to be preserved /// intact so that NLL can respect them. For example: @@ -1806,6 +1808,19 @@ pub enum StatementKind<'tcx> { Nop, } +/// `RetagKind` describes what kind of retag is to be performed. +#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, PartialEq, Eq)] +pub enum RetagKind { + /// The initial retag when entering a function + FnEntry, + /// Retag preparing for a two-phase borrow + TwoPhase, + /// Retagging raw pointers + Raw, + /// A "normal" retag + Default, +} + /// The `FakeReadCause` describes the type of pattern why a `FakeRead` statement exists. #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)] pub enum FakeReadCause { @@ -1841,9 +1856,16 @@ impl<'tcx> Debug for Statement<'tcx> { match self.kind { Assign(ref place, ref rv) => write!(fmt, "{:?} = {:?}", place, rv), FakeRead(ref cause, ref place) => write!(fmt, "FakeRead({:?}, {:?})", cause, place), - Retag { fn_entry, ref place } => - write!(fmt, "Retag({}{:?})", if fn_entry { "[fn entry] " } else { "" }, place), - EscapeToRaw(ref place) => write!(fmt, "EscapeToRaw({:?})", place), + Retag(ref kind, ref place) => + write!(fmt, "Retag({}{:?})", + match kind { + RetagKind::FnEntry => "[fn entry] ", + RetagKind::TwoPhase => "[2phase] ", + RetagKind::Raw => "[raw] ", + RetagKind::Default => "", + }, + place, + ), StorageLive(ref place) => write!(fmt, "StorageLive({:?})", place), StorageDead(ref place) => write!(fmt, "StorageDead({:?})", place), SetDiscriminant { @@ -2172,7 +2194,7 @@ pub enum Rvalue<'tcx> { /// Read the discriminant of an ADT. /// - /// Undefined (i.e. no effort is made to make it defined, but there’s no reason why it cannot + /// Undefined (i.e., no effort is made to make it defined, but there’s no reason why it cannot /// be defined to return, say, a 0) if ADT is not an enum. Discriminant(Place<'tcx>), @@ -2214,7 +2236,7 @@ pub enum AggregateKind<'tcx> { /// The second field is the variant index. It's equal to 0 for struct /// and union expressions. The fourth field is /// active field number and is present only for union expressions - /// -- e.g. for a union expression `SomeUnion { c: .. }`, the + /// -- e.g., for a union expression `SomeUnion { c: .. }`, the /// active field index would identity the field `c` Adt( &'tcx AdtDef, @@ -2368,17 +2390,17 @@ impl<'tcx> Debug for Rvalue<'tcx> { } AggregateKind::Closure(def_id, _) => ty::tls::with(|tcx| { - if let Some(node_id) = tcx.hir.as_local_node_id(def_id) { + if let Some(node_id) = tcx.hir().as_local_node_id(def_id) { let name = if tcx.sess.opts.debugging_opts.span_free_formats { format!("[closure@{:?}]", node_id) } else { - format!("[closure@{:?}]", tcx.hir.span(node_id)) + format!("[closure@{:?}]", tcx.hir().span(node_id)) }; let mut struct_fmt = fmt.debug_struct(&name); tcx.with_freevars(node_id, |freevars| { for (freevar, place) in freevars.iter().zip(places) { - let var_name = tcx.hir.name(freevar.var_id()); + let var_name = tcx.hir().name(freevar.var_id()); struct_fmt.field(&var_name.as_str(), place); } }); @@ -2390,13 +2412,13 @@ impl<'tcx> Debug for Rvalue<'tcx> { }), AggregateKind::Generator(def_id, _, _) => ty::tls::with(|tcx| { - if let Some(node_id) = tcx.hir.as_local_node_id(def_id) { - let name = format!("[generator@{:?}]", tcx.hir.span(node_id)); + if let Some(node_id) = tcx.hir().as_local_node_id(def_id) { + let name = format!("[generator@{:?}]", tcx.hir().span(node_id)); let mut struct_fmt = fmt.debug_struct(&name); tcx.with_freevars(node_id, |freevars| { for (freevar, place) in freevars.iter().zip(places) { - let var_name = tcx.hir.name(freevar.var_id()); + let var_name = tcx.hir().name(freevar.var_id()); struct_fmt.field(&var_name.as_str(), place); } struct_fmt.field("$state", &places[freevars.len()]); @@ -2629,7 +2651,7 @@ pub fn fmt_const_val(f: &mut impl Write, const_val: &ty::Const<'_>) -> fmt::Resu if let Ref(_, &ty::TyS { sty: Str, .. }, _) = ty.sty { return ty::tls::with(|tcx| { let alloc = tcx.alloc_map.lock().get(ptr.alloc_id); - if let Some(interpret::AllocType::Memory(alloc)) = alloc { + if let Some(interpret::AllocKind::Memory(alloc)) = alloc { assert_eq!(len as usize as u128, len); let slice = &alloc.bytes[(ptr.offset.bytes() as usize)..][..(len as usize)]; @@ -2770,8 +2792,11 @@ impl Location { #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub enum UnsafetyViolationKind { General, - /// unsafety is not allowed at all in min const fn - MinConstFn, + /// Right now function calls to `const unsafe fn` are only permitted behind a feature gate + /// Also, even `const unsafe fn` need an `unsafe` block to do the allowed operations. + GatedConstFnCall, + /// Permitted in const fn and regular fns + GeneralAndConstFn, ExternStatic(ast::NodeId), BorrowPacked(ast::NodeId), } @@ -2894,6 +2919,7 @@ pub struct ClosureOutlivesRequirement<'tcx> { #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] pub enum ConstraintCategory { Return, + Yield, UseAsConst, UseAsStatic, TypeAnnotation, @@ -2953,6 +2979,7 @@ CloneTypeFoldableAndLiftImpls! { SourceInfo, UpvarDecl, FakeReadCause, + RetagKind, SourceScope, SourceScopeData, SourceScopeLocalData, @@ -2972,6 +2999,7 @@ BraceStructTypeFoldableImpl! { arg_count, upvar_decls, spread_arg, + control_flow_destroyed, span, cache, } @@ -3019,8 +3047,7 @@ EnumTypeFoldableImpl! { (StatementKind::StorageLive)(a), (StatementKind::StorageDead)(a), (StatementKind::InlineAsm) { asm, outputs, inputs }, - (StatementKind::Retag) { fn_entry, place }, - (StatementKind::EscapeToRaw)(place), + (StatementKind::Retag)(kind, place), (StatementKind::AscribeUserType)(a, v, b), (StatementKind::Nop), } diff --git a/src/librustc/mir/mono.rs b/src/librustc/mir/mono.rs index ff2bf3d7807..c96cbd40efa 100644 --- a/src/librustc/mir/mono.rs +++ b/src/librustc/mir/mono.rs @@ -272,7 +272,7 @@ impl<'a, 'gcx: 'tcx, 'tcx: 'a> CodegenUnitNameBuilder<'a, 'gcx, 'tcx> { /// /// The '.' before `` makes sure that names with a special /// suffix can never collide with a name built out of regular Rust - /// identifiers (e.g. module paths). + /// identifiers (e.g., module paths). pub fn build_cgu_name(&mut self, cnum: CrateNum, components: I, diff --git a/src/librustc/mir/traversal.rs b/src/librustc/mir/traversal.rs index f3a0b7de903..4424ba0a4f7 100644 --- a/src/librustc/mir/traversal.rs +++ b/src/librustc/mir/traversal.rs @@ -253,7 +253,7 @@ impl<'a, 'tcx> Iterator for Postorder<'a, 'tcx> { /// ``` /// /// A reverse postorder traversal of this graph is either `A B C D` or `A C B D` -/// Note that for a graph containing no loops (i.e. A DAG), this is equivalent to +/// Note that for a graph containing no loops (i.e., A DAG), this is equivalent to /// a topological sort. /// /// Construction of a `ReversePostorder` traversal requires doing a full diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 0c9b06a8d8c..278a4dc1d87 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -33,7 +33,7 @@ use syntax_pos::Span; // in that circumstance. // // For the most part, we do not destructure things external to the -// MIR, e.g. types, spans, etc, but simply visit them and stop. This +// MIR, e.g., types, spans, etc, but simply visit them and stop. This // avoids duplication with other visitors like `TypeFoldable`. // // ## Updating @@ -153,10 +153,10 @@ macro_rules! make_mir_visitor { } fn visit_retag(&mut self, - fn_entry: & $($mutability)* bool, + kind: & $($mutability)* RetagKind, place: & $($mutability)* Place<'tcx>, location: Location) { - self.super_retag(fn_entry, place, location); + self.super_retag(kind, place, location); } fn visit_place(&mut self, @@ -384,9 +384,6 @@ macro_rules! make_mir_visitor { location ); } - StatementKind::EscapeToRaw(ref $($mutability)* op) => { - self.visit_operand(op, location); - } StatementKind::StorageLive(ref $($mutability)* local) => { self.visit_local( local, @@ -416,9 +413,9 @@ macro_rules! make_mir_visitor { self.visit_operand(input, location); } } - StatementKind::Retag { ref $($mutability)* fn_entry, - ref $($mutability)* place } => { - self.visit_retag(fn_entry, place, location); + StatementKind::Retag ( ref $($mutability)* kind, + ref $($mutability)* place ) => { + self.visit_retag(kind, place, location); } StatementKind::AscribeUserType( ref $($mutability)* place, @@ -723,7 +720,7 @@ macro_rules! make_mir_visitor { } fn super_retag(&mut self, - _fn_entry: & $($mutability)* bool, + _kind: & $($mutability)* RetagKind, place: & $($mutability)* Place<'tcx>, location: Location) { self.visit_place( @@ -994,7 +991,7 @@ pub enum NonMutatingUseContext<'tcx> { ShallowBorrow(Region<'tcx>), /// Unique borrow. UniqueBorrow(Region<'tcx>), - /// Used as base for another place, e.g. `x` in `x.y`. Will not mutate the place. + /// Used as base for another place, e.g., `x` in `x.y`. Will not mutate the place. /// For example, the projection `x.y` is not marked as a mutation in these cases: /// /// z = x.y; @@ -1017,7 +1014,7 @@ pub enum MutatingUseContext<'tcx> { Drop, /// Mutable borrow. Borrow(Region<'tcx>), - /// Used as base for another place, e.g. `x` in `x.y`. Could potentially mutate the place. + /// Used as base for another place, e.g., `x` in `x.y`. Could potentially mutate the place. /// For example, the projection `x.y` is marked as a mutation in these cases: /// /// x.y = ...; diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 480d4a8e48f..b58d80e2485 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -14,7 +14,7 @@ use std::str::FromStr; use session::{early_error, early_warn, Session}; -use session::search_paths::SearchPaths; +use session::search_paths::SearchPath; use rustc_target::spec::{LinkerFlavor, PanicStrategy, RelroLevel}; use rustc_target::spec::{Target, TargetTriple}; @@ -374,7 +374,7 @@ top_level_options!( lint_cap: Option [TRACKED], describe_lints: bool [UNTRACKED], output_types: OutputTypes [TRACKED], - search_paths: SearchPaths [UNTRACKED], + search_paths: Vec [UNTRACKED], libs: Vec<(String, Option, Option)> [TRACKED], maybe_sysroot: Option [TRACKED], @@ -593,7 +593,7 @@ impl Default for Options { lint_cap: None, describe_lints: false, output_types: OutputTypes(BTreeMap::new()), - search_paths: SearchPaths::new(), + search_paths: vec![], maybe_sysroot: None, target_triple: TargetTriple::from_triple(host_triple()), test: false, @@ -780,43 +780,42 @@ macro_rules! options { } pub type $setter_name = fn(&mut $struct_name, v: Option<&str>) -> bool; - pub const $stat: &'static [(&'static str, $setter_name, - Option<&'static str>, &'static str)] = + pub const $stat: &[(&str, $setter_name, Option<&str>, &str)] = &[ $( (stringify!($opt), $mod_set::$opt, $mod_desc::$parse, $desc) ),* ]; #[allow(non_upper_case_globals, dead_code)] mod $mod_desc { - pub const parse_bool: Option<&'static str> = None; - pub const parse_opt_bool: Option<&'static str> = + pub const parse_bool: Option<&str> = None; + pub const parse_opt_bool: Option<&str> = Some("one of: `y`, `yes`, `on`, `n`, `no`, or `off`"); - pub const parse_string: Option<&'static str> = Some("a string"); - pub const parse_string_push: Option<&'static str> = Some("a string"); - pub const parse_pathbuf_push: Option<&'static str> = Some("a path"); - pub const parse_opt_string: Option<&'static str> = Some("a string"); - pub const parse_opt_pathbuf: Option<&'static str> = Some("a path"); - pub const parse_list: Option<&'static str> = Some("a space-separated list of strings"); - pub const parse_opt_list: Option<&'static str> = Some("a space-separated list of strings"); - pub const parse_uint: Option<&'static str> = Some("a number"); - pub const parse_passes: Option<&'static str> = + pub const parse_string: Option<&str> = Some("a string"); + pub const parse_string_push: Option<&str> = Some("a string"); + pub const parse_pathbuf_push: Option<&str> = Some("a path"); + pub const parse_opt_string: Option<&str> = Some("a string"); + pub const parse_opt_pathbuf: Option<&str> = Some("a path"); + pub const parse_list: Option<&str> = Some("a space-separated list of strings"); + pub const parse_opt_list: Option<&str> = Some("a space-separated list of strings"); + pub const parse_uint: Option<&str> = Some("a number"); + pub const parse_passes: Option<&str> = Some("a space-separated list of passes, or `all`"); - pub const parse_opt_uint: Option<&'static str> = + pub const parse_opt_uint: Option<&str> = Some("a number"); - pub const parse_panic_strategy: Option<&'static str> = + pub const parse_panic_strategy: Option<&str> = Some("either `unwind` or `abort`"); - pub const parse_relro_level: Option<&'static str> = + pub const parse_relro_level: Option<&str> = Some("one of: `full`, `partial`, or `off`"); - pub const parse_sanitizer: Option<&'static str> = + pub const parse_sanitizer: Option<&str> = Some("one of: `address`, `leak`, `memory` or `thread`"); - pub const parse_linker_flavor: Option<&'static str> = + pub const parse_linker_flavor: Option<&str> = Some(::rustc_target::spec::LinkerFlavor::one_of()); - pub const parse_optimization_fuel: Option<&'static str> = + pub const parse_optimization_fuel: Option<&str> = Some("crate=integer"); - pub const parse_unpretty: Option<&'static str> = + pub const parse_unpretty: Option<&str> = Some("`string` or `string=string`"); - pub const parse_lto: Option<&'static str> = + pub const parse_lto: Option<&str> = Some("either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, \ `fat`, or omitted"); - pub const parse_cross_lang_lto: Option<&'static str> = + pub const parse_cross_lang_lto: Option<&str> = Some("either a boolean (`yes`, `no`, `on`, `off`, etc), \ or the path to the linker plugin"); } @@ -1136,6 +1135,8 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, "enable incremental compilation"), default_linker_libraries: Option = (None, parse_opt_bool, [UNTRACKED], "allow the linker to link its default libraries"), + linker_flavor: Option = (None, parse_linker_flavor, [UNTRACKED], + "Linker flavor"), } options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, @@ -1273,7 +1274,13 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, arg_align_attributes: bool = (false, parse_bool, [TRACKED], "emit align metadata for reference arguments"), dump_mir: Option = (None, parse_opt_string, [UNTRACKED], - "dump MIR state at various points in transforms"), + "dump MIR state to file. + `val` is used to select which passes and functions to dump. For example: + `all` matches all passes and functions, + `foo` matches all passes for functions whose name contains 'foo', + `foo & ConstProp` only the 'ConstProp' pass for function names containing 'foo', + `foo | bar` all passes for function names containing 'foo' or 'bar'."), + dump_mir_dir: String = (String::from("mir_dump"), parse_string, [UNTRACKED], "the directory the MIR is dumped into"), dump_mir_graphviz: bool = (false, parse_bool, [UNTRACKED], @@ -1281,7 +1288,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, dump_mir_exclude_pass_number: bool = (false, parse_bool, [UNTRACKED], "if set, exclude the pass number when dumping MIR (used in tests)"), mir_emit_retag: bool = (false, parse_bool, [TRACKED], - "emit Retagging MIR statements, interpreted e.g. by miri; implies -Zmir-opt-level=0"), + "emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0"), perf_stats: bool = (false, parse_bool, [UNTRACKED], "print some performance-related statistics"), hir_stats: bool = (false, parse_bool, [UNTRACKED], @@ -1292,8 +1299,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "pass `-install_name @rpath/...` to the macOS linker"), sanitizer: Option = (None, parse_sanitizer, [TRACKED], "Use a sanitizer"), - linker_flavor: Option = (None, parse_linker_flavor, [UNTRACKED], - "Linker flavor"), fuel: Option<(String, u64)> = (None, parse_optimization_fuel, [TRACKED], "set the optimization fuel quota for a crate"), print_fuel: Option = (None, parse_opt_string, [TRACKED], @@ -1533,7 +1538,7 @@ impl RustcOptGroup { // adds extra rustc-specific metadata to each option; such metadata // is exposed by . The public // functions below ending with `_u` are the functions that return -// *unstable* options, i.e. options that are only enabled when the +// *unstable* options, i.e., options that are only enabled when the // user also passes the `-Z unstable-options` debugging flag. mod opt { // The `fn opt_u` etc below are written so that we can use them @@ -1756,8 +1761,8 @@ pub fn parse_cfgspecs(cfgspecs: Vec) -> ast::CrateConfig { .into_iter() .map(|s| { let sess = parse::ParseSess::new(FilePathMapping::empty()); - let mut parser = - parse::new_parser_from_source_str(&sess, FileName::CfgSpec, s.to_string()); + let filename = FileName::cfg_spec_source_code(&s); + let mut parser = parse::new_parser_from_source_str(&sess, filename, s.to_string()); macro_rules! error {($reason: expr) => { early_error(ErrorOutputType::default(), @@ -2110,9 +2115,9 @@ pub fn build_session_options_and_crate_config( } }; - let mut search_paths = SearchPaths::new(); + let mut search_paths = vec![]; for s in &matches.opt_strs("L") { - search_paths.add_path(&s[..], error_format); + search_paths.push(SearchPath::from_cli_opt(&s[..], error_format)); } let libs = matches @@ -2381,7 +2386,7 @@ impl fmt::Display for CrateType { /// tracking are hashed into a single value that determines whether the /// incremental compilation cache can be re-used or not. This hashing is done /// via the DepTrackingHash trait defined below, since the standard Hash -/// implementation might not be suitable (e.g. arguments are stored in a Vec, +/// implementation might not be suitable (e.g., arguments are stored in a Vec, /// the hash of which is order dependent, but we might not want the order of /// arguments to make a difference for the hash). /// @@ -2530,6 +2535,7 @@ mod tests { use session::config::{build_configuration, build_session_options_and_crate_config}; use session::config::{LtoCli, CrossLangLto}; use session::build_session; + use session::search_paths::SearchPath; use std::collections::{BTreeMap, BTreeSet}; use std::iter::FromIterator; use std::path::PathBuf; @@ -2785,48 +2791,48 @@ mod tests { // Reference v1.search_paths - .add_path("native=abc", super::ErrorOutputType::Json(false)); + .push(SearchPath::from_cli_opt("native=abc", super::ErrorOutputType::Json(false))); v1.search_paths - .add_path("crate=def", super::ErrorOutputType::Json(false)); + .push(SearchPath::from_cli_opt("crate=def", super::ErrorOutputType::Json(false))); v1.search_paths - .add_path("dependency=ghi", super::ErrorOutputType::Json(false)); + .push(SearchPath::from_cli_opt("dependency=ghi", super::ErrorOutputType::Json(false))); v1.search_paths - .add_path("framework=jkl", super::ErrorOutputType::Json(false)); + .push(SearchPath::from_cli_opt("framework=jkl", super::ErrorOutputType::Json(false))); v1.search_paths - .add_path("all=mno", super::ErrorOutputType::Json(false)); + .push(SearchPath::from_cli_opt("all=mno", super::ErrorOutputType::Json(false))); v2.search_paths - .add_path("native=abc", super::ErrorOutputType::Json(false)); + .push(SearchPath::from_cli_opt("native=abc", super::ErrorOutputType::Json(false))); v2.search_paths - .add_path("dependency=ghi", super::ErrorOutputType::Json(false)); + .push(SearchPath::from_cli_opt("dependency=ghi", super::ErrorOutputType::Json(false))); v2.search_paths - .add_path("crate=def", super::ErrorOutputType::Json(false)); + .push(SearchPath::from_cli_opt("crate=def", super::ErrorOutputType::Json(false))); v2.search_paths - .add_path("framework=jkl", super::ErrorOutputType::Json(false)); + .push(SearchPath::from_cli_opt("framework=jkl", super::ErrorOutputType::Json(false))); v2.search_paths - .add_path("all=mno", super::ErrorOutputType::Json(false)); + .push(SearchPath::from_cli_opt("all=mno", super::ErrorOutputType::Json(false))); v3.search_paths - .add_path("crate=def", super::ErrorOutputType::Json(false)); + .push(SearchPath::from_cli_opt("crate=def", super::ErrorOutputType::Json(false))); v3.search_paths - .add_path("framework=jkl", super::ErrorOutputType::Json(false)); + .push(SearchPath::from_cli_opt("framework=jkl", super::ErrorOutputType::Json(false))); v3.search_paths - .add_path("native=abc", super::ErrorOutputType::Json(false)); + .push(SearchPath::from_cli_opt("native=abc", super::ErrorOutputType::Json(false))); v3.search_paths - .add_path("dependency=ghi", super::ErrorOutputType::Json(false)); + .push(SearchPath::from_cli_opt("dependency=ghi", super::ErrorOutputType::Json(false))); v3.search_paths - .add_path("all=mno", super::ErrorOutputType::Json(false)); + .push(SearchPath::from_cli_opt("all=mno", super::ErrorOutputType::Json(false))); v4.search_paths - .add_path("all=mno", super::ErrorOutputType::Json(false)); + .push(SearchPath::from_cli_opt("all=mno", super::ErrorOutputType::Json(false))); v4.search_paths - .add_path("native=abc", super::ErrorOutputType::Json(false)); + .push(SearchPath::from_cli_opt("native=abc", super::ErrorOutputType::Json(false))); v4.search_paths - .add_path("crate=def", super::ErrorOutputType::Json(false)); + .push(SearchPath::from_cli_opt("crate=def", super::ErrorOutputType::Json(false))); v4.search_paths - .add_path("dependency=ghi", super::ErrorOutputType::Json(false)); + .push(SearchPath::from_cli_opt("dependency=ghi", super::ErrorOutputType::Json(false))); v4.search_paths - .add_path("framework=jkl", super::ErrorOutputType::Json(false)); + .push(SearchPath::from_cli_opt("framework=jkl", super::ErrorOutputType::Json(false))); assert!(v1.dep_tracking_hash() == v2.dep_tracking_hash()); assert!(v1.dep_tracking_hash() == v3.dep_tracking_hash()); diff --git a/src/librustc/session/filesearch.rs b/src/librustc/session/filesearch.rs index f410c270bce..c204556d517 100644 --- a/src/librustc/session/filesearch.rs +++ b/src/librustc/session/filesearch.rs @@ -12,13 +12,12 @@ pub use self::FileMatch::*; -use rustc_data_structures::fx::FxHashSet; use std::borrow::Cow; use std::env; use std::fs; use std::path::{Path, PathBuf}; -use session::search_paths::{SearchPaths, PathKind}; +use session::search_paths::{SearchPath, PathKind}; use rustc_fs_util::fix_windows_verbatim_for_gcc; #[derive(Copy, Clone)] @@ -30,31 +29,19 @@ pub enum FileMatch { // A module for searching for libraries pub struct FileSearch<'a> { - pub sysroot: &'a Path, - pub search_paths: &'a SearchPaths, - pub triple: &'a str, - pub kind: PathKind, + sysroot: &'a Path, + triple: &'a str, + search_paths: &'a [SearchPath], + tlib_path: &'a SearchPath, + kind: PathKind, } impl<'a> FileSearch<'a> { - pub fn for_each_lib_search_path(&self, mut f: F) where - F: FnMut(&Path, PathKind) - { - let mut visited_dirs = FxHashSet::default(); - visited_dirs.reserve(self.search_paths.paths.len() + 1); - for (path, kind) in self.search_paths.iter(self.kind) { - f(path, kind); - visited_dirs.insert(path.to_path_buf()); - } - - debug!("filesearch: searching lib path"); - let tlib_path = make_target_lib_path(self.sysroot, - self.triple); - if !visited_dirs.contains(&tlib_path) { - f(&tlib_path, PathKind::All); - } - - visited_dirs.insert(tlib_path); + pub fn search_paths(&self) -> impl Iterator { + let kind = self.kind; + self.search_paths.iter() + .filter(move |sp| sp.kind.matches(kind)) + .chain(std::iter::once(self.tlib_path)) } pub fn get_lib_path(&self) -> PathBuf { @@ -64,14 +51,8 @@ impl<'a> FileSearch<'a> { pub fn search(&self, mut pick: F) where F: FnMut(&Path, PathKind) -> FileMatch { - self.for_each_lib_search_path(|lib_search_path, kind| { - debug!("searching {}", lib_search_path.display()); - let files = match fs::read_dir(lib_search_path) { - Ok(files) => files, - Err(..) => return, - }; - let files = files.filter_map(|p| p.ok().map(|s| s.path())) - .collect::>(); + for search_path in self.search_paths() { + debug!("searching {}", search_path.dir.display()); fn is_rlib(p: &Path) -> bool { p.extension() == Some("rlib".as_ref()) } @@ -79,11 +60,11 @@ impl<'a> FileSearch<'a> { // an rlib and a dylib we only read one of the files of // metadata, so in the name of speed, bring all rlib files to // the front of the search list. - let files1 = files.iter().filter(|p| is_rlib(p)); - let files2 = files.iter().filter(|p| !is_rlib(p)); + let files1 = search_path.files.iter().filter(|p| is_rlib(p)); + let files2 = search_path.files.iter().filter(|p| !is_rlib(p)); for path in files1.chain(files2) { debug!("testing {}", path.display()); - let maybe_picked = pick(path, kind); + let maybe_picked = pick(path, search_path.kind); match maybe_picked { FileMatches => { debug!("picked {}", path.display()); @@ -93,29 +74,30 @@ impl<'a> FileSearch<'a> { } } } - }); + } } pub fn new(sysroot: &'a Path, triple: &'a str, - search_paths: &'a SearchPaths, - kind: PathKind) -> FileSearch<'a> { + search_paths: &'a Vec, + tlib_path: &'a SearchPath, + kind: PathKind) + -> FileSearch<'a> { debug!("using sysroot = {}, triple = {}", sysroot.display(), triple); FileSearch { sysroot, - search_paths, triple, + search_paths, + tlib_path, kind, } } - // Returns a list of directories where target-specific dylibs might be located. - pub fn get_dylib_search_paths(&self) -> Vec { - let mut paths = Vec::new(); - self.for_each_lib_search_path(|lib_search_path, _| { - paths.push(lib_search_path.to_path_buf()); - }); - paths + // Returns just the directories within the search paths. + pub fn search_path_dirs(&self) -> Vec { + self.search_paths() + .map(|sp| sp.dir.to_path_buf()) + .collect() } // Returns a list of directories where target-specific tool binaries are located. @@ -138,8 +120,7 @@ pub fn relative_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf p } -fn make_target_lib_path(sysroot: &Path, - target_triple: &str) -> PathBuf { +pub fn make_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf { sysroot.join(&relative_target_lib_path(sysroot, target_triple)) } @@ -176,15 +157,15 @@ fn find_libdir(sysroot: &Path) -> Cow<'static, str> { // of the directory where librustc is located, rather than where the rustc // binary is. // If --libdir is set during configuration to the value other than - // "lib" (i.e. non-default), this value is used (see issue #16552). + // "lib" (i.e., non-default), this value is used (see issue #16552). #[cfg(target_pointer_width = "64")] - const PRIMARY_LIB_DIR: &'static str = "lib64"; + const PRIMARY_LIB_DIR: &str = "lib64"; #[cfg(target_pointer_width = "32")] - const PRIMARY_LIB_DIR: &'static str = "lib32"; + const PRIMARY_LIB_DIR: &str = "lib32"; - const SECONDARY_LIB_DIR: &'static str = "lib"; + const SECONDARY_LIB_DIR: &str = "lib"; match option_env!("CFG_LIBDIR_RELATIVE") { Some(libdir) if libdir != "lib" => libdir.into(), @@ -198,4 +179,4 @@ fn find_libdir(sysroot: &Path) -> Cow<'static, str> { // The name of rustc's own place to organize libraries. // Used to be "rustc", now the default is "rustlib" -const RUST_LIB_DIR: &'static str = "rustlib"; +const RUST_LIB_DIR: &str = "rustlib"; diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index d1c3acc57b7..180019ac387 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -19,8 +19,8 @@ use lint; use lint::builtin::BuiltinLintDiagnostics; use middle::allocator::AllocatorKind; use middle::dependency_format; -use session::search_paths::PathKind; use session::config::{OutputType, Lto}; +use session::search_paths::{PathKind, SearchPath}; use util::nodemap::{FxHashMap, FxHashSet}; use util::common::{duration_to_secs_str, ErrorReported}; use util::common::ProfileQueriesMsg; @@ -48,7 +48,7 @@ use std::cell::{self, Cell, RefCell}; use std::env; use std::fmt; use std::io::Write; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use std::time::Duration; use std::sync::mpsc; use std::sync::atomic::{AtomicUsize, Ordering}; @@ -64,12 +64,15 @@ pub struct Session { pub target: config::Config, pub host: Target, pub opts: config::Options, + pub host_tlib_path: SearchPath, + /// This is `None` if the host and target are the same. + pub target_tlib_path: Option, pub parse_sess: ParseSess, /// For a library crate, this is always none pub entry_fn: Once>, pub plugin_registrar_fn: Once>, pub proc_macro_decls_static: Once>, - pub default_sysroot: Option, + pub sysroot: PathBuf, /// The name of the root source file of the crate, in the local file system. /// `None` means that there is no source file. pub local_crate_source_file: Option, @@ -128,6 +131,9 @@ pub struct Session { /// Used by -Z profile-queries in util::common pub profile_channel: Lock>>, + /// Used by -Z self-profile + pub self_profiling_active: bool, + /// Used by -Z self-profile pub self_profiling: Lock, @@ -586,7 +592,7 @@ impl Session { // either return `No` or `ThinLocal`. // If processing command line options determined that we're incompatible - // with ThinLTO (e.g. `-C lto --emit llvm-ir`) then return that option. + // with ThinLTO (e.g., `-C lto --emit llvm-ir`) then return that option. if self.opts.cli_forced_thinlto_off { return config::Lto::No; } @@ -694,27 +700,22 @@ impl Session { ) } - pub fn sysroot<'a>(&'a self) -> &'a Path { - match self.opts.maybe_sysroot { - Some(ref sysroot) => sysroot, - None => self.default_sysroot - .as_ref() - .expect("missing sysroot and default_sysroot in Session"), - } - } pub fn target_filesearch(&self, kind: PathKind) -> filesearch::FileSearch<'_> { filesearch::FileSearch::new( - self.sysroot(), + &self.sysroot, self.opts.target_triple.triple(), &self.opts.search_paths, + // target_tlib_path==None means it's the same as host_tlib_path. + self.target_tlib_path.as_ref().unwrap_or(&self.host_tlib_path), kind, ) } pub fn host_filesearch(&self, kind: PathKind) -> filesearch::FileSearch<'_> { filesearch::FileSearch::new( - self.sysroot(), + &self.sysroot, config::host_triple(), &self.opts.search_paths, + &self.host_tlib_path, kind, ) } @@ -825,10 +826,17 @@ impl Session { } } + #[inline(never)] + #[cold] + fn profiler_active ()>(&self, f: F) { + let mut profiler = self.self_profiling.borrow_mut(); + f(&mut profiler); + } + + #[inline(always)] pub fn profiler ()>(&self, f: F) { - if self.opts.debugging_opts.self_profile { - let mut profiler = self.self_profiling.borrow_mut(); - f(&mut profiler); + if unlikely!(self.self_profiling_active) { + self.profiler_active(f) } } @@ -1109,9 +1117,18 @@ pub fn build_session_( let target_cfg = config::build_target_config(&sopts, &span_diagnostic); let p_s = parse::ParseSess::with_span_handler(span_diagnostic, source_map); - let default_sysroot = match sopts.maybe_sysroot { - Some(_) => None, - None => Some(filesearch::get_or_default_sysroot()), + let sysroot = match &sopts.maybe_sysroot { + Some(sysroot) => sysroot.clone(), + None => filesearch::get_or_default_sysroot(), + }; + + let host_triple = config::host_triple(); + let target_triple = sopts.target_triple.triple(); + let host_tlib_path = SearchPath::from_sysroot_and_triple(&sysroot, host_triple); + let target_tlib_path = if host_triple == target_triple { + None + } else { + Some(SearchPath::from_sysroot_and_triple(&sysroot, target_triple)) }; let file_path_mapping = sopts.file_path_mapping(); @@ -1138,16 +1155,21 @@ pub fn build_session_( CguReuseTracker::new_disabled() }; + let self_profiling_active = sopts.debugging_opts.self_profile || + sopts.debugging_opts.profile_json; + let sess = Session { target: target_cfg, host, opts: sopts, + host_tlib_path, + target_tlib_path, parse_sess: p_s, // For a library crate, this is always none entry_fn: Once::new(), plugin_registrar_fn: Once::new(), proc_macro_decls_static: Once::new(), - default_sysroot, + sysroot, local_crate_source_file, working_dir, lint_store: RwLock::new(lint::LintStore::new()), @@ -1168,6 +1190,7 @@ pub fn build_session_( imported_macro_spans: OneThread::new(RefCell::new(FxHashMap::default())), incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)), cgu_reuse_tracker, + self_profiling_active, self_profiling: Lock::new(SelfProfiler::new()), profile_channel: Lock::new(None), perf_stats: PerfStats { diff --git a/src/librustc/session/search_paths.rs b/src/librustc/session/search_paths.rs index 768d4f1e5fb..5c44a07f843 100644 --- a/src/librustc/session/search_paths.rs +++ b/src/librustc/session/search_paths.rs @@ -8,18 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::slice; use std::path::{Path, PathBuf}; use session::{early_error, config}; +use session::filesearch::make_target_lib_path; #[derive(Clone, Debug)] -pub struct SearchPaths { - crate paths: Vec<(PathKind, PathBuf)>, -} - -pub struct Iter<'a> { - kind: PathKind, - iter: slice::Iter<'a, (PathKind, PathBuf)>, +pub struct SearchPath { + pub kind: PathKind, + pub dir: PathBuf, + pub files: Vec, } #[derive(Eq, PartialEq, Clone, Copy, Debug, PartialOrd, Ord, Hash)] @@ -32,12 +29,17 @@ pub enum PathKind { All, } -impl SearchPaths { - pub fn new() -> SearchPaths { - SearchPaths { paths: Vec::new() } +impl PathKind { + pub fn matches(&self, kind: PathKind) -> bool { + match (self, kind) { + (PathKind::All, _) | (_, PathKind::All) => true, + _ => *self == kind, + } } +} - pub fn add_path(&mut self, path: &str, output: config::ErrorOutputType) { +impl SearchPath { + pub fn from_cli_opt(path: &str, output: config::ErrorOutputType) -> Self { let (kind, path) = if path.starts_with("native=") { (PathKind::Native, &path["native=".len()..]) } else if path.starts_with("crate=") { @@ -54,35 +56,28 @@ impl SearchPaths { if path.is_empty() { early_error(output, "empty search path given via `-L`"); } - self.paths.push((kind, PathBuf::from(path))); + + let dir = PathBuf::from(path); + Self::new(kind, dir) } - pub fn iter(&self, kind: PathKind) -> Iter<'_> { - Iter { kind: kind, iter: self.paths.iter() } + pub fn from_sysroot_and_triple(sysroot: &Path, triple: &str) -> Self { + Self::new(PathKind::All, make_target_lib_path(sysroot, triple)) } -} -impl<'a> Iterator for Iter<'a> { - type Item = (&'a Path, PathKind); - - fn next(&mut self) -> Option<(&'a Path, PathKind)> { - loop { - match self.iter.next() { - Some(&(kind, ref p)) if self.kind == PathKind::All || - kind == PathKind::All || - kind == self.kind => { - return Some((p, kind)) - } - Some(..) => {} - None => return None, + fn new(kind: PathKind, dir: PathBuf) -> Self { + // Get the files within the directory. + let files = match std::fs::read_dir(&dir) { + Ok(files) => { + files.filter_map(|p| { + p.ok().map(|s| s.path()) + }) + .collect::>() } - } - } + Err(..) => vec![], + }; - fn size_hint(&self) -> (usize, Option) { - // This iterator will never return more elements than the base iterator; - // but it can ignore all the remaining elements. - let (_, upper) = self.iter.size_hint(); - (0, upper) + SearchPath { kind, dir, files } } } + diff --git a/src/librustc/traits/auto_trait.rs b/src/librustc/traits/auto_trait.rs index c3cca149c2c..fff77816e75 100644 --- a/src/librustc/traits/auto_trait.rs +++ b/src/librustc/traits/auto_trait.rs @@ -138,7 +138,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { // the first evaluate_predicates call. // // The problem is this: most of rustc, including SelectionContext and traits::project, - // are designed to work with a concrete usage of a type (e.g. Vec + // are designed to work with a concrete usage of a type (e.g., Vec // fn() { Vec }. This information will generally never change - given // the 'T' in fn() { ... }, we'll never know anything else about 'T'. // If we're unable to prove that 'T' implements a particular trait, we're done - @@ -289,7 +289,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { // // One additional consideration is supertrait bounds. Normally, a ParamEnv is only ever // constructed once for a given type. As part of the construction process, the ParamEnv will - // have any supertrait bounds normalized - e.g. if we have a type 'struct Foo', the + // have any supertrait bounds normalized - e.g., if we have a type 'struct Foo', the // ParamEnv will contain 'T: Copy' and 'T: Clone', since 'Copy: Clone'. When we construct our // own ParamEnv, we need to do this ourselves, through traits::elaborate_predicates, or else // SelectionContext will choke on the missing predicates. However, this should never show up in @@ -334,11 +334,16 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { continue; } - let result = select.select(&Obligation::new(dummy_cause.clone(), new_env, pred)); + // Call infcx.resolve_type_vars_if_possible to see if we can + // get rid of any inference variables. + let obligation = infcx.resolve_type_vars_if_possible( + &Obligation::new(dummy_cause.clone(), new_env, pred) + ); + let result = select.select(&obligation); match &result { &Ok(Some(ref vtable)) => { - // If we see an explicit negative impl (e.g. 'impl !Send for MyStruct'), + // If we see an explicit negative impl (e.g., 'impl !Send for MyStruct'), // we immediately bail out, since it's impossible for us to continue. match vtable { Vtable::VtableImpl(VtableImplData { impl_def_id, .. }) => { @@ -369,7 +374,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { } &Ok(None) => {} &Err(SelectionError::Unimplemented) => { - if self.is_of_param(pred.skip_binder().trait_ref.substs) { + if self.is_param_no_infer(pred.skip_binder().trait_ref.substs) { already_visited.remove(&pred); self.add_user_pred( &mut user_computed_preds, @@ -427,11 +432,11 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { // If we put both of these predicates in our computed ParamEnv, we'll // confuse SelectionContext, since it will (correctly) view both as being applicable. // - // To solve this, we pick the 'more strict' lifetime bound - i.e. the HRTB + // To solve this, we pick the 'more strict' lifetime bound - i.e., the HRTB // Our end goal is to generate a user-visible description of the conditions // under which a type implements an auto trait. A trait predicate involving // a HRTB means that the type needs to work with any choice of lifetime, - // not just one specific lifetime (e.g. 'static). + // not just one specific lifetime (e.g., 'static). fn add_user_pred<'c>( &self, user_computed_preds: &mut FxHashSet>, @@ -631,18 +636,28 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { finished_map } - pub fn is_of_param(&self, substs: &Substs<'_>) -> bool { - if substs.is_noop() { - return false; - } + fn is_param_no_infer(&self, substs: &Substs<'_>) -> bool { + return self.is_of_param(substs.type_at(0)) && + !substs.types().any(|t| t.has_infer_types()); + } - return match substs.type_at(0).sty { + pub fn is_of_param(&self, ty: Ty<'_>) -> bool { + return match ty.sty { ty::Param(_) => true, - ty::Projection(p) => self.is_of_param(p.substs), + ty::Projection(p) => self.is_of_param(p.self_ty()), _ => false, }; } + fn is_self_referential_projection(&self, p: ty::PolyProjectionPredicate<'_>) -> bool { + match p.ty().skip_binder().sty { + ty::Projection(proj) if proj == p.skip_binder().projection_ty => { + true + }, + _ => false + } + } + pub fn evaluate_nested_obligations< 'b, 'c, @@ -661,28 +676,77 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { ) -> bool { let dummy_cause = ObligationCause::misc(DUMMY_SP, ast::DUMMY_NODE_ID); - for (obligation, predicate) in nested - .filter(|o| o.recursion_depth == 1) + for (obligation, mut predicate) in nested .map(|o| (o.clone(), o.predicate.clone())) { let is_new_pred = fresh_preds.insert(self.clean_pred(select.infcx(), predicate.clone())); + // Resolve any inference variables that we can, to help selection succeed + predicate = select.infcx().resolve_type_vars_if_possible(&predicate); + + // We only add a predicate as a user-displayable bound if + // it involves a generic parameter, and doesn't contain + // any inference variables. + // + // Displaying a bound involving a concrete type (instead of a generic + // parameter) would be pointless, since it's always true + // (e.g. u8: Copy) + // Displaying an inference variable is impossible, since they're + // an internal compiler detail without a defined visual representation + // + // We check this by calling is_of_param on the relevant types + // from the various possible predicates match &predicate { &ty::Predicate::Trait(ref p) => { - let substs = &p.skip_binder().trait_ref.substs; + if self.is_param_no_infer(p.skip_binder().trait_ref.substs) + && !only_projections + && is_new_pred { - if self.is_of_param(substs) && !only_projections && is_new_pred { self.add_user_pred(computed_preds, predicate); } predicates.push_back(p.clone()); } &ty::Predicate::Projection(p) => { - // If the projection isn't all type vars, then - // we don't want to add it as a bound - if self.is_of_param(p.skip_binder().projection_ty.substs) && is_new_pred { - self.add_user_pred(computed_preds, predicate); - } else { + debug!("evaluate_nested_obligations: examining projection predicate {:?}", + predicate); + + // As described above, we only want to display + // bounds which include a generic parameter but don't include + // an inference variable. + // Additionally, we check if we've seen this predicate before, + // to avoid rendering duplicate bounds to the user. + if self.is_param_no_infer(p.skip_binder().projection_ty.substs) + && !p.ty().skip_binder().is_ty_infer() + && is_new_pred { + debug!("evaluate_nested_obligations: adding projection predicate\ + to computed_preds: {:?}", predicate); + + // Under unusual circumstances, we can end up with a self-refeential + // projection predicate. For example: + // ::Value == ::Value + // Not only is displaying this to the user pointless, + // having it in the ParamEnv will cause an issue if we try to call + // poly_project_and_unify_type on the predicate, since this kind of + // predicate will normally never end up in a ParamEnv. + // + // For these reasons, we ignore these weird predicates, + // ensuring that we're able to properly synthesize an auto trait impl + if self.is_self_referential_projection(p) { + debug!("evaluate_nested_obligations: encountered a projection + predicate equating a type with itself! Skipping"); + + } else { + self.add_user_pred(computed_preds, predicate); + } + } + + // We can only call poly_project_and_unify_type when our predicate's + // Ty is an inference variable - otherwise, there won't be anything to + // unify + if p.ty().skip_binder().is_ty_infer() { + debug!("Projecting and unifying projection predicate {:?}", + predicate); match poly_project_and_unify_type(select, &obligation.with(p.clone())) { Err(e) => { debug!( diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index 4bf8ba0d6d1..853b54df2b9 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -20,6 +20,7 @@ use traits::{self, Normalized, SelectionContext, Obligation, ObligationCause}; use traits::IntercrateMode; use traits::select::IntercrateAmbiguityCause; use ty::{self, Ty, TyCtxt}; +use ty::relate::TraitObjectMode; use ty::fold::TypeFoldable; use ty::subst::Subst; @@ -52,6 +53,7 @@ pub fn overlapping_impls<'gcx, F1, F2, R>( impl1_def_id: DefId, impl2_def_id: DefId, intercrate_mode: IntercrateMode, + trait_object_mode: TraitObjectMode, on_overlap: F1, no_overlap: F2, ) -> R @@ -62,12 +64,14 @@ where debug!("overlapping_impls(\ impl1_def_id={:?}, \ impl2_def_id={:?}, - intercrate_mode={:?})", + intercrate_mode={:?}, + trait_object_mode={:?})", impl1_def_id, impl2_def_id, - intercrate_mode); + intercrate_mode, + trait_object_mode); - let overlaps = tcx.infer_ctxt().enter(|infcx| { + let overlaps = tcx.infer_ctxt().with_trait_object_mode(trait_object_mode).enter(|infcx| { let selcx = &mut SelectionContext::intercrate(&infcx, intercrate_mode); overlap(selcx, impl1_def_id, impl2_def_id).is_some() }); @@ -79,7 +83,7 @@ where // In the case where we detect an error, run the check again, but // this time tracking intercrate ambuiguity causes for better // diagnostics. (These take time and can lead to false errors.) - tcx.infer_ctxt().enter(|infcx| { + tcx.infer_ctxt().with_trait_object_mode(trait_object_mode).enter(|infcx| { let selcx = &mut SelectionContext::intercrate(&infcx, intercrate_mode); selcx.enable_tracking_intercrate_ambiguity_causes(); on_overlap(overlap(selcx, impl1_def_id, impl2_def_id).unwrap()) @@ -256,12 +260,12 @@ pub fn orphan_check<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, /// The current rule is that a trait-ref orphan checks in a crate C: /// /// 1. Order the parameters in the trait-ref in subst order - Self first, -/// others linearly (e.g. `>` is U < V < W). +/// others linearly (e.g., `>` is U < V < W). /// 2. Of these type parameters, there is at least one type parameter /// in which, walking the type as a tree, you can reach a type local /// to C where all types in-between are fundamental types. Call the /// first such parameter the "local key parameter". -/// - e.g. `Box` is OK, because you can visit LocalType +/// - e.g., `Box` is OK, because you can visit LocalType /// going through `Box`, which is fundamental. /// - similarly, `FundamentalPair, Box>` is OK for /// the same reason. @@ -269,7 +273,7 @@ pub fn orphan_check<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, /// not local), `Vec` is bad, because `Vec<->` is between /// the local type and the type parameter. /// 3. Every type parameter before the local key parameter is fully known in C. -/// - e.g. `impl T: Trait` is bad, because `T` might be +/// - e.g., `impl T: Trait` is bad, because `T` might be /// an unknown type. /// - but `impl LocalType: Trait` is OK, because `LocalType` /// occurs before `T`. @@ -277,7 +281,7 @@ pub fn orphan_check<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, /// through the parameter's type tree, must appear only as a subtree of /// a type local to C, with only fundamental types between the type /// local to C and the local key parameter. -/// - e.g. `Vec>>` (or equivalently `Box>>`) +/// - e.g., `Vec>>` (or equivalently `Box>>`) /// is bad, because the only local type with `T` as a subtree is /// `LocalType`, and `Vec<->` is between it and the type parameter. /// - similarly, `FundamentalPair, T>` is bad, because @@ -288,7 +292,7 @@ pub fn orphan_check<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, /// /// The orphan rules actually serve several different purposes: /// -/// 1. They enable link-safety - i.e. 2 mutually-unknowing crates (where +/// 1. They enable link-safety - i.e., 2 mutually-unknowing crates (where /// every type local to one crate is unknown in the other) can't implement /// the same trait-ref. This follows because it can be seen that no such /// type can orphan-check in 2 such crates. @@ -393,7 +397,7 @@ fn uncovered_tys<'tcx>(tcx: TyCtxt<'_, '_, '_>, ty: Ty<'tcx>, in_crate: InCrate) -> Vec> { if ty_is_local_constructor(ty, in_crate) { vec![] - } else if fundamental_ty(tcx, ty) { + } else if fundamental_ty(ty) { ty.walk_shallow() .flat_map(|t| uncovered_tys(tcx, t, in_crate)) .collect() @@ -411,14 +415,13 @@ fn is_possibly_remote_type(ty: Ty<'_>, _in_crate: InCrate) -> bool { fn ty_is_local(tcx: TyCtxt<'_, '_, '_>, ty: Ty<'_>, in_crate: InCrate) -> bool { ty_is_local_constructor(ty, in_crate) || - fundamental_ty(tcx, ty) && ty.walk_shallow().any(|t| ty_is_local(tcx, t, in_crate)) + fundamental_ty(ty) && ty.walk_shallow().any(|t| ty_is_local(tcx, t, in_crate)) } -fn fundamental_ty(tcx: TyCtxt<'_, '_, '_>, ty: Ty<'_>) -> bool { +fn fundamental_ty(ty: Ty<'_>) -> bool { match ty.sty { ty::Ref(..) => true, ty::Adt(def, _) => def.is_fundamental(), - ty::Dynamic(ref data, ..) => tcx.has_attr(data.principal().def_id(), "fundamental"), _ => false } } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 7e97dc3c84a..373d6652b9e 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -128,7 +128,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } - // returns if `cond` not occurring implies that `error` does not occur - i.e. that + // returns if `cond` not occurring implies that `error` does not occur - i.e., that // `error` occurring implies that `cond` occurs. fn error_implies(&self, cond: &ty::Predicate<'tcx>, @@ -459,7 +459,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { { let simp = fast_reject::simplify_type(self.tcx, trait_ref.skip_binder().self_ty(), - true); + true,); let all_impls = self.tcx.all_impls(trait_ref.def_id()); match simp { @@ -580,7 +580,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let mut err = struct_span_err!(self.tcx.sess, sp, E0276, "{}", msg); - if let Some(trait_item_span) = self.tcx.hir.span_if_local(trait_item_def_id) { + if let Some(trait_item_span) = self.tcx.hir().span_if_local(trait_item_def_id) { let span = self.tcx.sess.source_map().def_span(trait_item_span); err.span_label(span, format!("definition of `{}` from trait", item_name)); } @@ -765,8 +765,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => { let found_kind = self.closure_kind(closure_def_id, closure_substs).unwrap(); let closure_span = self.tcx.sess.source_map() - .def_span(self.tcx.hir.span_if_local(closure_def_id).unwrap()); - let node_id = self.tcx.hir.as_local_node_id(closure_def_id).unwrap(); + .def_span(self.tcx.hir().span_if_local(closure_def_id).unwrap()); + let node_id = self.tcx.hir().as_local_node_id(closure_def_id).unwrap(); let mut err = struct_span_err!( self.tcx.sess, closure_span, E0525, "expected a closure that implements the `{}` trait, \ @@ -785,7 +785,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // a particular trait. if let Some(tables) = self.in_progress_tables { let tables = tables.borrow(); - let closure_hir_id = self.tcx.hir.node_to_hir_id(node_id); + let closure_hir_id = self.tcx.hir().node_to_hir_id(node_id); match (found_kind, tables.closure_kind_origins().get(closure_hir_id)) { (ty::ClosureKind::FnOnce, Some((span, name))) => { err.span_label(*span, format!( @@ -841,7 +841,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { }; let found_span = found_did.and_then(|did| - self.tcx.hir.span_if_local(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 let found = match found_trait_ref.skip_binder().substs.type_at(1).sty { @@ -862,7 +862,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { expected_trait_ref) } else { let (closure_span, found) = found_did - .and_then(|did| self.tcx.hir.get_if_local(did)) + .and_then(|did| self.tcx.hir().get_if_local(did)) .map(|node| { let (found_span, found) = self.get_fn_like_arguments(node); (Some(found_span), found) @@ -901,8 +901,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { code: &ObligationCauseCode<'tcx>, err: &mut DiagnosticBuilder<'tcx>) { if let &ObligationCauseCode::VariableType(node_id) = code { - let parent_node = self.tcx.hir.get_parent_node(node_id); - if let Some(Node::Local(ref local)) = self.tcx.hir.find(parent_node) { + let parent_node = self.tcx.hir().get_parent_node(node_id); + if let Some(Node::Local(ref local)) = self.tcx.hir().find(parent_node) { if let Some(ref expr) = local.init { if let hir::ExprKind::Index(_, _) = expr.node { if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(expr.span) { @@ -976,7 +976,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { node: hir::ExprKind::Closure(_, ref _decl, id, span, _), .. }) => { - (self.tcx.sess.source_map().def_span(span), self.tcx.hir.body(id).arguments.iter() + (self.tcx.sess.source_map().def_span(span), self.tcx.hir().body(id).arguments.iter() .map(|arg| { if let hir::Pat { node: hir::PatKind::Tuple(args, _), @@ -1037,7 +1037,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ).collect::>()) } Node::StructCtor(ref variant_data) => { - (self.tcx.sess.source_map().def_span(self.tcx.hir.span(variant_data.id())), + (self.tcx.sess.source_map().def_span(self.tcx.hir().span(variant_data.id())), vec![ArgKind::empty(); variant_data.fields().len()]) } _ => panic!("non-FnLike node found: {:?}", node), @@ -1236,7 +1236,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { -> DiagnosticBuilder<'tcx> { assert!(type_def_id.is_local()); - let span = self.hir.span_if_local(type_def_id).unwrap(); + let span = self.hir().span_if_local(type_def_id).unwrap(); let span = self.sess.source_map().def_span(span); let mut err = struct_span_err!(self.sess, span, E0072, "recursive type `{}` has infinite size", @@ -1482,7 +1482,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { 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) { + 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); } else { diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index bc091a4e7e0..09c7bd67970 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -61,6 +61,16 @@ pub struct FulfillmentContext<'tcx> { // type-lives-for-region constraints, and because the type // is well-formed, the constraints should hold. register_region_obligations: bool, + // Is it OK to register obligations into this infcx inside + // an infcx snapshot? + // + // The "primary fulfillment" in many cases in typeck lives + // outside of any snapshot, so any use of it inside a snapshot + // will lead to trouble and therefore is checked against, but + // other fulfillment contexts sometimes do live inside of + // a snapshot (they don't *straddle* a snapshot, so there + // is no trouble there). + usable_in_snapshot: bool } #[derive(Clone, Debug)] @@ -74,14 +84,24 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> { pub fn new() -> FulfillmentContext<'tcx> { FulfillmentContext { predicates: ObligationForest::new(), - register_region_obligations: true + register_region_obligations: true, + usable_in_snapshot: false, + } + } + + pub fn new_in_snapshot() -> FulfillmentContext<'tcx> { + FulfillmentContext { + predicates: ObligationForest::new(), + register_region_obligations: true, + usable_in_snapshot: true, } } pub fn new_ignoring_regions() -> FulfillmentContext<'tcx> { FulfillmentContext { predicates: ObligationForest::new(), - register_region_obligations: false + register_region_obligations: false, + usable_in_snapshot: false } } @@ -195,7 +215,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { debug!("register_predicate_obligation(obligation={:?})", obligation); - assert!(!infcx.is_in_snapshot()); + assert!(!infcx.is_in_snapshot() || self.usable_in_snapshot); self.predicates.register_obligation(PendingPredicateObligation { obligation, diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index ab2fa68ab5f..cf37c3fceba 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -8,52 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Trait Resolution. See [rustc guide] for more info on how this works. +//! Trait Resolution. See the [rustc guide] for more information on how this works. //! //! [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/resolution.html -pub use self::SelectionError::*; -pub use self::FulfillmentErrorCode::*; -pub use self::Vtable::*; -pub use self::ObligationCauseCode::*; - -use chalk_engine; -use hir; -use hir::def_id::DefId; -use infer::SuppressRegionErrors; -use infer::outlives::env::OutlivesEnvironment; -use middle::region; -use mir::interpret::ErrorHandled; -use ty::subst::Substs; -use ty::{self, AdtKind, List, Ty, TyCtxt, GenericParamDefKind, ToPredicate}; -use ty::error::{ExpectedFound, TypeError}; -use ty::fold::{TypeFolder, TypeFoldable, TypeVisitor}; -use infer::{InferCtxt}; -use util::common::ErrorReported; - -use rustc_data_structures::sync::Lrc; -use std::fmt::Debug; -use std::rc::Rc; -use syntax::ast; -use syntax_pos::{Span, DUMMY_SP}; - -pub use self::coherence::{orphan_check, overlapping_impls, OrphanCheckErr, OverlapResult}; -pub use self::fulfill::{FulfillmentContext, PendingPredicateObligation}; -pub use self::project::MismatchedProjectionTypes; -pub use self::project::{normalize, normalize_projection_type, poly_project_and_unify_type}; -pub use self::project::{ProjectionCache, ProjectionCacheSnapshot, Reveal, Normalized}; -pub use self::object_safety::ObjectSafetyViolation; -pub use self::object_safety::MethodViolationCode; -pub use self::on_unimplemented::{OnUnimplementedDirective, OnUnimplementedNote}; -pub use self::select::{EvaluationCache, SelectionContext, SelectionCache}; -pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError}; -pub use self::specialize::{OverlapError, specialization_graph, translate_substs}; -pub use self::specialize::find_associated_item; -pub use self::engine::{TraitEngine, TraitEngineExt}; -pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs}; -pub use self::util::{supertraits, supertrait_def_ids, Supertraits, SupertraitDefIds}; -pub use self::util::transitive_bounds; - #[allow(dead_code)] pub mod auto_trait; mod coherence; @@ -68,9 +26,56 @@ mod specialize; mod structural_impls; pub mod codegen; mod util; - pub mod query; +use chalk_engine; +use hir; +use hir::def_id::DefId; +use infer::{InferCtxt, SuppressRegionErrors}; +use infer::outlives::env::OutlivesEnvironment; +use middle::region; +use mir::interpret::ErrorHandled; +use rustc_data_structures::sync::Lrc; +use syntax::ast; +use syntax_pos::{Span, DUMMY_SP}; +use ty::subst::Substs; +use ty::{self, AdtKind, List, Ty, TyCtxt, GenericParamDefKind, ToPredicate}; +use ty::error::{ExpectedFound, TypeError}; +use ty::fold::{TypeFolder, TypeFoldable, TypeVisitor}; +use util::common::ErrorReported; + +use std::fmt::Debug; +use std::rc::Rc; + +pub use self::SelectionError::*; +pub use self::FulfillmentErrorCode::*; +pub use self::Vtable::*; +pub use self::ObligationCauseCode::*; + +pub use self::coherence::{orphan_check, overlapping_impls, OrphanCheckErr, OverlapResult}; +pub use self::fulfill::{FulfillmentContext, PendingPredicateObligation}; +pub use self::project::MismatchedProjectionTypes; +pub use self::project::{normalize, normalize_projection_type, poly_project_and_unify_type}; +pub use self::project::{ProjectionCache, ProjectionCacheSnapshot, Reveal, Normalized}; +pub use self::object_safety::ObjectSafetyViolation; +pub use self::object_safety::MethodViolationCode; +pub use self::on_unimplemented::{OnUnimplementedDirective, OnUnimplementedNote}; +pub use self::select::{EvaluationCache, SelectionContext, SelectionCache}; +pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError}; +pub use self::specialize::{OverlapError, specialization_graph, translate_substs}; +pub use self::specialize::find_associated_item; +pub use self::specialize::specialization_graph::FutureCompatOverlapError; +pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind; +pub use self::engine::{TraitEngine, TraitEngineExt}; +pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs}; +pub use self::util::{supertraits, supertrait_def_ids, transitive_bounds, + Supertraits, SupertraitDefIds}; + +pub use self::ObligationCauseCode::*; +pub use self::FulfillmentErrorCode::*; +pub use self::SelectionError::*; +pub use self::Vtable::*; + // Whether to enable bug compatibility with issue #43355 #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum IntercrateMode { @@ -91,7 +96,7 @@ pub enum TraitQueryMode { Canonical, } -/// An `Obligation` represents some trait reference (e.g. `int:Eq`) for +/// An `Obligation` represents some trait reference (e.g., `int:Eq`) for /// which the vtable must be found. The process of finding a vtable is /// called "resolving" the `Obligation`. This process consists of /// either identifying an `impl` (e.g., `impl Eq for int`) that @@ -955,7 +960,7 @@ fn substitute_normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx /// Given a trait `trait_ref`, iterates the vtable entries /// that come from `trait_ref`, including its supertraits. -#[inline] // FIXME(#35870) Avoid closures being unexported due to impl Trait. +#[inline] // FIXME(#35870): avoid closures being unexported due to `impl Trait`. fn vtable_methods<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 2909daf22b3..fe40141a5e1 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -36,7 +36,7 @@ pub enum ObjectSafetyViolation { SizedSelf, /// Supertrait reference references `Self` an in illegal location - /// (e.g. `trait Foo : Bar`) + /// (e.g., `trait Foo : Bar`) SupertraitSelf, /// Method has something illegal @@ -81,7 +81,7 @@ pub enum MethodViolationCode { /// e.g., `fn foo(&self, x: Self)` or `fn foo(&self) -> Self` ReferencesSelf, - /// e.g. `fn foo(&self) where Self: Clone` + /// e.g., `fn foo(&self) where Self: Clone` WhereClauseReferencesSelf(Span), /// e.g., `fn foo()` @@ -190,7 +190,26 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { // In the case of a trait predicate, we can skip the "self" type. data.skip_binder().input_types().skip(1).any(|t| t.has_self_ty()) } - ty::Predicate::Projection(..) | + ty::Predicate::Projection(ref data) => { + // And similarly for projections. This should be redundant with + // the previous check because any projection should have a + // matching `Trait` predicate with the same inputs, but we do + // the check to be safe. + // + // Note that we *do* allow projection *outputs* to contain + // `self` (i.e., `trait Foo: Bar { type Result; }`), + // we just require the user to specify *both* outputs + // in the object type (i.e., `dyn Foo`). + // + // This is ALT2 in issue #56288, see that for discussion of the + // possible alternatives. + data.skip_binder() + .projection_ty + .trait_ref(self) + .input_types() + .skip(1) + .any(|t| t.has_self_ty()) + } ty::Predicate::WellFormed(..) | ty::Predicate::ObjectSafe(..) | ty::Predicate::TypeOutlives(..) | @@ -343,7 +362,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { } }; - // e.g. Rc<()> + // e.g., Rc<()> let unit_receiver_ty = self.receiver_for_self_ty( receiver_ty, self.mk_unit(), method.def_id ); @@ -357,7 +376,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { trait_def_id, self.mk_region(ty::ReStatic) ); - // e.g. Rc + // e.g., Rc let trait_object_receiver = self.receiver_for_self_ty( receiver_ty, trait_object_ty, method.def_id ); @@ -376,7 +395,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { } /// performs a type substitution to produce the version of receiver_ty when `Self = self_ty` - /// e.g. for receiver_ty = `Rc` and self_ty = `Foo`, returns `Rc` + /// e.g., for receiver_ty = `Rc` and self_ty = `Foo`, returns `Rc` fn receiver_for_self_ty( self, receiver_ty: Ty<'tcx>, self_ty: Ty<'tcx>, method_def_id: DefId ) -> Ty<'tcx> { @@ -451,7 +470,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { /// /// The only case where the receiver is not dispatchable, but is still a valid receiver /// type (just not object-safe), is when there is more than one level of pointer indirection. - /// e.g. `self: &&Self`, `self: &Rc`, `self: Box>`. In these cases, there + /// e.g., `self: &&Self`, `self: &Rc`, `self: Box>`. In these cases, there /// is no way, or at least no inexpensive way, to coerce the receiver from the version where /// `Self = dyn Trait` to the version where `Self = T`, where `T` is the unknown erased type /// contained by the trait object, because the object that needs to be coerced is behind diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 1d3d66e82f1..5717a76f1cf 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -70,7 +70,7 @@ pub enum Reveal { /// be observable directly by the user, `Reveal::All` /// should not be used by checks which may expose /// type equality or type contents to the user. - /// There are some exceptions, e.g. around OIBITS and + /// There are some exceptions, e.g., around OIBITS and /// transmute-checking, which expose some details, but /// not the whole concrete type of the `impl Trait`. All, @@ -608,7 +608,7 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>( // created (and hence the new ones will quickly be // discarded as duplicated). But when doing trait // evaluation this is not the case, and dropping the trait - // evaluations can causes ICEs (e.g. #43132). + // evaluations can causes ICEs (e.g., #43132). debug!("opt_normalize_projection_type: \ found normalized ty `{:?}`", ty); @@ -1589,7 +1589,7 @@ fn assoc_ty_def<'cx, 'gcx, 'tcx>( /// When working with a fulfillment context, the derived obligations of each /// projection cache entry will be registered on the fulfillcx, so any users /// that can wait for a fulfillcx fixed point need not care about this. However, -/// users that don't wait for a fixed point (e.g. trait evaluation) have to +/// users that don't wait for a fixed point (e.g., trait evaluation) have to /// resolve the obligations themselves to make sure the projected result is /// ok and avoid issues like #43132. /// @@ -1637,7 +1637,7 @@ enum ProjectionCacheEntry<'tcx> { NormalizedTy(NormalizedTy<'tcx>), } -// NB: intentionally not Clone +// N.B., intentionally not Clone pub struct ProjectionCacheSnapshot { snapshot: Snapshot, } diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs index b8bf0fcc153..f506c47371c 100644 --- a/src/librustc/traits/query/dropck_outlives.rs +++ b/src/librustc/traits/query/dropck_outlives.rs @@ -55,8 +55,8 @@ impl<'cx, 'gcx, 'tcx> At<'cx, 'gcx, 'tcx> { let c_ty = self.infcx.canonicalize_query(&self.param_env.and(ty), &mut orig_values); let span = self.cause.span; debug!("c_ty = {:?}", c_ty); - match &gcx.dropck_outlives(c_ty) { - Ok(result) if result.is_proven() => { + if let Ok(result) = &gcx.dropck_outlives(c_ty) { + if result.is_proven() { if let Ok(InferOk { value, obligations }) = self.infcx.instantiate_query_response_and_region_obligations( self.cause, @@ -72,8 +72,6 @@ impl<'cx, 'gcx, 'tcx> At<'cx, 'gcx, 'tcx> { }; } } - - _ => { /* fallthrough to error-handling code below */ } } // Errors and ambiuity in dropck occur in two cases: @@ -82,10 +80,11 @@ impl<'cx, 'gcx, 'tcx> At<'cx, 'gcx, 'tcx> { // Either of these should have created an error before. tcx.sess .delay_span_bug(span, "dtorck encountered internal error"); - return InferOk { + + InferOk { value: vec![], obligations: vec![], - }; + } } } @@ -102,7 +101,7 @@ impl<'tcx> DropckOutlivesResult<'tcx> { span: Span, ty: Ty<'tcx>, ) { - for overflow_ty in self.overflows.iter().take(1) { + if let Some(overflow_ty) = self.overflows.iter().next() { let mut err = struct_span_err!( tcx.sess, span, @@ -228,7 +227,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) -> // (T1..Tn) and closures have same properties as T1..Tn -- // check if *any* of those are trivial. - ty::Tuple(ref tys) => tys.iter().cloned().all(|t| trivial_dropck_outlives(tcx, t)), + ty::Tuple(ref tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t)), ty::Closure(def_id, ref substs) => substs .upvar_tys(def_id, tcx) .all(|t| trivial_dropck_outlives(tcx, t)), diff --git a/src/librustc/traits/query/method_autoderef.rs b/src/librustc/traits/query/method_autoderef.rs new file mode 100644 index 00000000000..175883eb2a7 --- /dev/null +++ b/src/librustc/traits/query/method_autoderef.rs @@ -0,0 +1,55 @@ +// 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 rustc_data_structures::sync::Lrc; +use infer::canonical::{Canonical, QueryResponse}; +use ty::Ty; + +#[derive(Debug)] +pub struct CandidateStep<'tcx> { + pub self_ty: Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>, + pub autoderefs: usize, + // true if the type results from a dereference of a raw pointer. + // when assembling candidates, we include these steps, but not when + // picking methods. This so that if we have `foo: *const Foo` and `Foo` has methods + // `fn by_raw_ptr(self: *const Self)` and `fn by_ref(&self)`, then + // `foo.by_raw_ptr()` will work and `foo.by_ref()` won't. + pub from_unsafe_deref: bool, + pub unsize: bool, +} + +#[derive(Clone, Debug)] +pub struct MethodAutoderefStepsResult<'tcx> { + /// The valid autoderef steps that could be find. + pub steps: Lrc>>, + /// If Some(T), a type autoderef reported an error on. + pub opt_bad_ty: Option>>, + /// If `true`, `steps` has been truncated due to reaching the + /// recursion limit. + pub reached_recursion_limit: bool, +} + +#[derive(Debug)] +pub struct MethodAutoderefBadTy<'tcx> { + pub reached_raw_pointer: bool, + pub ty: Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>, +} + +impl_stable_hash_for!(struct MethodAutoderefBadTy<'tcx> { + reached_raw_pointer, ty +}); + +impl_stable_hash_for!(struct MethodAutoderefStepsResult<'tcx> { + reached_recursion_limit, steps, opt_bad_ty +}); + +impl_stable_hash_for!(struct CandidateStep<'tcx> { + self_ty, autoderefs, from_unsafe_deref, unsize +}); diff --git a/src/librustc/traits/query/mod.rs b/src/librustc/traits/query/mod.rs index 13683d85444..b11cb737764 100644 --- a/src/librustc/traits/query/mod.rs +++ b/src/librustc/traits/query/mod.rs @@ -21,6 +21,7 @@ use ty::{self, Ty}; pub mod dropck_outlives; pub mod evaluate_obligation; +pub mod method_autoderef; pub mod normalize; pub mod normalize_erasing_regions; pub mod outlives_bounds; diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index fb4c9f3bad7..d46389b0ee2 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! See [rustc guide] for more info on how this works. +//! Candidate selection. See the [rustc guide] for more information on how this works. //! //! [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/resolution.html#selection @@ -44,7 +44,7 @@ use infer::{InferCtxt, InferOk, TypeFreshener}; use middle::lang_items; use mir::interpret::GlobalId; use ty::fast_reject; -use ty::relate::TypeRelation; +use ty::relate::{TypeRelation, TraitObjectMode}; use ty::subst::{Subst, Substs}; use ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable}; @@ -69,10 +69,10 @@ pub struct SelectionContext<'cx, 'gcx: 'cx + 'tcx, 'tcx: 'cx> { /// require themselves. freshener: TypeFreshener<'cx, 'gcx, 'tcx>, - /// If true, indicates that the evaluation should be conservative + /// If `true`, indicates that the evaluation should be conservative /// and consider the possibility of types outside this crate. /// This comes up primarily when resolving ambiguity. Imagine - /// there is some trait reference `$0 : Bar` where `$0` is an + /// there is some trait reference `$0: Bar` where `$0` is an /// inference variable. If `intercrate` is true, then we can never /// say for sure that this reference is not implemented, even if /// there are *no impls at all for `Bar`*, because `$0` could be @@ -80,7 +80,7 @@ pub struct SelectionContext<'cx, 'gcx: 'cx + 'tcx, 'tcx: 'cx> { /// `Bar`. This is the suitable mode for coherence. Elsewhere, /// though, we set this to false, because we are only interested /// in types that the user could actually have written --- in - /// other words, we consider `$0 : Bar` to be unimplemented if + /// other words, we consider `$0: Bar` to be unimplemented if /// there is no type that the user could *actually name* that /// would satisfy it. This avoids crippling inference, basically. intercrate: Option, @@ -1170,7 +1170,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // // The selection process begins by examining all in-scope impls, // caller obligations, and so forth and assembling a list of - // candidates. See [rustc guide] for more details. + // candidates. See the [rustc guide] for more details. // // [rustc guide]: // https://rust-lang.github.io/rustc-guide/traits/resolution.html#candidate-assembly @@ -1501,6 +1501,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { return false; } + // Same idea as the above, but for alt trait object modes. These + // should only be used in intercrate mode - better safe than sorry. + if self.infcx.trait_object_mode() != TraitObjectMode::NoSquash { + bug!("using squashing TraitObjectMode outside of intercrate mode? param_env={:?}", + param_env); + } + // Otherwise, we can use the global cache. true } @@ -1615,7 +1622,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { }; if obligation.predicate.skip_binder().self_ty().is_ty_var() { - // Self is a type variable (e.g. `_: AsRef`). + // Self is a type variable (e.g., `_: AsRef`). // // This is somewhat problematic, as the current scheme can't really // handle it turning to be a projection. This does end up as truly @@ -1664,7 +1671,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { self.assemble_candidates_for_unsizing(obligation, &mut candidates); } else { if lang_items.clone_trait() == Some(def_id) { - // Same builtin conditions as `Copy`, i.e. every type which has builtin support + // Same builtin conditions as `Copy`, i.e., every type which has builtin support // for `Copy` also has builtin support for `Clone`, + tuples and arrays of `Clone` // types have builtin support for `Clone`. let clone_conditions = self.copy_clone_conditions(obligation); @@ -2023,7 +2030,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { { candidates.vec.push(ImplCandidate(impl_def_id)); - // NB: we can safely drop the placeholder map + // N.B., we can safely drop the placeholder map // since we are in a probe. mem::drop(placeholder_map); } @@ -2069,7 +2076,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // that this obligation holds. That could be a // where-clause or, in the case of an object type, // it could be that the object type lists the - // trait (e.g. `Foo+Send : Send`). See + // trait (e.g., `Foo+Send : Send`). See // `compile-fail/typeck-default-trait-impl-send-param.rs` // for an example of a test case that exercises // this path. @@ -2097,7 +2104,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ); self.probe(|this, _snapshot| { - // the code below doesn't care about regions, and the + // The code below doesn't care about regions, and the // self-ty here doesn't escape this probe, so just erase // any LBR. let self_ty = this.tcx().erase_late_bound_regions(&obligation.self_ty()); @@ -2145,7 +2152,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { .count(); if upcast_trait_refs > 1 { - // can be upcast in many ways; need more type information + // Can be upcast in many ways; need more type information. candidates.ambiguous = true; } else if upcast_trait_refs == 1 { candidates.vec.push(ObjectCandidate); @@ -2197,8 +2204,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { (&ty::Dynamic(ref data_a, ..), &ty::Dynamic(ref data_b, ..)) => { // Upcasts permit two things: // - // 1. Dropping builtin bounds, e.g. `Foo+Send` to `Foo` - // 2. Tightening the region bound, e.g. `Foo+'a` to `Foo+'b` if `'a : 'b` + // 1. Dropping builtin bounds, e.g., `Foo+Send` to `Foo` + // 2. Tightening the region bound, e.g., `Foo+'a` to `Foo+'b` if `'a : 'b` // // Note that neither of these changes requires any // change at runtime. Eventually this will be @@ -2354,7 +2361,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ImplCandidate(other_def) => { // See if we can toss out `victim` based on specialization. // This requires us to know *for sure* that the `other` impl applies - // i.e. EvaluatedToOk: + // i.e., EvaluatedToOk: if other.evaluation == EvaluatedToOk { match victim.candidate { ImplCandidate(victim_def) => { @@ -2717,7 +2724,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // // Confirmation unifies the output type parameters of the trait // with the values found in the obligation, possibly yielding a - // type error. See [rustc guide] for more details. + // type error. See the [rustc guide] for more details. // // [rustc guide]: // https://rust-lang.github.io/rustc-guide/traits/resolution.html#confirmation @@ -3003,7 +3010,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // are sufficient to determine the impl substs, without // relying on projections in the impl-trait-ref. // - // e.g. `impl> Foo<::T> for V` + // e.g., `impl> Foo<::T> for V` impl_obligations.append(&mut substs.obligations); VtableImplData { @@ -3699,7 +3706,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { previous: &ty::PolyTraitRef<'tcx>, current: &ty::PolyTraitRef<'tcx>, ) -> bool { - let mut matcher = ty::_match::Match::new(self.tcx()); + let mut matcher = ty::_match::Match::new( + self.tcx(), self.infcx.trait_object_mode()); matcher.relate(previous, current).is_ok() } diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 19ef3171b13..70d36e9afe1 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -19,24 +19,24 @@ //! //! [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/specialization.html +pub mod specialization_graph; + +use hir::def_id::DefId; +use infer::{InferCtxt, InferOk}; +use lint; +use traits::{self, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine}; +use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::sync::Lrc; +use syntax_pos::DUMMY_SP; +use traits::select::IntercrateAmbiguityCause; +use ty::{self, TyCtxt, TypeFoldable}; +use ty::subst::{Subst, Substs}; + use super::{SelectionContext, FulfillmentContext}; use super::util::impl_trait_ref_and_oblig; -use rustc_data_structures::fx::FxHashSet; -use hir::def_id::DefId; -use infer::{InferCtxt, InferOk}; -use ty::subst::{Subst, Substs}; -use traits::{self, ObligationCause, TraitEngine}; -use traits::select::IntercrateAmbiguityCause; -use ty::{self, TyCtxt, TypeFoldable}; -use syntax_pos::DUMMY_SP; -use rustc_data_structures::sync::Lrc; - -use lint; - -pub mod specialization_graph; - /// Information pertinent to an overlapping impl error. +#[derive(Debug)] pub struct OverlapError { pub with_impl: DefId, pub trait_desc: String, @@ -85,6 +85,8 @@ pub fn translate_substs<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, source_substs: &'tcx Substs<'tcx>, target_node: specialization_graph::Node) -> &'tcx Substs<'tcx> { + debug!("translate_substs({:?}, {:?}, {:?}, {:?})", + param_env, source_impl, source_substs, target_node); let source_trait_ref = infcx.tcx .impl_trait_ref(source_impl) .unwrap() @@ -119,10 +121,13 @@ pub fn translate_substs<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, /// whichever applies. pub fn find_associated_item<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, + param_env: ty::ParamEnv<'tcx>, item: &ty::AssociatedItem, substs: &'tcx Substs<'tcx>, impl_data: &super::VtableImplData<'tcx, ()>, ) -> (DefId, &'tcx Substs<'tcx>) { + debug!("find_associated_item({:?}, {:?}, {:?}, {:?})", + param_env, item, substs, impl_data); assert!(!substs.needs_infer()); let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap(); @@ -132,7 +137,7 @@ pub fn find_associated_item<'a, 'tcx>( match ancestors.defs(tcx, item.ident, item.kind, trait_def_id).next() { Some(node_item) => { let substs = tcx.infer_ctxt().enter(|infcx| { - let param_env = ty::ParamEnv::reveal_all(); + let param_env = param_env.with_reveal_all(); let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs); let substs = translate_substs(&infcx, param_env, impl_data.impl_def_id, substs, node_item.node); @@ -179,7 +184,7 @@ pub(super) fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // // See RFC 1210 for more details and justification. - // Currently we do not allow e.g. a negative impl to specialize a positive one + // Currently we do not allow e.g., a negative impl to specialize a positive one if tcx.impl_polarity(impl1_def_id) != tcx.impl_polarity(impl2_def_id) { return false; } @@ -219,12 +224,17 @@ fn fulfill_implication<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, source_trait_ref: ty::TraitRef<'tcx>, target_impl: DefId) -> Result<&'tcx Substs<'tcx>, ()> { + debug!("fulfill_implication({:?}, trait_ref={:?} |- {:?} applies)", + param_env, source_trait_ref, target_impl); + let selcx = &mut SelectionContext::new(&infcx); let target_substs = infcx.fresh_substs_for_item(DUMMY_SP, target_impl); let (target_trait_ref, mut obligations) = impl_trait_ref_and_oblig(selcx, param_env, target_impl, target_substs); + debug!("fulfill_implication: target_trait_ref={:?}, obligations={:?}", + target_trait_ref, obligations); // do the impls unify? If not, no specialization. match infcx.at(&ObligationCause::dummy(), param_env) @@ -285,17 +295,18 @@ fn fulfill_implication<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, } // Query provider for `specialization_graph_of`. -pub(super) fn specialization_graph_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - trait_id: DefId) - -> Lrc { +pub(super) fn specialization_graph_provider<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + trait_id: DefId, +) -> Lrc { let mut sg = specialization_graph::Graph::new(); 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 - // negated CrateNum (so remote definitions are visited first) and then - // by a flattened version of the DefIndex. + // negated `CrateNum` (so remote definitions are visited first) and then + // by a flattened version of the `DefIndex`. trait_impls.sort_unstable_by_key(|def_id| { (-(def_id.krate.as_u32() as i64), def_id.index.address_space().index(), @@ -308,8 +319,9 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx let insert_result = sg.insert(tcx, impl_def_id); // Report error if there was one. let (overlap, used_to_be_allowed) = match insert_result { - Err(overlap) => (Some(overlap), false), - Ok(opt_overlap) => (opt_overlap, true) + Err(overlap) => (Some(overlap), None), + Ok(Some(overlap)) => (Some(overlap.error), Some(overlap.kind)), + Ok(None) => (None, None) }; if let Some(overlap) = overlap { @@ -319,15 +331,21 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx String::new(), |ty| { format!(" for type `{}`", ty) }), - if used_to_be_allowed { " (E0119)" } else { "" } + if used_to_be_allowed.is_some() { " (E0119)" } else { "" } ); let impl_span = tcx.sess.source_map().def_span( tcx.span_of_impl(impl_def_id).unwrap() ); - let mut err = if used_to_be_allowed { + let mut err = if let Some(kind) = used_to_be_allowed { + let lint = match kind { + FutureCompatOverlapErrorKind::Issue43355 => + lint::builtin::INCOHERENT_FUNDAMENTAL_IMPLS, + FutureCompatOverlapErrorKind::Issue33140 => + lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS, + }; tcx.struct_span_lint_node( - lint::builtin::INCOHERENT_FUNDAMENTAL_IMPLS, - tcx.hir.as_local_node_id(impl_def_id).unwrap(), + lint, + tcx.hir().as_local_node_id(impl_def_id).unwrap(), impl_span, &msg) } else { diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index db0302f3a90..1a228660306 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -17,6 +17,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, use traits; use ty::{self, TyCtxt, TypeFoldable}; use ty::fast_reject::{self, SimplifiedType}; +use ty::relate::TraitObjectMode; use rustc_data_structures::sync::Lrc; use syntax::ast::Ident; use util::captures::Captures; @@ -29,7 +30,7 @@ use util::nodemap::{DefIdMap, FxHashMap}; /// /// The graph provides two key services: /// -/// - Construction, which implicitly checks for overlapping impls (i.e., impls +/// - Construction. This implicitly checks for overlapping impls (i.e., impls /// that overlap but where neither specializes the other -- an artifact of the /// simple "chain" rule. /// @@ -39,11 +40,11 @@ use util::nodemap::{DefIdMap, FxHashMap}; /// has at most one parent. #[derive(RustcEncodable, RustcDecodable)] pub struct Graph { - // all impls have a parent; the "root" impls have as their parent the def_id - // of the trait + // All impls have a parent; the "root" impls have as their parent the `def_id` + // of the trait. parent: DefIdMap, - // the "root" impls are found by looking up the trait's def_id. + // The "root" impls are found by looking up the trait's def_id. children: DefIdMap, } @@ -68,10 +69,22 @@ struct Children { blanket_impls: Vec, } +#[derive(Copy, Clone, Debug)] +pub enum FutureCompatOverlapErrorKind { + Issue43355, + Issue33140, +} + +#[derive(Debug)] +pub struct FutureCompatOverlapError { + pub error: OverlapError, + pub kind: FutureCompatOverlapErrorKind +} + /// The result of attempting to insert an impl into a group of children. enum Inserted { /// The impl was inserted as a new child in this group of children. - BecameNewSibling(Option), + BecameNewSibling(Option), /// The impl should replace existing impls [X1, ..], because the impl specializes X1, X2, etc. ReplaceChildren(Vec), @@ -81,7 +94,7 @@ enum Inserted { } impl<'a, 'gcx, 'tcx> Children { - /// Insert an impl into this set of children without comparing to any existing impls + /// Insert an impl into this set of children without comparing to any existing impls. fn insert_blindly(&mut self, tcx: TyCtxt<'a, 'gcx, 'tcx>, impl_def_id: DefId) { @@ -132,10 +145,12 @@ impl<'a, 'gcx, 'tcx> Children { simplified_self, ); - for possible_sibling in match simplified_self { - Some(sty) => self.filtered(sty), - None => self.iter(), - } { + let possible_siblings = match simplified_self { + Some(sty) => PotentialSiblings::Filtered(self.filtered(sty)), + None => PotentialSiblings::Unfiltered(self.iter()), + }; + + for possible_sibling in possible_siblings { debug!( "insert: impl_def_id={:?}, simplified_self={:?}, possible_sibling={:?}", impl_def_id, @@ -144,13 +159,13 @@ impl<'a, 'gcx, 'tcx> Children { ); let overlap_error = |overlap: traits::coherence::OverlapResult<'_>| { - // overlap, but no specialization; error out + // Found overlap, but no specialization; error out. let trait_ref = overlap.impl_header.trait_ref.unwrap(); let self_ty = trait_ref.self_ty(); OverlapError { with_impl: possible_sibling, trait_desc: trait_ref.to_string(), - // only report the Self type if it has at least + // Only report the `Self` type if it has at least // some outer concrete shell; otherwise, it's // not adding much information. self_desc: if self_ty.has_concrete_skeleton() { @@ -168,6 +183,7 @@ impl<'a, 'gcx, 'tcx> Children { possible_sibling, impl_def_id, traits::IntercrateMode::Issue43355, + TraitObjectMode::NoSquash, |overlap| { if tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) { return Ok((false, false)); @@ -189,7 +205,7 @@ impl<'a, 'gcx, 'tcx> Children { debug!("descending as child of TraitRef {:?}", tcx.impl_trait_ref(possible_sibling).unwrap()); - // the impl specializes possible_sibling + // The impl specializes `possible_sibling`. return Ok(Inserted::ShouldRecurseOn(possible_sibling)); } else if ge && !le { debug!("placing as parent of TraitRef {:?}", @@ -198,12 +214,36 @@ impl<'a, 'gcx, 'tcx> Children { replace_children.push(possible_sibling); } else { if !tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) { + // do future-compat checks for overlap. Have issue #43355 + // errors overwrite issue #33140 errors when both are present. + traits::overlapping_impls( tcx, possible_sibling, impl_def_id, traits::IntercrateMode::Fixed, - |overlap| last_lint = Some(overlap_error(overlap)), + TraitObjectMode::SquashAutoTraitsIssue33140, + |overlap| { + last_lint = Some(FutureCompatOverlapError { + error: overlap_error(overlap), + kind: FutureCompatOverlapErrorKind::Issue33140 + }); + }, + || (), + ); + + traits::overlapping_impls( + tcx, + possible_sibling, + impl_def_id, + traits::IntercrateMode::Fixed, + TraitObjectMode::NoSquash, + |overlap| { + last_lint = Some(FutureCompatOverlapError { + error: overlap_error(overlap), + kind: FutureCompatOverlapErrorKind::Issue43355 + }); + }, || (), ); } @@ -216,20 +256,43 @@ impl<'a, 'gcx, 'tcx> Children { return Ok(Inserted::ReplaceChildren(replace_children)); } - // no overlap with any potential siblings, so add as a new sibling + // No overlap with any potential siblings, so add as a new sibling. debug!("placing as new sibling"); self.insert_blindly(tcx, impl_def_id); Ok(Inserted::BecameNewSibling(last_lint)) } - fn iter(&mut self) -> Box + '_> { + fn iter(&mut self) -> impl Iterator + '_ { let nonblanket = self.nonblanket_impls.iter_mut().flat_map(|(_, v)| v.iter()); - Box::new(self.blanket_impls.iter().chain(nonblanket).cloned()) + self.blanket_impls.iter().chain(nonblanket).cloned() } - fn filtered(&mut self, sty: SimplifiedType) -> Box + '_> { + fn filtered(&mut self, sty: SimplifiedType) -> impl Iterator + '_ { let nonblanket = self.nonblanket_impls.entry(sty).or_default().iter(); - Box::new(self.blanket_impls.iter().chain(nonblanket).cloned()) + self.blanket_impls.iter().chain(nonblanket).cloned() + } +} + +// A custom iterator used by Children::insert +enum PotentialSiblings + where I: Iterator, + J: Iterator +{ + Unfiltered(I), + Filtered(J) +} + +impl Iterator for PotentialSiblings + where I: Iterator, + J: Iterator +{ + type Item = DefId; + + fn next(&mut self) -> Option { + match *self { + PotentialSiblings::Unfiltered(ref mut iter) => iter.next(), + PotentialSiblings::Filtered(ref mut iter) => iter.next() + } } } @@ -247,7 +310,7 @@ impl<'a, 'gcx, 'tcx> Graph { pub fn insert(&mut self, tcx: TyCtxt<'a, 'gcx, 'tcx>, impl_def_id: DefId) - -> Result, OverlapError> { + -> Result, OverlapError> { assert!(impl_def_id.is_local()); let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); @@ -256,7 +319,7 @@ impl<'a, 'gcx, 'tcx> Graph { debug!("insert({:?}): inserting TraitRef {:?} into specialization graph", impl_def_id, trait_ref); - // if the reference itself contains an earlier error (e.g., due to a + // If the reference itself contains an earlier error (e.g., due to a // resolution failure), then we just insert the impl at the top level of // the graph and claim that there's no overlap (in order to suppress // bogus errors). @@ -275,7 +338,7 @@ impl<'a, 'gcx, 'tcx> Graph { let mut last_lint = None; let simplified = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false); - // Descend the specialization tree, where `parent` is the current parent node + // Descend the specialization tree, where `parent` is the current parent node. loop { use self::Inserted::*; @@ -313,7 +376,7 @@ impl<'a, 'gcx, 'tcx> Graph { siblings.insert_blindly(tcx, impl_def_id); } - // Set G's parent to N and N's parent to P + // Set G's parent to N and N's parent to P. for &grand_child_to_be in &grand_children_to_be { self.parent.insert(grand_child_to_be, impl_def_id); } @@ -429,7 +492,8 @@ impl NodeItem { impl<'a, 'gcx, 'tcx> Ancestors { /// Search the items from the given ancestors, returning each definition /// with the given name and the given kind. - #[inline] // FIXME(#35870) Avoid closures being unexported due to impl Trait. + // FIXME(#35870): avoid closures being unexported due to `impl Trait`. + #[inline] pub fn defs( self, tcx: TyCtxt<'a, 'gcx, 'tcx>, diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 36538ac0889..36e93cc7740 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -33,8 +33,8 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for traits::Obligation<'tcx, O> { if ty::tls::with(|tcx| tcx.sess.verbose()) { write!( f, - "Obligation(predicate={:?},cause={:?},depth={})", - self.predicate, self.cause, self.recursion_depth + "Obligation(predicate={:?},cause={:?},param_env={:?},depth={})", + self.predicate, self.cause, self.param_env, self.recursion_depth ) } else { write!( diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 3a882506b41..48db72c1f56 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -8,13 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use hir; use hir::def_id::DefId; -use ty::subst::{Kind, Subst, Substs}; +use traits::specialize::specialization_graph::NodeItem; use ty::{self, Ty, TyCtxt, ToPredicate, ToPolyTraitRef}; use ty::outlives::Component; +use ty::subst::{Kind, Subst, Substs}; use util::nodemap::FxHashSet; -use hir::{self}; -use traits::specialize::specialization_graph::NodeItem; use super::{Obligation, ObligationCause, PredicateObligation, SelectionContext, Normalized}; @@ -535,9 +535,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn impl_is_default(self, node_item_def_id: DefId) -> bool { - match self.hir.as_local_node_id(node_item_def_id) { + match self.hir().as_local_node_id(node_item_def_id) { Some(node_id) => { - let item = self.hir.expect_item(node_id); + let item = self.hir().expect_item(node_id); if let hir::ItemKind::Impl(_, _, defaultness, ..) = item.node { defaultness.is_default() } else { diff --git a/src/librustc/ty/_match.rs b/src/librustc/ty/_match.rs index d20b6d36199..29067bf518d 100644 --- a/src/librustc/ty/_match.rs +++ b/src/librustc/ty/_match.rs @@ -29,17 +29,24 @@ use ty::relate::{self, Relate, TypeRelation, RelateResult}; /// important thing about the result is Ok/Err. Also, matching never /// affects any type variables or unification state. pub struct Match<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { - tcx: TyCtxt<'a, 'gcx, 'tcx> + tcx: TyCtxt<'a, 'gcx, 'tcx>, + trait_object_mode: relate::TraitObjectMode } impl<'a, 'gcx, 'tcx> Match<'a, 'gcx, 'tcx> { - pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Match<'a, 'gcx, 'tcx> { - Match { tcx } + pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, + trait_object_mode: relate::TraitObjectMode) + -> Match<'a, 'gcx, 'tcx> { + Match { tcx, trait_object_mode } } } impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Match<'a, 'gcx, 'tcx> { fn tag(&self) -> &'static str { "Match" } + fn trait_object_mode(&self) -> relate::TraitObjectMode { + self.trait_object_mode + } + fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { self.tcx } fn a_is_expected(&self) -> bool { true } // irrelevant diff --git a/src/librustc/ty/adjustment.rs b/src/librustc/ty/adjustment.rs index 83521c5f724..d91ae7e120f 100644 --- a/src/librustc/ty/adjustment.rs +++ b/src/librustc/ty/adjustment.rs @@ -83,7 +83,7 @@ pub enum Adjust<'tcx> { /// Take the address and produce either a `&` or `*` pointer. Borrow(AutoBorrow<'tcx>), - /// Unsize a pointer/reference value, e.g. `&[T; n]` to + /// Unsize a pointer/reference value, e.g., `&[T; n]` to /// `&[T]`. Note that the source could be a thin or fat pointer. /// This will do things like convert thin pointers to fat /// pointers, or convert structs containing thin pointers to diff --git a/src/librustc/ty/codec.rs b/src/librustc/ty/codec.rs index 8738f574148..5ad7d247fe4 100644 --- a/src/librustc/ty/codec.rs +++ b/src/librustc/ty/codec.rs @@ -92,7 +92,7 @@ pub fn encode_with_shorthand(encoder: &mut E, let leb128_bits = len * 7; // Check that the shorthand is a not longer than the - // full encoding itself, i.e. it's an obvious win. + // full encoding itself, i.e., it's an obvious win. if leb128_bits >= 64 || (shorthand as u64) < (1 << leb128_bits) { cache(encoder).insert(value.clone(), shorthand); } diff --git a/src/librustc/ty/constness.rs b/src/librustc/ty/constness.rs index e32913b8905..3741f4051b8 100644 --- a/src/librustc/ty/constness.rs +++ b/src/librustc/ty/constness.rs @@ -5,7 +5,6 @@ use ty::TyCtxt; use syntax_pos::symbol::Symbol; use hir::map::blocks::FnLikeNode; use syntax::attr; -use rustc_target::spec::abi; impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { /// Whether the `def_id` counts as const fn in your current crate, considering all active @@ -40,19 +39,12 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { /// Returns true if this function must conform to `min_const_fn` pub fn is_min_const_fn(self, def_id: DefId) -> bool { + // Bail out if the signature doesn't contain `const` + if !self.is_const_fn_raw(def_id) { + return false; + } + if self.features().staged_api { - // some intrinsics are waved through if called inside the - // standard library. Users never need to call them directly - if let abi::Abi::RustIntrinsic = self.fn_sig(def_id).abi() { - assert!(!self.is_const_fn(def_id)); - match &self.item_name(def_id).as_str()[..] { - | "size_of" - | "min_align_of" - | "needs_drop" - => return true, - _ => {}, - } - } // in order for a libstd function to be considered min_const_fn // it needs to be stable and have no `rustc_const_unstable` attribute match self.lookup_stability(def_id) { @@ -75,10 +67,10 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { pub fn provide<'tcx>(providers: &mut Providers<'tcx>) { /// only checks whether the function has a `const` modifier fn is_const_fn_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> bool { - let node_id = tcx.hir.as_local_node_id(def_id) + let node_id = tcx.hir().as_local_node_id(def_id) .expect("Non-local call to local provider is_const_fn"); - if let Some(fn_like) = FnLikeNode::from_node(tcx.hir.get(node_id)) { + if let Some(fn_like) = FnLikeNode::from_node(tcx.hir().get(node_id)) { fn_like.constness() == hir::Constness::Const } else { false diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 42a4de1682c..9883752da0b 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -72,6 +72,7 @@ use std::ops::{Deref, Bound}; use std::iter; use std::sync::mpsc; use std::sync::Arc; +use std::marker::PhantomData; use rustc_target::spec::abi; use syntax::ast::{self, NodeId}; use syntax::attr; @@ -86,6 +87,7 @@ use hir; pub struct AllArenas<'tcx> { pub global: WorkerLocal>, pub interner: SyncDroplessArena, + global_ctxt: Option>, } impl<'tcx> AllArenas<'tcx> { @@ -93,6 +95,7 @@ impl<'tcx> AllArenas<'tcx> { AllArenas { global: WorkerLocal::new(|_| GlobalArenas::default()), interner: SyncDroplessArena::default(), + global_ctxt: None, } } } @@ -250,11 +253,11 @@ fn validate_hir_id_for_typeck_tables(local_id_root: Option, if let Some(local_id_root) = local_id_root { if hir_id.owner != local_id_root.index { ty::tls::with(|tcx| { - let node_id = tcx.hir.hir_to_node_id(hir_id); + let node_id = tcx.hir().hir_to_node_id(hir_id); bug!("node {} with HirId::owner {:?} cannot be placed in \ TypeckTables with local_id_root {:?}", - tcx.hir.node_to_string(node_id), + tcx.hir().node_to_string(node_id), DefId::local(hir_id.owner), local_id_root) }); @@ -530,8 +533,8 @@ impl<'tcx> TypeckTables<'tcx> { self.node_id_to_type_opt(id).unwrap_or_else(|| bug!("node_id_to_type: no type for node `{}`", tls::with(|tcx| { - let id = tcx.hir.hir_to_node_id(id); - tcx.hir.node_to_string(id) + let id = tcx.hir().hir_to_node_id(id); + tcx.hir().node_to_string(id) })) ) } @@ -587,7 +590,7 @@ impl<'tcx> TypeckTables<'tcx> { // auto-ref. The type returned by this function does not consider such // adjustments. See `expr_ty_adjusted()` instead. // - // NB (2): This type doesn't provide type parameter substitutions; e.g. if you + // NB (2): This type doesn't provide type parameter substitutions; e.g., if you // ask for the type of "id" in "id(3)", it will return "fn(&isize) -> isize" // instead of "fn(ty) -> T with T = isize". pub fn expr_ty(&self, expr: &hir::Expr) -> Ty<'tcx> { @@ -869,12 +872,13 @@ pub struct FreeRegionInfo { /// [rustc guide]: https://rust-lang.github.io/rustc-guide/ty.html #[derive(Copy, Clone)] pub struct TyCtxt<'a, 'gcx: 'tcx, 'tcx: 'a> { - gcx: &'a GlobalCtxt<'gcx>, - interners: &'a CtxtInterners<'tcx> + gcx: &'gcx GlobalCtxt<'gcx>, + interners: &'tcx CtxtInterners<'tcx>, + dummy: PhantomData<&'a ()>, } -impl<'a, 'gcx, 'tcx> Deref for TyCtxt<'a, 'gcx, 'tcx> { - type Target = &'a GlobalCtxt<'gcx>; +impl<'gcx> Deref for TyCtxt<'_, 'gcx, '_> { + type Target = &'gcx GlobalCtxt<'gcx>; #[inline(always)] fn deref(&self) -> &Self::Target { &self.gcx @@ -903,7 +907,7 @@ pub struct GlobalCtxt<'tcx> { /// Export map produced by name resolution. export_map: FxHashMap>>, - pub hir: hir_map::Map<'tcx>, + hir_map: hir_map::Map<'tcx>, /// A map from DefPathHash -> DefId. Includes DefIds from the local crate /// as well as all upstream crates. Only populated in incremental mode. @@ -946,7 +950,7 @@ pub struct GlobalCtxt<'tcx> { /// Stores the value of constants (and deduplicates the actual memory) allocation_interner: Lock>, - pub alloc_map: Lock>, + pub alloc_map: Lock>, layout_interner: Lock>, @@ -964,13 +968,19 @@ pub struct GlobalCtxt<'tcx> { impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Get the global TyCtxt. #[inline] - pub fn global_tcx(self) -> TyCtxt<'a, 'gcx, 'gcx> { + pub fn global_tcx(self) -> TyCtxt<'gcx, 'gcx, 'gcx> { TyCtxt { gcx: self.gcx, interners: &self.gcx.global_interners, + dummy: PhantomData, } } + #[inline(always)] + pub fn hir(self) -> &'a hir_map::Map<'gcx> { + &self.hir_map + } + pub fn alloc_generics(self, generics: ty::Generics) -> &'gcx ty::Generics { self.global_arenas.generics.alloc(generics) } @@ -1100,7 +1110,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { cstore: &'tcx CrateStoreDyn, local_providers: ty::query::Providers<'tcx>, extern_providers: ty::query::Providers<'tcx>, - arenas: &'tcx AllArenas<'tcx>, + arenas: &'tcx mut AllArenas<'tcx>, resolutions: ty::Resolutions, hir: hir_map::Map<'tcx>, on_disk_query_result_cache: query::OnDiskCache<'tcx>, @@ -1161,7 +1171,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { Lrc::new(StableVec::new(v))); } - let gcx = &GlobalCtxt { + arenas.global_ctxt = Some(GlobalCtxt { sess: s, cstore, global_arenas: &arenas.global, @@ -1186,7 +1196,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { .map(|(id, sp)| (hir.local_def_id(id), sp)) .collect(), extern_prelude: resolutions.extern_prelude, - hir, + hir_map: hir, def_path_hash_to_def_id, queries: query::Queries::new( providers, @@ -1204,7 +1214,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { alloc_map: Lock::new(interpret::AllocMap::new()), tx_to_llvm_workers: Lock::new(tx), output_filenames: Arc::new(output_filenames.clone()), - }; + }); + + let gcx = arenas.global_ctxt.as_ref().unwrap(); sync::assert_send_val(&gcx); @@ -1272,7 +1284,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn def_key(self, id: DefId) -> hir_map::DefKey { if id.is_local() { - self.hir.def_key(id) + self.hir().def_key(id) } else { self.cstore.def_key(id) } @@ -1285,7 +1297,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// be a non-local `DefPath`. pub fn def_path(self, id: DefId) -> hir_map::DefPath { if id.is_local() { - self.hir.def_path(id) + self.hir().def_path(id) } else { self.cstore.def_path(id) } @@ -1294,7 +1306,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { #[inline] pub fn def_path_hash(self, def_id: DefId) -> hir_map::DefPathHash { if def_id.is_local() { - self.hir.definitions().def_path_hash(def_id.index) + self.hir().definitions().def_path_hash(def_id.index) } else { self.cstore.def_path_hash(def_id) } @@ -1331,12 +1343,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.cstore.crate_data_as_rc_any(cnum) } + #[inline(always)] pub fn create_stable_hashing_context(self) -> StableHashingContext<'a> { - let krate = self.dep_graph.with_ignore(|| self.gcx.hir.krate()); + let krate = self.gcx.hir_map.forest.untracked_krate(); StableHashingContext::new(self.sess, krate, - self.hir.definitions(), + self.hir().definitions(), self.cstore) } @@ -1493,12 +1506,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { BorrowckMode::Ast => match self.sess.edition() { Edition::Edition2015 => BorrowckMode::Ast, Edition::Edition2018 => BorrowckMode::Migrate, - - // For now, future editions mean Migrate. (But it - // would make a lot of sense for it to be changed to - // `BorrowckMode::Mir`, depending on how we plan to - // time the forcing of full migration to NLL.) - _ => BorrowckMode::Migrate, }, } } @@ -1530,10 +1537,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { _ => return None, // not a free region }; - let node_id = self.hir + let node_id = self.hir() .as_local_node_id(suitable_region_binding_scope) .unwrap(); - let is_impl_item = match self.hir.find(node_id) { + 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) @@ -1553,8 +1560,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { scope_def_id: DefId, ) -> Option> { // HACK: `type_of_def_id()` will fail on these (#55796), so return None - let node_id = self.hir.as_local_node_id(scope_def_id).unwrap(); - match self.hir.get(node_id) { + let node_id = self.hir().as_local_node_id(scope_def_id).unwrap(); + match self.hir().get(node_id) { Node::Item(item) => { match item.node { ItemKind::Fn(..) => { /* type_of_def_id() will work */ } @@ -1610,20 +1617,25 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { } } -impl<'gcx: 'tcx, 'tcx> GlobalCtxt<'gcx> { +impl<'gcx> GlobalCtxt<'gcx> { /// Call the closure with a local `TyCtxt` using the given arena. - pub fn enter_local( - &self, + /// `interners` is a slot passed so we can create a CtxtInterners + /// with the same lifetime as `arena`. + pub fn enter_local<'tcx, F, R>( + &'gcx self, arena: &'tcx SyncDroplessArena, + interners: &'tcx mut Option>, f: F ) -> R where - F: for<'a> FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R + F: FnOnce(TyCtxt<'tcx, 'gcx, 'tcx>) -> R, + 'gcx: 'tcx, { - let interners = CtxtInterners::new(arena); + *interners = Some(CtxtInterners::new(&arena)); let tcx = TyCtxt { gcx: self, - interners: &interners, + interners: interners.as_ref().unwrap(), + dummy: PhantomData, }; ty::tls::with_related_context(tcx.global_tcx(), |icx| { let new_icx = ty::tls::ImplicitCtxt { @@ -1632,8 +1644,8 @@ impl<'gcx: 'tcx, 'tcx> GlobalCtxt<'gcx> { layout_depth: icx.layout_depth, task: icx.task, }; - ty::tls::enter_context(&new_icx, |new_icx| { - f(new_icx.tcx) + ty::tls::enter_context(&new_icx, |_| { + f(tcx) }) }) } @@ -1655,7 +1667,7 @@ impl<'gcx: 'tcx, 'tcx> GlobalCtxt<'gcx> { /// For Ty, None can be returned if either the type interner doesn't /// contain the TyKind key or if the address of the interned /// pointer differs. The latter case is possible if a primitive type, -/// e.g. `()` or `u8`, was interned in a different context. +/// e.g., `()` or `u8`, was interned in a different context. pub trait Lift<'tcx>: fmt::Debug { type Lifted: fmt::Debug + 'tcx; fn lift_to_tcx<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option; @@ -1873,6 +1885,7 @@ pub mod tls { use std::fmt; use std::mem; + use std::marker::PhantomData; use syntax_pos; use ty::query; use errors::{Diagnostic, TRACK_DIAGNOSTICS}; @@ -1892,10 +1905,10 @@ pub mod tls { /// you should also have access to an ImplicitCtxt through the functions /// in this module. #[derive(Clone)] - pub struct ImplicitCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { + pub struct ImplicitCtxt<'a, 'gcx: 'tcx, 'tcx> { /// The current TyCtxt. Initially created by `enter_global` and updated /// by `enter_local` with a new local interner - pub tcx: TyCtxt<'a, 'gcx, 'tcx>, + pub tcx: TyCtxt<'tcx, 'gcx, 'tcx>, /// The current query job, if any. This is updated by start_job in /// ty::query::plumbing when executing a query @@ -1913,6 +1926,7 @@ pub mod tls { /// to `value` during the call to `f`. It is restored to its previous value after. /// This is used to set the pointer to the new ImplicitCtxt. #[cfg(parallel_queries)] + #[inline] fn set_tlv R, R>(value: usize, f: F) -> R { rayon_core::tlv::with(value, f) } @@ -1920,6 +1934,7 @@ pub mod tls { /// Gets Rayon's thread local variable which is preserved for Rayon jobs. /// This is used to get the pointer to the current ImplicitCtxt. #[cfg(parallel_queries)] + #[inline] fn get_tlv() -> usize { rayon_core::tlv::get() } @@ -1932,6 +1947,7 @@ pub mod tls { /// It is restored to its previous value after. /// This is used to set the pointer to the new ImplicitCtxt. #[cfg(not(parallel_queries))] + #[inline] fn set_tlv R, R>(value: usize, f: F) -> R { let old = get_tlv(); let _reset = OnDrop(move || TLV.with(|tlv| tlv.set(old))); @@ -1948,8 +1964,12 @@ pub mod tls { /// This is a callback from libsyntax as it cannot access the implicit state /// in librustc otherwise fn span_debug(span: syntax_pos::Span, f: &mut fmt::Formatter<'_>) -> fmt::Result { - with(|tcx| { - write!(f, "{}", tcx.sess.source_map().span_to_string(span)) + with_opt(|tcx| { + if let Some(tcx) = tcx { + write!(f, "{}", tcx.sess.source_map().span_to_string(span)) + } else { + syntax_pos::default_span_debug(span, f) + } }) } @@ -1992,6 +2012,7 @@ pub mod tls { } /// Sets `context` as the new current ImplicitCtxt for the duration of the function `f` + #[inline] pub fn enter_context<'a, 'gcx: 'tcx, 'tcx, F, R>(context: &ImplicitCtxt<'a, 'gcx, 'tcx>, f: F) -> R where F: FnOnce(&ImplicitCtxt<'a, 'gcx, 'tcx>) -> R @@ -2005,8 +2026,8 @@ pub mod tls { /// creating a initial TyCtxt and ImplicitCtxt. /// This happens once per rustc session and TyCtxts only exists /// inside the `f` function. - pub fn enter_global<'gcx, F, R>(gcx: &GlobalCtxt<'gcx>, f: F) -> R - where F: for<'a> FnOnce(TyCtxt<'a, 'gcx, 'gcx>) -> R + pub fn enter_global<'gcx, F, R>(gcx: &'gcx GlobalCtxt<'gcx>, f: F) -> R + where F: FnOnce(TyCtxt<'gcx, 'gcx, 'gcx>) -> R { with_thread_locals(|| { // Update GCX_PTR to indicate there's a GlobalCtxt available @@ -2021,6 +2042,7 @@ pub mod tls { let tcx = TyCtxt { gcx, interners: &gcx.global_interners, + dummy: PhantomData, }; let icx = ImplicitCtxt { tcx, @@ -2050,6 +2072,7 @@ pub mod tls { let tcx = TyCtxt { gcx, interners: &gcx.global_interners, + dummy: PhantomData, }; let icx = ImplicitCtxt { query: None, @@ -2061,6 +2084,7 @@ pub mod tls { } /// Allows access to the current ImplicitCtxt in a closure if one is available + #[inline] pub fn with_context_opt(f: F) -> R where F: for<'a, 'gcx, 'tcx> FnOnce(Option<&ImplicitCtxt<'a, 'gcx, 'tcx>>) -> R { @@ -2078,6 +2102,7 @@ pub mod tls { /// Allows access to the current ImplicitCtxt. /// Panics if there is no ImplicitCtxt available + #[inline] pub fn with_context(f: F) -> R where F: for<'a, 'gcx, 'tcx> FnOnce(&ImplicitCtxt<'a, 'gcx, 'tcx>) -> R { @@ -2089,6 +2114,7 @@ pub mod tls { /// with the same 'gcx lifetime as the TyCtxt passed in. /// This will panic if you pass it a TyCtxt which has a different global interner from /// the current ImplicitCtxt's tcx field. + #[inline] pub fn with_related_context<'a, 'gcx, 'tcx1, F, R>(tcx: TyCtxt<'a, 'gcx, 'tcx1>, f: F) -> R where F: for<'b, 'tcx2> FnOnce(&ImplicitCtxt<'b, 'gcx, 'tcx2>) -> R { @@ -2107,6 +2133,7 @@ pub mod tls { /// is given an ImplicitCtxt with the same 'tcx and 'gcx lifetimes as the TyCtxt passed in. /// This will panic if you pass it a TyCtxt which has a different global interner or /// a different local interner from the current ImplicitCtxt's tcx field. + #[inline] pub fn with_fully_related_context<'a, 'gcx, 'tcx, F, R>(tcx: TyCtxt<'a, 'gcx, 'tcx>, f: F) -> R where F: for<'b> FnOnce(&ImplicitCtxt<'b, 'gcx, 'tcx>) -> R { @@ -2124,6 +2151,7 @@ pub mod tls { /// Allows access to the TyCtxt in the current ImplicitCtxt. /// Panics if there is no ImplicitCtxt available + #[inline] pub fn with(f: F) -> R where F: for<'a, 'gcx, 'tcx> FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R { @@ -2132,6 +2160,7 @@ pub mod tls { /// Allows access to the TyCtxt in the current ImplicitCtxt. /// The closure is passed None if there is no ImplicitCtxt available + #[inline] pub fn with_opt(f: F) -> R where F: for<'a, 'gcx, 'tcx> FnOnce(Option>) -> R { @@ -2229,7 +2258,7 @@ impl<'tcx, T: 'tcx+?Sized> Clone for Interned<'tcx, T> { } impl<'tcx, T: 'tcx+?Sized> Copy for Interned<'tcx, T> {} -// NB: An Interned compares and hashes as a sty. +// N.B., an `Interned` compares and hashes as a sty. impl<'tcx> PartialEq for Interned<'tcx, TyS<'tcx>> { fn eq(&self, other: &Interned<'tcx, TyS<'tcx>>) -> bool { self.0.sty == other.0.sty @@ -2250,7 +2279,7 @@ impl<'tcx: 'lcx, 'lcx> Borrow> for Interned<'tcx, TyS<'tcx>> { } } -// NB: An Interned> compares and hashes as its elements. +// N.B., an `Interned>` compares and hashes as its elements. impl<'tcx, T: PartialEq> PartialEq for Interned<'tcx, List> { fn eq(&self, other: &Interned<'tcx, List>) -> bool { self.0[..] == other.0[..] @@ -2461,7 +2490,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Given a closure signature `sig`, returns an equivalent `fn` /// type with the same signature. Detuples and so forth -- so - /// e.g. if we have a sig with `Fn<(u32, i32)>` then you would get + /// e.g., if we have a sig with `Fn<(u32, i32)>` then you would get /// a `fn(u32, i32)`. pub fn coerce_closure_fn_ty(self, sig: PolyFnSig<'tcx>) -> Ty<'tcx> { let converted_sig = sig.map_bound(|s| { @@ -2710,7 +2739,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { #[inline] pub fn mk_self_type(self) -> Ty<'tcx> { - self.mk_ty_param(0, keywords::SelfType.name().as_interned_str()) + self.mk_ty_param(0, keywords::SelfUpper.name().as_interned_str()) } pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> Kind<'tcx> { @@ -2866,11 +2895,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn lint_hir_note>(self, - lint: &'static Lint, - hir_id: HirId, - span: S, - msg: &str, - note: &str) { + lint: &'static Lint, + hir_id: HirId, + span: S, + msg: &str, + note: &str) { let mut err = self.struct_span_lint_hir(lint, hir_id, span.into(), msg); err.note(note); err.emit() @@ -2901,11 +2930,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.dep_graph.with_ignore(|| { let sets = self.lint_levels(LOCAL_CRATE); loop { - let hir_id = self.hir.definitions().node_to_hir_id(id); + let hir_id = self.hir().definitions().node_to_hir_id(id); if let Some(pair) = sets.level_and_source(lint, hir_id, self.sess) { return pair } - let next = self.hir.get_parent_node(id); + let next = self.hir().get_parent_node(id); if next == id { bug!("lint traversal reached the root of the crate"); } @@ -2921,7 +2950,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { msg: &str) -> DiagnosticBuilder<'tcx> { - let node_id = self.hir.hir_to_node_id(hir_id); + let node_id = self.hir().hir_to_node_id(hir_id); let (level, src) = self.lint_level_at_node(lint, node_id); lint::struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg) } @@ -3013,9 +3042,9 @@ impl InternIteratorElement for Result { } pub fn provide(providers: &mut ty::query::Providers<'_>) { - // FIXME(#44234) - almost all of these queries have no sub-queries and + // FIXME(#44234): almost all of these queries have no sub-queries and // therefore no actual inputs, they're just reading tables calculated in - // resolve! Does this work? Unsure! That's what the issue is about + // resolve! Does this work? Unsure! That's what the issue is about. providers.in_scope_traits_map = |tcx, id| tcx.gcx.trait_map.get(&id).cloned(); providers.module_exports = |tcx, id| tcx.gcx.export_map.get(&id).cloned(); providers.crate_name = |tcx, id| { @@ -3045,16 +3074,16 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { }; providers.lookup_stability = |tcx, id| { assert_eq!(id.krate, LOCAL_CRATE); - let id = tcx.hir.definitions().def_index_to_hir_id(id.index); + let id = tcx.hir().definitions().def_index_to_hir_id(id.index); tcx.stability().local_stability(id) }; providers.lookup_deprecation_entry = |tcx, id| { assert_eq!(id.krate, LOCAL_CRATE); - let id = tcx.hir.definitions().def_index_to_hir_id(id.index); + let id = tcx.hir().definitions().def_index_to_hir_id(id.index); tcx.stability().local_deprecation_entry(id) }; providers.extern_mod_stmt_cnum = |tcx, id| { - let id = tcx.hir.as_local_node_id(id).unwrap(); + let id = tcx.hir().as_local_node_id(id).unwrap(); tcx.cstore.extern_mod_stmt_cnum_untracked(id) }; providers.all_crate_nums = |tcx, cnum| { @@ -3075,10 +3104,10 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { }; providers.is_panic_runtime = |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); - attr::contains_name(tcx.hir.krate_attrs(), "panic_runtime") + attr::contains_name(tcx.hir().krate_attrs(), "panic_runtime") }; providers.is_compiler_builtins = |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); - attr::contains_name(tcx.hir.krate_attrs(), "compiler_builtins") + attr::contains_name(tcx.hir().krate_attrs(), "compiler_builtins") }; } diff --git a/src/librustc/ty/erase_regions.rs b/src/librustc/ty/erase_regions.rs index f53e634a044..a361ad057c7 100644 --- a/src/librustc/ty/erase_regions.rs +++ b/src/librustc/ty/erase_regions.rs @@ -19,7 +19,7 @@ pub(super) fn provide(providers: &mut ty::query::Providers<'_>) { } fn erase_regions_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { - // NB: use `super_fold_with` here. If we used `fold_with`, it + // N.B., use `super_fold_with` here. If we used `fold_with`, it // could invoke the `erase_regions_ty` query recursively. ty.super_fold_with(&mut RegionEraserVisitor { tcx }) } diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs index 8304e363815..bd01dd8cb0c 100644 --- a/src/librustc/ty/fast_reject.rs +++ b/src/librustc/ty/fast_reject.rs @@ -43,6 +43,9 @@ pub enum SimplifiedTypeGen PtrSimplifiedType, NeverSimplifiedType, TupleSimplifiedType(usize), + /// A trait object, all of whose components are markers + /// (e.g., `dyn Send + Sync`). + MarkerTraitObjectSimplifiedType, TraitSimplifiedType(D), ClosureSimplifiedType(D), GeneratorSimplifiedType(D), @@ -78,7 +81,12 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, ty::Array(..) | ty::Slice(_) => Some(ArraySimplifiedType), ty::RawPtr(_) => Some(PtrSimplifiedType), ty::Dynamic(ref trait_info, ..) => { - Some(TraitSimplifiedType(trait_info.principal().def_id())) + let principal_def_id = trait_info.principal().def_id(); + if tcx.trait_is_auto(principal_def_id) { + Some(MarkerTraitObjectSimplifiedType) + } else { + Some(TraitSimplifiedType(principal_def_id)) + } } ty::Ref(_, ty, _) => { // since we introduce auto-refs during method lookup, we @@ -110,7 +118,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, // anything. when lazy normalization happens, this // will change. It would still be nice to have a way // to deal with known-not-to-unify-with-anything - // projections (e.g. the likes of <__S as Encoder>::Error). + // projections (e.g., the likes of <__S as Encoder>::Error). Some(ParameterSimplifiedType) } else { None @@ -144,6 +152,7 @@ impl SimplifiedTypeGen { NeverSimplifiedType => NeverSimplifiedType, TupleSimplifiedType(n) => TupleSimplifiedType(n), TraitSimplifiedType(d) => TraitSimplifiedType(map(d)), + MarkerTraitObjectSimplifiedType => MarkerTraitObjectSimplifiedType, ClosureSimplifiedType(d) => ClosureSimplifiedType(map(d)), GeneratorSimplifiedType(d) => GeneratorSimplifiedType(map(d)), GeneratorWitnessSimplifiedType(n) => GeneratorWitnessSimplifiedType(n), @@ -170,7 +179,8 @@ impl<'a, 'gcx, D> HashStable> for SimplifiedTypeGen ArraySimplifiedType | PtrSimplifiedType | NeverSimplifiedType | - ParameterSimplifiedType => { + ParameterSimplifiedType | + MarkerTraitObjectSimplifiedType => { // nothing to do } IntSimplifiedType(t) => t.hash_stable(hcx, hasher), diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 20f64597b78..a40e1df14f8 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -887,7 +887,7 @@ struct LateBoundRegionsCollector { /// If true, we only want regions that are known to be /// "constrained" when you equate this type with another type. In - /// particular, if you have e.g. `&'a u32` and `&'b u32`, equating + /// particular, if you have e.g., `&'a u32` and `&'b u32`, equating /// them constraints `'a == 'b`. But if you have `<&'a u32 as /// Trait>::Foo` and `<&'b u32 as Trait>::Foo`, normalizing those /// types may mean that `'a` and `'b` don't appear in the results, diff --git a/src/librustc/ty/inhabitedness/def_id_forest.rs b/src/librustc/ty/inhabitedness/def_id_forest.rs index 7bc77e1b1a1..af2185205a3 100644 --- a/src/librustc/ty/inhabitedness/def_id_forest.rs +++ b/src/librustc/ty/inhabitedness/def_id_forest.rs @@ -43,7 +43,7 @@ impl<'a, 'gcx, 'tcx> DefIdForest { /// crate. #[inline] pub fn full(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest { - let crate_id = tcx.hir.local_def_id(CRATE_NODE_ID); + let crate_id = tcx.hir().local_def_id(CRATE_NODE_ID); DefIdForest::from_id(crate_id) } @@ -74,10 +74,21 @@ impl<'a, 'gcx, 'tcx> DefIdForest { iter: I) -> DefIdForest where I: IntoIterator { - let mut ret = DefIdForest::full(tcx); + let mut iter = iter.into_iter(); + let mut ret = if let Some(first) = iter.next() { + first + } else { + return DefIdForest::full(tcx); + }; + let mut next_ret = SmallVec::new(); let mut old_ret: SmallVec<[DefId; 1]> = SmallVec::new(); for next_forest in iter { + // No need to continue if the intersection is already empty. + if ret.is_empty() { + break; + } + for id in ret.root_ids.drain() { if next_forest.contains(tcx, id) { next_ret.push(id); diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs index 721d5e14ccc..c64811e32f4 100644 --- a/src/librustc/ty/inhabitedness/mod.rs +++ b/src/librustc/ty/inhabitedness/mod.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use util::nodemap::{FxHashMap, FxHashSet}; use ty::context::TyCtxt; use ty::{AdtDef, VariantDef, FieldDef, Ty, TyS}; use ty::{DefId, Substs}; @@ -113,7 +112,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } fn ty_inhabitedness_forest(self, ty: Ty<'tcx>) -> DefIdForest { - ty.uninhabited_from(&mut FxHashMap::default(), self) + ty.uninhabited_from(self) } pub fn is_enum_variant_uninhabited_from(self, @@ -140,7 +139,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let adt_kind = self.adt_def(adt_def_id).adt_kind(); // Compute inhabitedness forest: - variant.uninhabited_from(&mut FxHashMap::default(), self, substs, adt_kind) + variant.uninhabited_from(self, substs, adt_kind) } } @@ -148,12 +147,11 @@ impl<'a, 'gcx, 'tcx> AdtDef { /// Calculate the forest of DefIds from which this adt is visibly uninhabited. fn uninhabited_from( &self, - visited: &mut FxHashMap>>, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &'tcx Substs<'tcx>) -> DefIdForest { DefIdForest::intersection(tcx, self.variants.iter().map(|v| { - v.uninhabited_from(visited, tcx, substs, self.adt_kind()) + v.uninhabited_from(tcx, substs, self.adt_kind()) })) } } @@ -162,7 +160,6 @@ impl<'a, 'gcx, 'tcx> VariantDef { /// Calculate the forest of DefIds from which this variant is visibly uninhabited. fn uninhabited_from( &self, - visited: &mut FxHashMap>>, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &'tcx Substs<'tcx>, adt_kind: AdtKind) -> DefIdForest @@ -175,7 +172,7 @@ impl<'a, 'gcx, 'tcx> VariantDef { AdtKind::Struct => false, }; DefIdForest::union(tcx, self.fields.iter().map(|f| { - f.uninhabited_from(visited, tcx, substs, is_enum) + f.uninhabited_from(tcx, substs, is_enum) })) } } @@ -184,13 +181,12 @@ impl<'a, 'gcx, 'tcx> FieldDef { /// Calculate the forest of DefIds from which this field is visibly uninhabited. fn uninhabited_from( &self, - visited: &mut FxHashMap>>, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &'tcx Substs<'tcx>, is_enum: bool, ) -> DefIdForest { - let mut data_uninhabitedness = move || { - self.ty(tcx, substs).uninhabited_from(visited, tcx) + let data_uninhabitedness = move || { + self.ty(tcx, substs).uninhabited_from(tcx) }; // FIXME(canndrew): Currently enum fields are (incorrectly) stored with // Visibility::Invisible so we need to override self.vis if we're @@ -213,46 +209,16 @@ impl<'a, 'gcx, 'tcx> FieldDef { impl<'a, 'gcx, 'tcx> TyS<'tcx> { /// Calculate the forest of DefIds from which this type is visibly uninhabited. - fn uninhabited_from( - &self, - visited: &mut FxHashMap>>, - tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest + fn uninhabited_from(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest { match self.sty { - Adt(def, substs) => { - { - let substs_set = visited.entry(def.did).or_default(); - if !substs_set.insert(substs) { - // We are already calculating the inhabitedness of this type. - // The type must contain a reference to itself. Break the - // infinite loop. - return DefIdForest::empty(); - } - if substs_set.len() >= tcx.sess.recursion_limit.get() / 4 { - // We have gone very deep, reinstantiating this ADT inside - // itself with different type arguments. We are probably - // hitting an infinite loop. For example, it's possible to write: - // a type Foo - // which contains a Foo<(T, T)> - // which contains a Foo<((T, T), (T, T))> - // which contains a Foo<(((T, T), (T, T)), ((T, T), (T, T)))> - // etc. - let error = format!("reached recursion limit while checking \ - inhabitedness of `{}`", self); - tcx.sess.fatal(&error); - } - } - let ret = def.uninhabited_from(visited, tcx, substs); - let substs_set = visited.get_mut(&def.did).unwrap(); - substs_set.remove(substs); - ret - } + Adt(def, substs) => def.uninhabited_from(tcx, substs), Never => DefIdForest::full(tcx), Tuple(ref tys) => { DefIdForest::union(tcx, tys.iter().map(|ty| { - ty.uninhabited_from(visited, tcx) + ty.uninhabited_from(tcx) })) } @@ -260,7 +226,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { match len.assert_usize(tcx) { // If the array is definitely non-empty, it's uninhabited if // the type of its elements is uninhabited. - Some(n) if n != 0 => ty.uninhabited_from(visited, tcx), + Some(n) if n != 0 => ty.uninhabited_from(tcx), _ => DefIdForest::empty() } } diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 411a6e7e623..a24920da158 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -347,9 +347,10 @@ fn resolve_associated_item<'a, 'tcx>( ) -> Option> { let def_id = trait_item.def_id; debug!("resolve_associated_item(trait_item={:?}, \ + param_env={:?}, \ trait_id={:?}, \ rcvr_substs={:?})", - def_id, trait_id, rcvr_substs); + def_id, param_env, trait_id, rcvr_substs); let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs); let vtbl = tcx.codegen_fulfill_obligation((param_env, ty::Binder::bind(trait_ref))); @@ -359,7 +360,7 @@ fn resolve_associated_item<'a, 'tcx>( match vtbl { traits::VtableImpl(impl_data) => { let (def_id, substs) = traits::find_associated_item( - tcx, trait_item, rcvr_substs, &impl_data); + tcx, param_env, trait_item, rcvr_substs, &impl_data); let substs = tcx.erase_regions(&substs); Some(ty::Instance::new(def_id, substs)) } diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 350e55288ea..a39eb004fd7 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -83,7 +83,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Returns a string identifying this local node-id. pub fn node_path_str(self, id: ast::NodeId) -> String { - self.item_path_str(self.hir.local_def_id(id)) + self.item_path_str(self.hir().local_def_id(id)) } /// Returns a string identifying this def-id. This string is @@ -317,7 +317,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // Unclear if there is any value in distinguishing these. // Probably eventually (and maybe we would even want - // finer-grained distinctions, e.g. between enum/struct). + // finer-grained distinctions, e.g., between enum/struct). data @ DefPathData::Misc | data @ DefPathData::TypeNs(..) | data @ DefPathData::Trait(..) | @@ -464,8 +464,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // only occur very early in the compiler pipeline. let parent_def_id = self.parent_def_id(impl_def_id).unwrap(); self.push_item_path(buffer, parent_def_id, pushed_prelude_crate); - let node_id = self.hir.as_local_node_id(impl_def_id).unwrap(); - let item = self.hir.expect_item(node_id); + let node_id = self.hir().as_local_node_id(impl_def_id).unwrap(); + let item = self.hir().expect_item(node_id); let span_str = self.sess.source_map().span_to_string(item.span); buffer.push(&format!("", span_str)); } diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 5406495226d..f4506c8e819 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -191,7 +191,14 @@ fn layout_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty::tls::enter_context(&icx, |_| { let cx = LayoutCx { tcx, param_env }; - cx.layout_raw_uncached(ty) + let layout = cx.layout_raw_uncached(ty); + // Type-level uninhabitedness should always imply ABI uninhabitedness. + if let Ok(layout) = layout { + if ty.conservative_is_privately_uninhabited(tcx) { + assert!(layout.abi.is_uninhabited()); + } + } + layout }) }) } @@ -205,12 +212,11 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { pub struct LayoutCx<'tcx, C> { pub tcx: C, - pub param_env: ty::ParamEnv<'tcx> + pub param_env: ty::ParamEnv<'tcx>, } impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { - fn layout_raw_uncached(&self, ty: Ty<'tcx>) - -> Result<&'tcx LayoutDetails, LayoutError<'tcx>> { + fn layout_raw_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx LayoutDetails, LayoutError<'tcx>> { let tcx = self.tcx; let param_env = self.param_env; let dl = self.data_layout(); @@ -248,7 +254,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { AlwaysSized, /// A univariant, the last field of which may be coerced to unsized. MaybeUnsized, - /// A univariant, but with a prefix of an arbitrary size & alignment (e.g. enum tag). + /// A univariant, but with a prefix of an arbitrary size & alignment (e.g., enum tag). Prefixed(Size, Align), } @@ -551,13 +557,19 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { let size = element.size.checked_mul(count, dl) .ok_or(LayoutError::SizeOverflow(ty))?; + let abi = if count != 0 && ty.conservative_is_privately_uninhabited(tcx) { + Abi::Uninhabited + } else { + Abi::Aggregate { sized: true } + }; + tcx.intern_layout(LayoutDetails { variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldPlacement::Array { stride: element.size, count }, - abi: Abi::Aggregate { sized: true }, + abi, align: element.align, size }) @@ -748,7 +760,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { // A variant is absent if it's uninhabited and only has ZST fields. // Present uninhabited variants only require space for their fields, - // but *not* an encoding of the discriminant (e.g. a tag value). + // but *not* an encoding of the discriminant (e.g., a tag value). // See issue #49298 for more details on the need to leave space // for non-ZST uninhabited data (mostly partial initialization). let absent = |fields: &[TyLayout<'_>]| { @@ -1252,7 +1264,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { }).collect(); session::VariantInfo { - name: n.map(|n|n.to_string()), + name: n.map(|n| n.to_string()), kind: if layout.is_unsized() { session::SizeKind::Min } else { @@ -1311,7 +1323,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { } } -/// Type size "skeleton", i.e. the only information determining a type's size. +/// Type size "skeleton", i.e., the only information determining a type's size. /// While this is conservative, (aside from constant sizes, only pointers, /// newtypes thereof and null pointer optimized enums are allowed), it is /// enough to statically check common use cases of transmute. @@ -1522,7 +1534,7 @@ impl<'a, 'tcx> LayoutOf for LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { details }; - // NB: This recording is normally disabled; when enabled, it + // N.B., this recording is normally disabled; when enabled, it // can however trigger recursive invocations of `layout_of`. // Therefore, we execute it *after* the main query has // completed, to avoid problems around recursive structures @@ -1549,7 +1561,7 @@ impl<'a, 'tcx> LayoutOf for LayoutCx<'tcx, ty::query::TyCtxtAt<'a, 'tcx, 'tcx>> details }; - // NB: This recording is normally disabled; when enabled, it + // N.B., this recording is normally disabled; when enabled, it // can however trigger recursive invocations of `layout_of`. // Therefore, we execute it *after* the main query has // completed, to avoid problems around recursive structures @@ -1660,7 +1672,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> assert!(i < this.fields.count()); // Reuse the fat *T type as its own thin pointer data field. - // This provides information about e.g. DST struct pointees + // This provides information about e.g., DST struct pointees // (which may have no non-DST form), and will work as long // as the `Abi` or `FieldPlacement` is checked by users. if i == 0 { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 4633ab11663..e1bf43c3782 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -82,7 +82,7 @@ pub use self::binding::BindingMode; pub use self::binding::BindingMode::*; pub use self::context::{TyCtxt, FreeRegionInfo, GlobalArenas, AllArenas, tls, keep_local}; -pub use self::context::{Lift, TypeckTables}; +pub use self::context::{Lift, TypeckTables, CtxtInterners}; pub use self::instance::{Instance, InstanceDef}; @@ -125,7 +125,7 @@ mod sty; /// The complete set of all analyses described in this module. This is /// produced by the driver and fed to codegen and later passes. /// -/// NB: These contents are being migrated into queries using the +/// N.B., these contents are being migrated into queries using the /// *on-demand* infrastructure. #[derive(Clone)] pub struct CrateAnalysis { @@ -289,7 +289,7 @@ impl Visibility { def => Visibility::Restricted(def.def_id()), }, hir::VisibilityKind::Inherited => { - Visibility::Restricted(tcx.hir.get_module_parent(id)) + Visibility::Restricted(tcx.hir().get_module_parent(id)) } } } @@ -505,15 +505,15 @@ pub struct TyS<'tcx> { /// by some sub-binder. /// /// So, for a type without any late-bound things, like `u32`, this - /// will be INNERMOST, because that is the innermost binder that + /// will be *innermost*, because that is the innermost binder that /// captures nothing. But for a type `&'D u32`, where `'D` is a - /// late-bound region with debruijn index D, this would be D+1 -- - /// the binder itself does not capture D, but D is captured by an - /// inner binder. + /// late-bound region with debruijn index `D`, this would be `D + 1` + /// -- the binder itself does not capture `D`, but `D` is captured + /// by an inner binder. /// - /// We call this concept an "exclusive" binder D (because all + /// We call this concept an "exclusive" binder `D` because all /// debruijn indices within the type are contained within `0..D` - /// (exclusive)). + /// (exclusive). outer_exclusive_binder: ty::DebruijnIndex, } @@ -900,10 +900,10 @@ pub struct GenericParamCount { } /// Information about the formal type/lifetime parameters associated -/// with an item or method. Analogous to hir::Generics. +/// with an item or method. Analogous to `hir::Generics`. /// -/// The ordering of parameters is the same as in Subst (excluding child generics): -/// Self (optionally), Lifetime params..., Type params... +/// The ordering of parameters is the same as in `Subst` (excluding child generics): +/// `Self` (optionally), `Lifetime` params..., `Type` params... #[derive(Clone, Debug, RustcEncodable, RustcDecodable)] pub struct Generics { pub parent: Option, @@ -1681,7 +1681,7 @@ impl<'tcx> ParamEnv<'tcx> { /// pair it with the empty environment. This improves caching and is generally /// invisible. /// - /// NB: We preserve the environment when type-checking because it + /// N.B., we preserve the environment when type-checking because it /// is possible for the user to have wacky where-clauses like /// `where Box: Copy`, which are clearly never /// satisfiable. We generally want to behave as if they were true, @@ -1754,17 +1754,19 @@ bitflags! { pub struct AdtFlags: u32 { const NO_ADT_FLAGS = 0; const IS_ENUM = 1 << 0; - const IS_PHANTOM_DATA = 1 << 1; - const IS_FUNDAMENTAL = 1 << 2; - const IS_UNION = 1 << 3; - const IS_BOX = 1 << 4; + const IS_UNION = 1 << 1; + const IS_STRUCT = 1 << 2; + const HAS_CTOR = 1 << 3; + const IS_PHANTOM_DATA = 1 << 4; + const IS_FUNDAMENTAL = 1 << 5; + const IS_BOX = 1 << 6; /// Indicates whether the type is an `Arc`. - const IS_ARC = 1 << 5; + const IS_ARC = 1 << 7; /// Indicates whether the type is an `Rc`. - const IS_RC = 1 << 6; + const IS_RC = 1 << 8; /// Indicates whether the variant list of this ADT is `#[non_exhaustive]`. /// (i.e., this flag is never set unless this ADT is an enum). - const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 7; + const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 9; } } @@ -1778,8 +1780,8 @@ bitflags! { #[derive(Debug)] pub struct VariantDef { - /// The variant's DefId. If this is a tuple-like struct, - /// this is the DefId of the struct's ctor. + /// The variant's `DefId`. If this is a tuple-like struct, + /// this is the `DefId` of the struct's ctor. pub did: DefId, pub name: Name, // struct's name if this is a struct pub discr: VariantDiscr, @@ -1798,7 +1800,7 @@ impl<'a, 'gcx, 'tcx> VariantDef { /// /// Note that we *could* use the constructor DefId, because the constructor attributes /// redirect to the base attributes, but compiling a small crate requires - /// loading the AdtDefs for all the structs in the universe (e.g. coherence for any + /// loading the AdtDefs for all the structs in the universe (e.g., coherence for any /// built-in trait), and we do not want to load attributes twice. /// /// If someone speeds up attribute loading to not be a performance concern, they can @@ -1847,7 +1849,7 @@ impl_stable_hash_for!(struct VariantDef { #[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)] pub enum VariantDiscr { - /// Explicit value for this variant, i.e. `X = 123`. + /// Explicit value for this variant, i.e., `X = 123`. /// The `DefId` corresponds to the embedded constant. Explicit(DefId), @@ -1865,9 +1867,9 @@ pub struct FieldDef { pub vis: Visibility, } -/// The definition of an abstract data type - a struct or enum. +/// The definition of an abstract data type -- a struct or enum. /// -/// These are all interned (by intern_adt_def) into the adt_defs +/// These are all interned (by `intern_adt_def`) into the `adt_defs` /// table. pub struct AdtDef { pub did: DefId, @@ -2059,9 +2061,10 @@ impl ReprOptions { } /// Returns `true` if this `#[repr()]` should inhibit struct field reordering - /// optimizations, such as with repr(C) or repr(packed(1)). + /// optimizations, such as with repr(C), repr(packed(1)), or repr(). pub fn inhibit_struct_field_reordering_opt(&self) -> bool { - !(self.flags & ReprFlags::IS_UNOPTIMISABLE).is_empty() || (self.pack == 1) + self.flags.intersects(ReprFlags::IS_UNOPTIMISABLE) || self.pack == 1 || + self.int.is_some() } /// Returns true if this `#[repr()]` should inhibit union abi optimisations @@ -2079,31 +2082,43 @@ impl<'a, 'gcx, 'tcx> AdtDef { repr: ReprOptions) -> Self { debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr); let mut flags = AdtFlags::NO_ADT_FLAGS; - let attrs = tcx.get_attrs(did); - if attr::contains_name(&attrs, "fundamental") { - flags = flags | AdtFlags::IS_FUNDAMENTAL; - } - if Some(did) == tcx.lang_items().phantom_data() { - flags = flags | AdtFlags::IS_PHANTOM_DATA; - } - if Some(did) == tcx.lang_items().owned_box() { - flags = flags | AdtFlags::IS_BOX; - } - if Some(did) == tcx.lang_items().arc() { - flags = flags | AdtFlags::IS_ARC; - } - if Some(did) == tcx.lang_items().rc() { - flags = flags | AdtFlags::IS_RC; - } + if kind == AdtKind::Enum && tcx.has_attr(did, "non_exhaustive") { debug!("found non-exhaustive variant list for {:?}", did); flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE; } - match kind { - AdtKind::Enum => flags = flags | AdtFlags::IS_ENUM, - AdtKind::Union => flags = flags | AdtFlags::IS_UNION, - AdtKind::Struct => {} + flags |= match kind { + AdtKind::Enum => AdtFlags::IS_ENUM, + AdtKind::Union => AdtFlags::IS_UNION, + AdtKind::Struct => AdtFlags::IS_STRUCT, + }; + + if let AdtKind::Struct = kind { + let variant_def = &variants[VariantIdx::new(0)]; + let def_key = tcx.def_key(variant_def.did); + match def_key.disambiguated_data.data { + DefPathData::StructCtor => flags |= AdtFlags::HAS_CTOR, + _ => (), + } } + + let attrs = tcx.get_attrs(did); + if attr::contains_name(&attrs, "fundamental") { + flags |= AdtFlags::IS_FUNDAMENTAL; + } + if Some(did) == tcx.lang_items().phantom_data() { + flags |= AdtFlags::IS_PHANTOM_DATA; + } + if Some(did) == tcx.lang_items().owned_box() { + flags |= AdtFlags::IS_BOX; + } + if Some(did) == tcx.lang_items().arc() { + flags |= AdtFlags::IS_ARC; + } + if Some(did) == tcx.lang_items().rc() { + flags |= AdtFlags::IS_RC; + } + AdtDef { did, variants, @@ -2114,25 +2129,25 @@ impl<'a, 'gcx, 'tcx> AdtDef { #[inline] pub fn is_struct(&self) -> bool { - !self.is_union() && !self.is_enum() + self.flags.contains(AdtFlags::IS_STRUCT) } #[inline] pub fn is_union(&self) -> bool { - self.flags.intersects(AdtFlags::IS_UNION) + self.flags.contains(AdtFlags::IS_UNION) } #[inline] pub fn is_enum(&self) -> bool { - self.flags.intersects(AdtFlags::IS_ENUM) + self.flags.contains(AdtFlags::IS_ENUM) } #[inline] pub fn is_variant_list_non_exhaustive(&self) -> bool { - self.flags.intersects(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE) + self.flags.contains(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE) } - /// Returns the kind of the ADT - Struct or Enum. + /// Returns the kind of the ADT. #[inline] pub fn adt_kind(&self) -> AdtKind { if self.is_enum() { @@ -2161,33 +2176,39 @@ impl<'a, 'gcx, 'tcx> AdtDef { } } - /// Returns whether this type is #[fundamental] for the purposes + /// If this function returns `true`, it implies that `is_struct` must return `true`. + #[inline] + pub fn has_ctor(&self) -> bool { + self.flags.contains(AdtFlags::HAS_CTOR) + } + + /// Returns whether this type is `#[fundamental]` for the purposes /// of coherence checking. #[inline] pub fn is_fundamental(&self) -> bool { - self.flags.intersects(AdtFlags::IS_FUNDAMENTAL) + self.flags.contains(AdtFlags::IS_FUNDAMENTAL) } /// Returns `true` if this is PhantomData. #[inline] pub fn is_phantom_data(&self) -> bool { - self.flags.intersects(AdtFlags::IS_PHANTOM_DATA) + self.flags.contains(AdtFlags::IS_PHANTOM_DATA) } /// Returns `true` if this is `Arc`. pub fn is_arc(&self) -> bool { - self.flags.intersects(AdtFlags::IS_ARC) + self.flags.contains(AdtFlags::IS_ARC) } /// Returns `true` if this is `Rc`. pub fn is_rc(&self) -> bool { - self.flags.intersects(AdtFlags::IS_RC) + self.flags.contains(AdtFlags::IS_RC) } /// Returns `true` if this is Box. #[inline] pub fn is_box(&self) -> bool { - self.flags.intersects(AdtFlags::IS_BOX) + self.flags.contains(AdtFlags::IS_BOX) } /// Returns whether this type has a destructor. @@ -2367,7 +2388,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { /// Self would prevent its containing ADT from being Sized. /// /// Due to normalization being eager, this applies even if - /// the associated type is behind a pointer, e.g. issue #31299. + /// the associated type is behind a pointer, e.g., issue #31299. pub fn sized_constraint(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &'tcx [Ty<'tcx>] { match tcx.try_adt_sized_constraint(DUMMY_SP, self.did) { Ok(tys) => tys, @@ -2619,29 +2640,29 @@ impl<'gcx> ::std::ops::Deref for Attributes<'gcx> { impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn body_tables(self, body: hir::BodyId) -> &'gcx TypeckTables<'gcx> { - self.typeck_tables_of(self.hir.body_owner_def_id(body)) + self.typeck_tables_of(self.hir().body_owner_def_id(body)) } /// Returns an iterator of the def-ids for all body-owners in this /// crate. If you would prefer to iterate over the bodies - /// themselves, you can do `self.hir.krate().body_ids.iter()`. + /// themselves, you can do `self.hir().krate().body_ids.iter()`. pub fn body_owners( self, ) -> impl Iterator + Captures<'tcx> + Captures<'gcx> + 'a { - self.hir.krate() - .body_ids - .iter() - .map(move |&body_id| self.hir.body_owner_def_id(body_id)) + self.hir().krate() + .body_ids + .iter() + .map(move |&body_id| self.hir().body_owner_def_id(body_id)) } pub fn par_body_owners(self, f: F) { - par_iter(&self.hir.krate().body_ids).for_each(|&body_id| { - f(self.hir.body_owner_def_id(body_id)) + par_iter(&self.hir().krate().body_ids).for_each(|&body_id| { + f(self.hir().body_owner_def_id(body_id)) }); } pub fn expr_span(self, id: NodeId) -> Span { - match self.hir.find(id) { + match self.hir().find(id) { Some(Node::Expr(e)) => { e.span } @@ -2667,8 +2688,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn opt_associated_item(self, def_id: DefId) -> Option { - let is_associated_item = if let Some(node_id) = self.hir.as_local_node_id(def_id) { - match self.hir.get(node_id) { + let is_associated_item = if let Some(node_id) = self.hir().as_local_node_id(def_id) { + match self.hir().get(node_id) { Node::TraitItem(_) | Node::ImplItem(_) => true, _ => false, } @@ -2691,7 +2712,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { parent_vis: &hir::Visibility, trait_item_ref: &hir::TraitItemRef) -> AssociatedItem { - let def_id = self.hir.local_def_id(trait_item_ref.id.node_id); + let def_id = self.hir().local_def_id(trait_item_ref.id.node_id); let (kind, has_self) = match trait_item_ref.kind { hir::AssociatedItemKind::Const => (ty::AssociatedKind::Const, false), hir::AssociatedItemKind::Method { has_self } => { @@ -2717,7 +2738,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { parent_def_id: DefId, impl_item_ref: &hir::ImplItemRef) -> AssociatedItem { - let def_id = self.hir.local_def_id(impl_item_ref.id.node_id); + let def_id = self.hir().local_def_id(impl_item_ref.id.node_id); let (kind, has_self) = match impl_item_ref.kind { hir::AssociatedItemKind::Const => (ty::AssociatedKind::Const, false), hir::AssociatedItemKind::Method { has_self } => { @@ -2740,7 +2761,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn field_index(self, node_id: NodeId, tables: &TypeckTables<'_>) -> usize { - let hir_id = self.hir.node_to_hir_id(node_id); + let hir_id = self.hir().node_to_hir_id(node_id); tables.field_indices().get(hir_id).cloned().expect("no index for a field") } @@ -2878,8 +2899,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Get the attributes of a definition. pub fn get_attrs(self, did: DefId) -> Attributes<'gcx> { - if let Some(id) = self.hir.as_local_node_id(did) { - Attributes::Borrowed(self.hir.attrs(id)) + if let Some(id) = self.hir().as_local_node_id(did) { + Attributes::Borrowed(self.hir().attrs(id)) } else { Attributes::Owned(self.item_attrs(did)) } @@ -2930,8 +2951,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// with the name of the crate containing the impl. pub fn span_of_impl(self, impl_did: DefId) -> Result { if impl_did.is_local() { - let node_id = self.hir.as_local_node_id(impl_did).unwrap(); - Ok(self.hir.span(node_id)) + let node_id = self.hir().as_local_node_id(impl_did).unwrap(); + Ok(self.hir().span(node_id)) } else { Err(self.crate_name(impl_did.krate)) } @@ -2947,14 +2968,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn adjust_ident(self, mut ident: Ident, scope: DefId, block: NodeId) -> (Ident, DefId) { ident = ident.modern(); let target_expansion = match scope.krate { - LOCAL_CRATE => self.hir.definitions().expansion_that_defined(scope.index), + LOCAL_CRATE => self.hir().definitions().expansion_that_defined(scope.index), _ => Mark::root(), }; let scope = match ident.span.adjust(target_expansion) { Some(actual_expansion) => - self.hir.definitions().parent_module_of_macro_def(actual_expansion), + self.hir().definitions().parent_module_of_macro_def(actual_expansion), None if block == DUMMY_NODE_ID => DefId::local(CRATE_DEF_INDEX), // Dummy DefId - None => self.hir.get_module_parent(block), + None => self.hir().get_module_parent(block), }; (ident, scope) } @@ -2980,7 +3001,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn with_freevars(self, fid: NodeId, f: F) -> T where F: FnOnce(&[hir::Freevar]) -> T, { - let def_id = self.hir.local_def_id(fid); + let def_id = self.hir().local_def_id(fid); match self.freevars(def_id) { None => f(&[]), Some(d) => f(&d), @@ -2989,10 +3010,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } fn associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> AssociatedItem { - let id = tcx.hir.as_local_node_id(def_id).unwrap(); - let parent_id = tcx.hir.get_parent(id); - let parent_def_id = tcx.hir.local_def_id(parent_id); - let parent_item = tcx.hir.expect_item(parent_id); + let id = tcx.hir().as_local_node_id(def_id).unwrap(); + let parent_id = tcx.hir().get_parent(id); + let parent_def_id = tcx.hir().local_def_id(parent_id); + let parent_item = tcx.hir().expect_item(parent_id); match parent_item.node { hir::ItemKind::Impl(.., ref impl_item_refs) => { if let Some(impl_item_ref) = impl_item_refs.iter().find(|i| i.id.node_id == id) { @@ -3049,19 +3070,19 @@ fn adt_sized_constraint<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn associated_item_def_ids<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Lrc> { - let id = tcx.hir.as_local_node_id(def_id).unwrap(); - let item = tcx.hir.expect_item(id); + let id = tcx.hir().as_local_node_id(def_id).unwrap(); + let item = tcx.hir().expect_item(id); let vec: Vec<_> = match item.node { hir::ItemKind::Trait(.., ref trait_item_refs) => { trait_item_refs.iter() .map(|trait_item_ref| trait_item_ref.id) - .map(|id| tcx.hir.local_def_id(id.node_id)) + .map(|id| tcx.hir().local_def_id(id.node_id)) .collect() } hir::ItemKind::Impl(.., ref impl_item_refs) => { impl_item_refs.iter() .map(|impl_item_ref| impl_item_ref.id) - .map(|id| tcx.hir.local_def_id(id.node_id)) + .map(|id| tcx.hir().local_def_id(id.node_id)) .collect() } hir::ItemKind::TraitAlias(..) => vec![], @@ -3071,7 +3092,7 @@ fn associated_item_def_ids<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } fn def_span<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Span { - tcx.hir.span_if_local(def_id).unwrap() + tcx.hir().span_if_local(def_id).unwrap() } /// If the given def ID describes an item belonging to a trait, @@ -3089,8 +3110,8 @@ fn trait_of_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Option /// Yields the parent function's `DefId` if `def_id` is an `impl Trait` definition. pub fn is_impl_trait_defn(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Option { - if let Some(node_id) = tcx.hir.as_local_node_id(def_id) { - if let Node::Item(item) = tcx.hir.get(node_id) { + if let Some(node_id) = tcx.hir().as_local_node_id(def_id) { + if let Node::Item(item) = tcx.hir().get(node_id) { if let hir::ItemKind::Existential(ref exist_ty) = item.node { return exist_ty.impl_trait_fn; } @@ -3101,8 +3122,8 @@ pub fn is_impl_trait_defn(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Option, def_id: DefId) -> bool { - if let Some(node_id) = tcx.hir.as_local_node_id(def_id) { - if let Node::Item(item) = tcx.hir.get(node_id) { + if let Some(node_id) = tcx.hir().as_local_node_id(def_id) { + if let Node::Item(item) = tcx.hir().get(node_id) { if let hir::ItemKind::TraitAlias(..) = item.node { return true; } @@ -3140,8 +3161,8 @@ fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let unnormalized_env = ty::ParamEnv::new(tcx.intern_predicates(&predicates), traits::Reveal::UserFacing); - let body_id = tcx.hir.as_local_node_id(def_id).map_or(DUMMY_NODE_ID, |id| { - tcx.hir.maybe_body_owned_by(id).map_or(id, |body| body.node_id) + let body_id = tcx.hir().as_local_node_id(def_id).map_or(DUMMY_NODE_ID, |id| { + tcx.hir().maybe_body_owned_by(id).map_or(id, |body| body.node_id) }); let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id); traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause) @@ -3163,7 +3184,7 @@ fn crate_hash<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) -> Svh { assert_eq!(crate_num, LOCAL_CRATE); - tcx.hir.crate_hash + tcx.hir().crate_hash } fn instance_def_size_estimate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs index 5d12aaeed5f..b320c29dfad 100644 --- a/src/librustc/ty/query/config.rs +++ b/src/librustc/ty/query/config.rs @@ -227,9 +227,9 @@ impl<'tcx> QueryDescription<'tcx> for queries::erase_regions_ty<'tcx> { impl<'tcx> QueryDescription<'tcx> for queries::type_param_predicates<'tcx> { fn describe(tcx: TyCtxt<'_, '_, '_>, (_, def_id): (DefId, DefId)) -> Cow<'static, str> { - let id = tcx.hir.as_local_node_id(def_id).unwrap(); + let id = tcx.hir().as_local_node_id(def_id).unwrap(); format!("computing the bounds for type parameter `{}`", - tcx.hir.ty_param_name(id)).into() + tcx.hir().ty_param_name(id)).into() } } @@ -827,6 +827,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::substitute_normalize_and_test_pre } } +impl<'tcx> QueryDescription<'tcx> for queries::method_autoderef_steps<'tcx> { + fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTyGoal<'tcx>) -> Cow<'static, str> { + format!("computing autoderef types for `{:?}`", goal).into() + } +} + impl<'tcx> QueryDescription<'tcx> for queries::target_features_whitelist<'tcx> { fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { "looking up the whitelist of target features".into() diff --git a/src/librustc/ty/query/job.rs b/src/librustc/ty/query/job.rs index d588bc8c0cb..6e513d68f60 100644 --- a/src/librustc/ty/query/job.rs +++ b/src/librustc/ty/query/job.rs @@ -18,6 +18,11 @@ use syntax_pos::Span; use ty::tls; use ty::query::Query; use ty::query::plumbing::CycleError; +#[cfg(not(parallel_queries))] +use ty::query::{ + plumbing::TryGetJob, + config::QueryDescription, +}; use ty::context::TyCtxt; use errors::Diagnostic; use std::process; @@ -83,33 +88,44 @@ impl<'tcx> QueryJob<'tcx> { /// /// For single threaded rustc there's no concurrent jobs running, so if we are waiting for any /// query that means that there is a query cycle, thus this always running a cycle error. + #[cfg(not(parallel_queries))] + #[inline(never)] + #[cold] + pub(super) fn cycle_error<'lcx, 'a, D: QueryDescription<'tcx>>( + &self, + tcx: TyCtxt<'_, 'tcx, 'lcx>, + span: Span, + ) -> TryGetJob<'a, 'tcx, D> { + TryGetJob::JobCompleted(Err(Box::new(self.find_cycle_in_stack(tcx, span)))) + } + + /// Awaits for the query job to complete. + /// + /// For single threaded rustc there's no concurrent jobs running, so if we are waiting for any + /// query that means that there is a query cycle, thus this always running a cycle error. + #[cfg(parallel_queries)] pub(super) fn await<'lcx>( &self, tcx: TyCtxt<'_, 'tcx, 'lcx>, span: Span, - ) -> Result<(), CycleError<'tcx>> { - #[cfg(not(parallel_queries))] - { - self.find_cycle_in_stack(tcx, span) - } - - #[cfg(parallel_queries)] - { - tls::with_related_context(tcx, move |icx| { - let mut waiter = Lrc::new(QueryWaiter { - query: icx.query.clone(), - span, - cycle: Lock::new(None), - condvar: Condvar::new(), - }); - self.latch.await(&waiter); - - match Lrc::get_mut(&mut waiter).unwrap().cycle.get_mut().take() { - None => Ok(()), - Some(cycle) => Err(cycle) - } - }) - } + ) -> Result<(), Box>> { + tls::with_related_context(tcx, move |icx| { + let mut waiter = Lrc::new(QueryWaiter { + query: icx.query.clone(), + span, + cycle: Lock::new(None), + condvar: Condvar::new(), + }); + self.latch.await(&waiter); + // FIXME: Get rid of this lock. We have ownership of the QueryWaiter + // although another thread may still have a Lrc reference so we cannot + // use Lrc::get_mut + let mut cycle = waiter.cycle.lock(); + match cycle.take() { + None => Ok(()), + Some(cycle) => Err(Box::new(cycle)) + } + }) } #[cfg(not(parallel_queries))] @@ -117,7 +133,7 @@ impl<'tcx> QueryJob<'tcx> { &self, tcx: TyCtxt<'_, 'tcx, 'lcx>, span: Span, - ) -> Result<(), CycleError<'tcx>> { + ) -> CycleError<'tcx> { // Get the current executing query (waiter) and find the waitee amongst its parents let mut current_job = tls::with_related_context(tcx, |icx| icx.query.clone()); let mut cycle = Vec::new(); @@ -137,7 +153,7 @@ impl<'tcx> QueryJob<'tcx> { let usage = job.parent.as_ref().map(|parent| { (job.info.span, parent.info.query.clone()) }); - return Err(CycleError { usage, cycle }); + return CycleError { usage, cycle }; } current_job = job.parent.clone(); @@ -326,19 +342,17 @@ fn connected_to_root<'tcx>( query: Lrc>, visited: &mut FxHashSet<*const QueryJob<'tcx>> ) -> bool { - // This query is connected to the root (it has no query parent), return true - if query.parent.is_none() { - return true; - } - // We already visited this or we're deliberately ignoring it if visited.contains(&query.as_ptr()) { return false; } - visited.insert(query.as_ptr()); + // This query is connected to the root (it has no query parent), return true + if query.parent.is_none() { + return true; + } - let mut connected = false; + visited.insert(query.as_ptr()); visit_waiters(query, |_, successor| { if connected_to_root(successor, visited) { @@ -349,6 +363,28 @@ fn connected_to_root<'tcx>( }).is_some() } +// Deterministically pick an query from a list +#[cfg(parallel_queries)] +fn pick_query<'a, 'tcx, T, F: Fn(&T) -> (Span, Lrc>)>( + tcx: TyCtxt<'_, 'tcx, '_>, + queries: &'a [T], + f: F +) -> &'a T { + // Deterministically pick an entry point + // FIXME: Sort this instead + let mut hcx = tcx.create_stable_hashing_context(); + queries.iter().min_by_key(|v| { + let (span, query) = f(v); + let mut stable_hasher = StableHasher::::new(); + query.info.query.hash_stable(&mut hcx, &mut stable_hasher); + // Prefer entry points which have valid spans for nicer error messages + // We add an integer to the tuple ensuring that entry points + // with valid spans are picked first + let span_cmp = if span == DUMMY_SP { 1 } else { 0 }; + (span_cmp, stable_hasher.finish()) + }).unwrap() +} + /// Looks for query cycles starting from the last query in `jobs`. /// If a cycle is found, all queries in the cycle is removed from `jobs` and /// the function return true. @@ -388,41 +424,52 @@ fn remove_cycle<'tcx>( // Find the queries in the cycle which are // connected to queries outside the cycle - let entry_points = stack.iter().filter_map(|query| { - // Mark all the other queries in the cycle as already visited - let mut visited = FxHashSet::from_iter(stack.iter().filter_map(|q| { - if q.1.as_ptr() != query.1.as_ptr() { - Some(q.1.as_ptr()) - } else { - None - } - })); - - if connected_to_root(query.1.clone(), &mut visited) { - Some(query.1.clone()) + let entry_points: Vec<_> = stack.iter().filter_map(|(span, query)| { + if query.parent.is_none() { + // This query is connected to the root (it has no query parent) + Some((*span, query.clone(), None)) } else { - None + let mut waiters = Vec::new(); + // Find all the direct waiters who lead to the root + visit_waiters(query.clone(), |span, waiter| { + // Mark all the other queries in the cycle as already visited + let mut visited = FxHashSet::from_iter(stack.iter().map(|q| q.1.as_ptr())); + + if connected_to_root(waiter.clone(), &mut visited) { + waiters.push((span, waiter)); + } + + None + }); + if waiters.is_empty() { + None + } else { + // Deterministically pick one of the waiters to show to the user + let waiter = pick_query(tcx, &waiters, |s| s.clone()).clone(); + Some((*span, query.clone(), Some(waiter))) + } } - }); + }).collect(); + + let entry_points: Vec<(Span, Lrc>, Option<(Span, Lrc>)>)> + = entry_points; // Deterministically pick an entry point - // FIXME: Sort this instead - let mut hcx = tcx.create_stable_hashing_context(); - let entry_point = entry_points.min_by_key(|q| { - let mut stable_hasher = StableHasher::::new(); - q.info.query.hash_stable(&mut hcx, &mut stable_hasher); - stable_hasher.finish() - }).unwrap().as_ptr(); + let (_, entry_point, usage) = pick_query(tcx, &entry_points, |e| (e.0, e.1.clone())); // Shift the stack so that our entry point is first - let entry_point_pos = stack.iter().position(|(_, query)| query.as_ptr() == entry_point); + let entry_point_pos = stack.iter().position(|(_, query)| { + query.as_ptr() == entry_point.as_ptr() + }); if let Some(pos) = entry_point_pos { - stack.rotate_right(pos); + stack.rotate_left(pos); } + let usage = usage.as_ref().map(|(span, query)| (*span, query.info.query.clone())); + // Create the cycle error let mut error = CycleError { - usage: None, + usage, cycle: stack.iter().map(|&(s, ref q)| QueryInfo { span: s, query: q.info.query.clone(), diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 699c2d111c6..c9ffab21b78 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -40,6 +40,7 @@ use traits::query::{ CanonicalTypeOpSubtypeGoal, CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpNormalizeGoal, NoSolution, }; +use traits::query::method_autoderef::MethodAutoderefStepsResult; use traits::query::dropck_outlives::{DtorckConstraint, DropckOutlivesResult}; use traits::query::normalize::NormalizationResult; use traits::query::outlives_bounds::OutlivesBound; @@ -166,21 +167,21 @@ define_queries! { <'tcx> ) -> Result, NoSolution>, /// True if this is a const fn, use the `is_const_fn` to know whether your crate actually - /// sees it as const fn (e.g. the const-fn-ness might be unstable and you might not have + /// sees it as const fn (e.g., the const-fn-ness might be unstable and you might not have /// the feature gate active) /// - /// DO NOT CALL MANUALLY, it is only meant to cache the base data for the `is_const_fn` - /// function + /// **Do not call this function manually.** It is only meant to cache the base data for the + /// `is_const_fn` function. [] fn is_const_fn_raw: IsConstFn(DefId) -> bool, /// Returns true if calls to the function may be promoted /// - /// This is either because the function is e.g. a tuple-struct or tuple-variant constructor, - /// or because it has the `#[rustc_promotable]` attribute. The attribute should be removed - /// in the future in favour of some form of check which figures out whether the function - /// does not inspect the bits of any of its arguments (so is essentially just a constructor - /// function) + /// This is either because the function is e.g., a tuple-struct or tuple-variant + /// constructor, or because it has the `#[rustc_promotable]` attribute. The attribute should + /// be removed in the future in favour of some form of check which figures out whether the + /// function does not inspect the bits of any of its arguments (so is essentially just a + /// constructor function). [] fn is_promotable_const_fn: IsPromotableConstFn(DefId) -> bool, /// True if this is a foreign item (i.e., linked via `extern { ... }`). @@ -539,7 +540,7 @@ define_queries! { <'tcx> [] fn all_crate_nums: all_crate_nums_node(CrateNum) -> Lrc>, /// A vector of every trait accessible in the whole crate - /// (i.e. including those from subcrates). This is used only for + /// (i.e., including those from subcrates). This is used only for /// error reporting. [] fn all_traits: all_traits_node(CrateNum) -> Lrc>, }, @@ -668,6 +669,10 @@ define_queries! { <'tcx> [] fn substitute_normalize_and_test_predicates: substitute_normalize_and_test_predicates_node((DefId, &'tcx Substs<'tcx>)) -> bool, + + [] fn method_autoderef_steps: MethodAutoderefSteps( + CanonicalTyGoal<'tcx> + ) -> MethodAutoderefStepsResult<'tcx>, }, Other { @@ -705,21 +710,21 @@ impl<'a, 'tcx, 'lcx> TyCtxt<'a, 'tcx, 'lcx> { self, span: Span, key: DefId, - ) -> Result<&'tcx [Ty<'tcx>], DiagnosticBuilder<'a>> { + ) -> Result<&'tcx [Ty<'tcx>], Box>> { self.try_get_query::>(span, key) } pub fn try_needs_drop_raw( self, span: Span, key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, - ) -> Result> { + ) -> Result>> { self.try_get_query::>(span, key) } pub fn try_optimized_mir( self, span: Span, key: DefId, - ) -> Result<&'tcx mir::Mir<'tcx>, DiagnosticBuilder<'a>> { + ) -> Result<&'tcx mir::Mir<'tcx>, Box>> { self.try_get_query::>(span, key) } } diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index 7d3ae64f4fc..04c880826fe 100644 --- a/src/librustc/ty/query/on_disk_cache.rs +++ b/src/librustc/ty/query/on_disk_cache.rs @@ -725,7 +725,7 @@ impl<'a, 'tcx, 'x> SpecializedDecoder for CacheDecoder<'a, 'tcx, 'x> { #[inline] fn specialized_decode(&mut self) -> Result { let hir_id = hir::HirId::decode(self)?; - Ok(self.tcx().hir.hir_to_node_id(hir_id)) + Ok(self.tcx().hir().hir_to_node_id(hir_id)) } } @@ -926,7 +926,7 @@ impl<'enc, 'a, 'tcx, E> SpecializedEncoder for CacheEncoder<'enc, 'a local_id, } = *id; - let def_path_hash = self.tcx.hir.definitions().def_path_hash(owner); + let def_path_hash = self.tcx.hir().definitions().def_path_hash(owner); def_path_hash.encode(self)?; local_id.encode(self) @@ -968,7 +968,7 @@ impl<'enc, 'a, 'tcx, E> SpecializedEncoder for CacheEncoder<'enc, 'a, 't { #[inline] fn specialized_encode(&mut self, node_id: &NodeId) -> Result<(), Self::Error> { - let hir_id = self.tcx.hir.node_to_hir_id(*node_id); + let hir_id = self.tcx.hir().node_to_hir_id(*node_id); hir_id.encode(self) } } diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 5f33d466c4a..0359890dd93 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -136,11 +136,14 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { Entry::Vacant(entry) => { // No job entry for this query. Return a new one to be started later return tls::with_related_context(tcx, |icx| { + // Create the `parent` variable before `info`. This allows LLVM + // to elide the move of `info` + let parent = icx.query.clone(); let info = QueryInfo { span, query: Q::query(key.clone()), }; - let job = Lrc::new(QueryJob::new(info, icx.query.clone())); + let job = Lrc::new(QueryJob::new(info, parent)); let owner = JobOwner { cache, job: job.clone(), @@ -153,14 +156,25 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { }; mem::drop(lock); - if let Err(cycle) = job.await(tcx, span) { - return TryGetJob::JobCompleted(Err(cycle)); + // If we are single-threaded we know that we have cycle error, + // so we just turn the errror + #[cfg(not(parallel_queries))] + return job.cycle_error(tcx, span); + + // With parallel queries we might just have to wait on some other + // thread + #[cfg(parallel_queries)] + { + if let Err(cycle) = job.await(tcx, span) { + return TryGetJob::JobCompleted(Err(cycle)); + } } } } /// Completes the query by updating the query cache with the `result`, /// signals the waiter and forgets the JobOwner, so it won't poison the query + #[inline(always)] pub(super) fn complete(self, result: &Q::Value, dep_node_index: DepNodeIndex) { // We can move out of `self` here because we `mem::forget` it below let key = unsafe { ptr::read(&self.key) }; @@ -197,7 +211,7 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { let r = tls::with_related_context(tcx, move |current_icx| { // Update the ImplicitCtxt to point to our new query job let new_icx = tls::ImplicitCtxt { - tcx, + tcx: tcx.global_tcx(), query: Some(self.job.clone()), layout_depth: current_icx.layout_depth, task: current_icx.task, @@ -217,6 +231,8 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { } impl<'a, 'tcx, Q: QueryDescription<'tcx>> Drop for JobOwner<'a, 'tcx, Q> { + #[inline(never)] + #[cold] fn drop(&mut self) { // Poison the query so jobs waiting on it panic self.cache.borrow_mut().active.insert(self.key.clone(), QueryResult::Poisoned); @@ -241,12 +257,16 @@ pub(super) enum TryGetJob<'a, 'tcx: 'a, D: QueryDescription<'tcx> + 'a> { /// The query was already completed. /// Returns the result of the query and its dep node index /// if it succeeded or a cycle error if it failed - JobCompleted(Result<(D::Value, DepNodeIndex), CycleError<'tcx>>), + JobCompleted(Result<(D::Value, DepNodeIndex), Box>>), } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { - pub(super) fn report_cycle(self, CycleError { usage, cycle: stack }: CycleError<'gcx>) - -> DiagnosticBuilder<'a> + #[inline(never)] + #[cold] + pub(super) fn report_cycle( + self, + box CycleError { usage, cycle: stack }: Box> + ) -> Box> { assert!(!stack.is_empty()); @@ -280,7 +300,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { &format!("cycle used when {}", query.describe(self))); } - return err + return Box::new(err) }) } @@ -345,11 +365,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } + #[inline(never)] fn try_get_with>( self, span: Span, key: Q::Key) - -> Result> + -> Result>> { debug!("ty::queries::{}::try_get_with(key={:?}, span={:?})", Q::NAME, @@ -436,7 +457,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { job: JobOwner<'a, 'gcx, Q>, dep_node_index: DepNodeIndex, dep_node: &DepNode - ) -> Result> + ) -> Result>> { // Note this function can be called concurrently from the same query // We must ensure that this is handled correctly @@ -522,7 +543,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { key: Q::Key, job: JobOwner<'_, 'gcx, Q>, dep_node: DepNode) - -> Result<(Q::Value, DepNodeIndex), CycleError<'gcx>> { + -> Result<(Q::Value, DepNodeIndex), Box>> { // If the following assertion triggers, it can have two reasons: // 1. Something is wrong with DepNode creation, either here or // in DepGraph::try_mark_green() @@ -611,37 +632,55 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { key: Q::Key, span: Span, dep_node: DepNode - ) -> Result<(Q::Value, DepNodeIndex), CycleError<'gcx>> { + ) { + profq_msg!( + self, + ProfileQueriesMsg::QueryBegin(span.data(), profq_query_msg!(Q::NAME, self, key)) + ); + // We may be concurrently trying both execute and force a query // Ensure that only one of them runs the query let job = match JobOwner::try_get(self, span, &key) { TryGetJob::NotYetStarted(job) => job, - TryGetJob::JobCompleted(result) => return result, + TryGetJob::JobCompleted(_) => return, }; - self.force_query_with_job::(key, job, dep_node) + if let Err(e) = self.force_query_with_job::(key, job, dep_node) { + self.report_cycle(e).emit(); + } } pub(super) fn try_get_query>( self, span: Span, key: Q::Key, - ) -> Result> { + ) -> Result>> { match self.try_get_with::(span, key) { Ok(e) => Ok(e), Err(e) => Err(self.report_cycle(e)), } } + // FIXME: Try uninlining this + #[inline(always)] pub(super) fn get_query>( self, span: Span, key: Q::Key, ) -> Q::Value { - self.try_get_query::(span, key).unwrap_or_else(|mut e| { - e.emit(); - Q::handle_cycle_error(self) + self.try_get_with::(span, key).unwrap_or_else(|e| { + self.emit_error::(e) }) } + + #[inline(never)] + #[cold] + fn emit_error>( + self, + e: Box>, + ) -> Q::Value { + self.report_cycle(e).emit(); + Q::handle_cycle_error(self) + } } macro_rules! handle_cycle_error { @@ -806,15 +845,18 @@ macro_rules! define_queries_inner { } impl<$tcx> QueryAccessors<$tcx> for queries::$name<$tcx> { + #[inline(always)] fn query(key: Self::Key) -> Query<'tcx> { Query::$name(key) } + #[inline(always)] fn query_cache<'a>(tcx: TyCtxt<'a, $tcx, '_>) -> &'a Lock> { &tcx.queries.$name } #[allow(unused)] + #[inline(always)] fn to_dep_node(tcx: TyCtxt<'_, $tcx, '_>, key: &Self::Key) -> DepNode { use dep_graph::DepConstructor::*; @@ -861,6 +903,7 @@ macro_rules! define_queries_inner { impl<'a, 'gcx, 'tcx> Deref for TyCtxtAt<'a, 'gcx, 'tcx> { type Target = TyCtxt<'a, 'gcx, 'tcx>; + #[inline(always)] fn deref(&self) -> &Self::Target { &self.tcx } @@ -869,6 +912,7 @@ macro_rules! define_queries_inner { impl<'a, $tcx, 'lcx> TyCtxt<'a, $tcx, 'lcx> { /// Return a transparent wrapper for `TyCtxt` which uses /// `span` as the location of queries performed through it. + #[inline(always)] pub fn at(self, span: Span) -> TyCtxtAt<'a, $tcx, 'lcx> { TyCtxtAt { tcx: self, @@ -877,6 +921,7 @@ macro_rules! define_queries_inner { } $($(#[$attr])* + #[inline(always)] pub fn $name(self, key: $K) -> $V { self.at(DUMMY_SP).$name(key) })* @@ -884,6 +929,7 @@ macro_rules! define_queries_inner { impl<'a, $tcx, 'lcx> TyCtxtAt<'a, $tcx, 'lcx> { $($(#[$attr])* + #[inline(always)] pub fn $name(self, key: $K) -> $V { self.tcx.get_query::>(self.span, key) })* @@ -1023,20 +1069,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, macro_rules! force { ($query:ident, $key:expr) => { { - use $crate::util::common::{ProfileQueriesMsg, profq_msg}; - - profq_msg!(tcx, - ProfileQueriesMsg::QueryBegin( - DUMMY_SP.data(), - profq_query_msg!(::ty::query::queries::$query::NAME, tcx, $key), - ) - ); - - if let Err(e) = tcx.force_query::<::ty::query::queries::$query<'_>>( - $key, DUMMY_SP, *dep_node - ) { - tcx.report_cycle(e).emit(); - } + tcx.force_query::<::ty::query::queries::$query<'_>>($key, DUMMY_SP, *dep_node); } } }; @@ -1089,6 +1122,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::TypeOpNormalizePolyFnSig | DepKind::TypeOpNormalizeFnSig | DepKind::SubstituteNormalizeAndTestPredicates | + DepKind::MethodAutoderefSteps | DepKind::InstanceDefSizeEstimate | DepKind::ProgramClausesForEnv | diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 1b64a686794..88c3e5c8715 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -8,10 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Generalized type relating mechanism. A type relation R relates a -//! pair of values (A, B). A and B are usually types or regions but -//! can be other things. Examples of type relations are subtyping, -//! type equality, etc. +//! Generalized type relating mechanism. +//! +//! A type relation `R` relates a pair of values `(A, B)`. `A and B` are usually +//! types or regions but can be other things. Examples of type relations are +//! subtyping, type equality, etc. use hir::def_id::DefId; use mir::interpret::ConstValue; @@ -34,9 +35,20 @@ pub enum Cause { ExistentialRegionBound, // relating an existential region bound } +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum TraitObjectMode { + NoSquash, + /// A temporary mode to treat `Send + Sync = Sync + Send`, should be + /// used only in coherence. + SquashAutoTraitsIssue33140 +} + pub trait TypeRelation<'a, 'gcx: 'a+'tcx, 'tcx: 'a> : Sized { fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx>; + /// Return the trait object mode to be used. + fn trait_object_mode(&self) -> TraitObjectMode; + /// Returns a static string we can use for printouts. fn tag(&self) -> &'static str; @@ -595,14 +607,44 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List> { a: &Self, b: &Self) -> RelateResult<'tcx, Self> - where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a { + where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a { + use ty::ExistentialPredicate::*; - if a.len() != b.len() { + let tcx = relation.tcx(); + let (a_buf, b_buf); + let (a_norm, b_norm): (&[_], &[_]) = match relation.trait_object_mode() { + TraitObjectMode::NoSquash => { + (a, b) + } + TraitObjectMode::SquashAutoTraitsIssue33140 => { + // Treat auto-trait "principal" components as equal + // to the non-principal components, to make + // `dyn Send+Sync = dyn Sync+Send`. + let normalize = |d: &[ty::ExistentialPredicate<'tcx>]| { + let mut result: Vec<_> = d.iter().map(|pi| match pi { + Trait(ref a) if tcx.trait_is_auto(a.def_id) => { + AutoTrait(a.def_id) + }, + other => *other + }).collect(); + + result.sort_by(|a, b| a.stable_cmp(tcx, b)); + result.dedup(); + result + }; + + a_buf = normalize(a); + b_buf = normalize(b); + + (&a_buf, &b_buf) + } + }; + + if a_norm.len() != b_norm.len() { return Err(TypeError::ExistentialMismatch(expected_found(relation, a, b))); } - let tcx = relation.tcx(); - let v = a.iter().zip(b.iter()).map(|(ep_a, ep_b)| { + let v = a_norm.iter().zip(b_norm.iter()).map(|(ep_a, ep_b)| { use ty::ExistentialPredicate::*; match (*ep_a, *ep_b) { (Trait(ref a), Trait(ref b)) => Ok(Trait(relation.relate(a, b)?)), diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index d6aeb288b5c..1d28c4fa114 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -35,6 +35,7 @@ CloneTypeFoldableAndLiftImpls! { usize, ::ty::layout::VariantIdx, u64, + String, ::middle::region::Scope, ::syntax::ast::FloatTy, ::syntax::ast::NodeId, diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 1416cb17fea..2189267cb0b 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -8,8 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! This module contains TyKind and its major components +//! This module contains `TyKind` and its major components. +use hir; use hir::def_id::DefId; use infer::canonical::Canonical; use mir::interpret::ConstValue; @@ -30,9 +31,6 @@ use syntax::ast::{self, Ident}; use syntax::symbol::{keywords, InternedString}; use serialize; - -use hir; - use self::InferTy::*; use self::TyKind::*; @@ -91,7 +89,7 @@ impl BoundRegion { } } -/// N.B., If you change this, you'll probably want to change the corresponding +/// N.B., if you change this, you'll probably want to change the corresponding /// AST structure in `libsyntax/ast.rs` as well. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] pub enum TyKind<'tcx> { @@ -531,11 +529,11 @@ impl<'tcx> UpvarSubsts<'tcx> { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash, RustcEncodable, RustcDecodable)] pub enum ExistentialPredicate<'tcx> { - /// e.g. Iterator + /// e.g., Iterator Trait(ExistentialTraitRef<'tcx>), - /// e.g. Iterator::Item = T + /// e.g., Iterator::Item = T Projection(ExistentialProjection<'tcx>), - /// e.g. Send + /// e.g., Send AutoTrait(DefId), } @@ -784,7 +782,7 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> { /// Binder`). Note that when we instantiate, /// erase, or otherwise "discharge" these bound vars, we change the /// type from `Binder` to just `T` (see -/// e.g. `liberate_late_bound_regions`). +/// e.g., `liberate_late_bound_regions`). #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct Binder(T); @@ -1020,7 +1018,7 @@ impl<'a, 'gcx, 'tcx> ParamTy { } pub fn for_self() -> ParamTy { - ParamTy::new(0, keywords::SelfType.name().as_interned_str()) + ParamTy::new(0, keywords::SelfUpper.name().as_interned_str()) } pub fn for_def(def: &ty::GenericParamDef) -> ParamTy { @@ -1035,7 +1033,7 @@ impl<'a, 'gcx, 'tcx> ParamTy { // FIXME(#50125): Ignoring `Self` with `idx != 0` might lead to weird behavior elsewhere, // but this should only be possible when using `-Z continue-parse-after-error` like // `compile-fail/issue-36638.rs`. - self.name == keywords::SelfType.name().as_str() && self.idx == 0 + self.name == keywords::SelfUpper.name().as_str() && self.idx == 0 } } @@ -1099,12 +1097,12 @@ pub type Region<'tcx> = &'tcx RegionKind; /// with some concrete region before being used. There are 2 kind of /// bound regions: early-bound, which are bound in an item's Generics, /// and are substituted by a Substs, and late-bound, which are part of -/// higher-ranked types (e.g. `for<'a> fn(&'a ())`) and are substituted by +/// higher-ranked types (e.g., `for<'a> fn(&'a ())`) and are substituted by /// the likes of `liberate_late_bound_regions`. The distinction exists /// because higher-ranked lifetimes aren't supported in all places. See [1][2]. /// /// Unlike Param-s, bound regions are not supposed to exist "in the wild" -/// outside their binder, e.g. in types passed to type inference, and +/// outside their binder, e.g., in types passed to type inference, and /// should first be substituted (by placeholder regions, free regions, /// or region variables). /// @@ -1160,7 +1158,7 @@ pub enum RegionKind { ReFree(FreeRegion), /// A concrete region naming some statically determined scope - /// (e.g. an expression or sequence of statements) within the + /// (e.g., an expression or sequence of statements) within the /// current function. ReScope(region::Scope), @@ -1324,7 +1322,7 @@ impl<'a, 'tcx, 'gcx> PolyExistentialProjection<'tcx> { impl DebruijnIndex { /// Returns the resulting index when this value is moved into - /// `amount` number of new binders. So e.g. if you had + /// `amount` number of new binders. So e.g., if you had /// /// for<'a> fn(&'a x) /// @@ -1332,7 +1330,7 @@ impl DebruijnIndex { /// /// for<'a> fn(for<'b> fn(&'a x)) /// - /// you would need to shift the index for `'a` into 1 new binder. + /// you would need to shift the index for `'a` into a new binder. #[must_use] pub fn shifted_in(self, amount: u32) -> DebruijnIndex { DebruijnIndex::from_u32(self.as_u32() + amount) @@ -1545,6 +1543,51 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } + /// Checks whether a type is definitely uninhabited. This is + /// conservative: for some types that are uninhabited we return `false`, + /// but we only return `true` for types that are definitely uninhabited. + /// `ty.conservative_is_privately_uninhabited` implies that any value of type `ty` + /// will be `Abi::Uninhabited`. (Note that uninhabited types may have nonzero + /// size, to account for partial initialisation. See #49298 for details.) + pub fn conservative_is_privately_uninhabited(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool { + // FIXME(varkor): we can make this less conversative by substituting concrete + // type arguments. + match self.sty { + ty::Never => true, + ty::Adt(def, _) if def.is_union() => { + // For now, `union`s are never considered uninhabited. + false + } + ty::Adt(def, _) => { + // Any ADT is uninhabited if either: + // (a) It has no variants (i.e. an empty `enum`); + // (b) Each of its variants (a single one in the case of a `struct`) has at least + // one uninhabited field. + def.variants.iter().all(|var| { + var.fields.iter().any(|field| { + tcx.type_of(field.did).conservative_is_privately_uninhabited(tcx) + }) + }) + } + ty::Tuple(tys) => tys.iter().any(|ty| ty.conservative_is_privately_uninhabited(tcx)), + ty::Array(ty, len) => { + match len.assert_usize(tcx) { + // If the array is definitely non-empty, it's uninhabited if + // the type of its elements is uninhabited. + Some(n) if n != 0 => ty.conservative_is_privately_uninhabited(tcx), + _ => false + } + } + ty::Ref(..) => { + // References to uninitialised memory is valid for any type, including + // uninhabited types, in unsafe code, so we treat all references as + // inhabited. + false + } + _ => false, + } + } + pub fn is_primitive(&self) -> bool { match self.sty { Bool | Char | Int(_) | Uint(_) | Float(_) => true, @@ -1787,6 +1830,13 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } + pub fn is_pointer_sized(&self) -> bool { + match self.sty { + Int(ast::IntTy::Isize) | Uint(ast::UintTy::Usize) => true, + _ => false, + } + } + pub fn is_machine(&self) -> bool { match self.sty { Int(ast::IntTy::Isize) | Uint(ast::UintTy::Usize) => false, @@ -1802,10 +1852,10 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } - /// Returns the type and mutability of *ty. + /// Returns the type and mutability of `*ty`. /// /// The parameter `explicit` indicates if this is an *explicit* dereference. - /// Some types---notably unsafe ptrs---can only be dereferenced explicitly. + /// Some types -- notably unsafe ptrs -- can only be dereferenced explicitly. pub fn builtin_deref(&self, explicit: bool) -> Option> { match self.sty { Adt(def, _) if def.is_box() => { diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 34252039898..cda281e053a 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -316,10 +316,10 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { } /// Transform from substitutions for a child of `source_ancestor` - /// (e.g. a trait or impl) to substitutions for the same child + /// (e.g., a trait or impl) to substitutions for the same child /// in a different item, with `target_substs` as the base for /// the target impl/trait, with the source child-specific - /// parameters (e.g. method parameters) on top of that base. + /// parameters (e.g., method parameters) on top of that base. pub fn rebase_onto(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, source_ancestor: DefId, target_substs: &Substs<'tcx>) diff --git a/src/librustc/ty/trait_def.rs b/src/librustc/ty/trait_def.rs index af678c3e992..fadb1a1cf6e 100644 --- a/src/librustc/ty/trait_def.rs +++ b/src/librustc/ty/trait_def.rs @@ -189,8 +189,8 @@ pub(super) fn trait_impls_of_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } - for &node_id in tcx.hir.trait_impls(trait_id) { - add_impl(tcx.hir.local_def_id(node_id)); + for &node_id in tcx.hir().trait_impls(trait_id) { + add_impl(tcx.hir().local_def_id(node_id)); } } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 51b197d7b99..f9ce228a30c 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -344,7 +344,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// themselves. This should really be a unique type; `FreshTy(0)` is a /// popular choice. /// - /// NB: in some cases, particularly around higher-ranked bounds, + /// N.B., in some cases, particularly around higher-ranked bounds, /// this function returns a kind of conservative approximation. /// That is, all regions returned by this function are definitely /// required, but there may be other region bounds that are not @@ -451,9 +451,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // destructor will not access borrowed data, // even if such data is otherwise reachable. // - // Such access can be in plain sight (e.g. dereferencing + // Such access can be in plain sight (e.g., dereferencing // `*foo.0` of `Foo<'a>(&'a u32)`) or indirectly hidden - // (e.g. calling `foo.0.clone()` of `Foo`). + // (e.g., calling `foo.0.clone()` of `Foo`). if self.has_attr(dtor, "unsafe_destructor_blind_to_params") { debug!("destructor_constraint({:?}) - blind", def.did); return vec![]; @@ -601,7 +601,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Return whether the node pointed to by def_id is a static item, and its mutability pub fn is_static(&self, def_id: DefId) -> Option { - if let Some(node) = self.hir.get_if_local(def_id) { + if let Some(node) = self.hir().get_if_local(def_id) { match node { Node::Item(&hir::Item { node: hir::ItemKind::Static(_, mutbl, _), .. @@ -656,7 +656,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { /// If `ty.needs_drop(...)` returns `true`, then `ty` is definitely /// non-copy and *might* have a destructor attached; if it returns - /// `false`, then `ty` definitely has no destructor (i.e. no drop glue). + /// `false`, then `ty` definitely has no destructor (i.e., no drop glue). /// /// (Note that this implies that if `ty` has a destructor attached, /// then `needs_drop` will definitely return `true` for `ty`.) @@ -711,7 +711,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { // Find non representable fields with their spans fold_repr(def.all_fields().map(|field| { let ty = field.ty(tcx, substs); - let span = tcx.hir.span_if_local(field.did).unwrap_or(sp); + let span = tcx.hir().span_if_local(field.did).unwrap_or(sp); match is_type_structurally_recursive(tcx, span, seen, representable_cache, ty) { diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index 7a246af82e5..68e197849b0 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -28,7 +28,7 @@ use lazy_static; use session::Session; // The name of the associated type for `Fn` return types -pub const FN_OUTPUT_NAME: &'static str = "Output"; +pub const FN_OUTPUT_NAME: &str = "Output"; // Useful type to use with `Result<>` indicate that an error has already // been reported to the user, so no need to continue checking. @@ -342,7 +342,7 @@ pub trait MemoizationMap { /// If `key` is present in the map, return the value, /// otherwise invoke `op` and store the value in the map. /// - /// NB: if the receiver is a `DepTrackingMap`, special care is + /// N.B., if the receiver is a `DepTrackingMap`, special care is /// needed in the `op` to ensure that the correct edges are /// added into the dep graph. See the `DepTrackingMap` impl for /// more details! diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index eea3b54919d..e248f6b42be 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -523,7 +523,7 @@ impl PrintContext { } }; let _ = write!(f, "{}", name); - ty::BrNamed(tcx.hir.local_def_id(CRATE_NODE_ID), name) + ty::BrNamed(tcx.hir().local_def_id(CRATE_NODE_ID), name) } }; tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)) @@ -679,7 +679,7 @@ impl fmt::Debug for ty::UpvarId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "UpvarId({:?};`{}`;{:?})", self.var_path.hir_id, - ty::tls::with(|tcx| tcx.hir.name(tcx.hir.hir_to_node_id(self.var_path.hir_id))), + ty::tls::with(|tcx| tcx.hir().name(tcx.hir().hir_to_node_id(self.var_path.hir_id))), self.closure_expr_id) } } @@ -1208,15 +1208,15 @@ define_print! { write!(f, "[static generator")?; } - if let Some(node_id) = tcx.hir.as_local_node_id(did) { - write!(f, "@{:?}", tcx.hir.span(node_id))?; + if let Some(node_id) = tcx.hir().as_local_node_id(did) { + write!(f, "@{:?}", tcx.hir().span(node_id))?; let mut sep = " "; tcx.with_freevars(node_id, |freevars| { for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) { print!(f, cx, write("{}{}:", sep, - tcx.hir.name(freevar.var_id())), + tcx.hir().name(freevar.var_id())), print(upvar_ty))?; sep = ", "; } @@ -1244,11 +1244,11 @@ define_print! { let upvar_tys = substs.upvar_tys(did, tcx); write!(f, "[closure")?; - if let Some(node_id) = tcx.hir.as_local_node_id(did) { + if let Some(node_id) = tcx.hir().as_local_node_id(did) { if tcx.sess.opts.debugging_opts.span_free_formats { write!(f, "@{:?}", node_id)?; } else { - write!(f, "@{:?}", tcx.hir.span(node_id))?; + write!(f, "@{:?}", tcx.hir().span(node_id))?; } let mut sep = " "; tcx.with_freevars(node_id, |freevars| { @@ -1256,7 +1256,7 @@ define_print! { print!(f, cx, write("{}{}:", sep, - tcx.hir.name(freevar.var_id())), + tcx.hir().name(freevar.var_id())), print(upvar_ty))?; sep = ", "; } diff --git a/src/librustc/util/profiling.rs b/src/librustc/util/profiling.rs index bea3453b31a..c2bfa62cf9d 100644 --- a/src/librustc/util/profiling.rs +++ b/src/librustc/util/profiling.rs @@ -11,7 +11,7 @@ use session::config::Options; use std::fs; -use std::io::{self, StdoutLock, Write}; +use std::io::{self, StderrLock, Write}; use std::time::{Duration, Instant}; macro_rules! define_categories { @@ -61,12 +61,16 @@ macro_rules! define_categories { } } - fn print(&self, lock: &mut StdoutLock<'_>) { - writeln!(lock, "| Phase | Time (ms) | Queries | Hits (%) |") + fn print(&self, lock: &mut StderrLock<'_>) { + writeln!(lock, "| Phase | Time (ms) \ + | Time (%) | Queries | Hits (%)") .unwrap(); - writeln!(lock, "| ---------------- | -------------- | -------------- | -------- |") + writeln!(lock, "| ---------------- | -------------- \ + | -------- | -------------- | --------") .unwrap(); + let total_time = ($(self.times.$name + )* 0) as f32; + $( let (hits, total) = self.query_counts.$name; let (hits, total) = if total > 0 { @@ -78,11 +82,12 @@ macro_rules! define_categories { writeln!( lock, - "| {0: <16} | {1: <14} | {2: <14} | {3: <8} |", + "| {0: <16} | {1: <14} | {2: <8.2} | {3: <14} | {4: <8}", stringify!($name), self.times.$name / 1_000_000, + ((self.times.$name as f32) / total_time) * 100.0, total, - hits + hits, ).unwrap(); )* } @@ -235,7 +240,7 @@ impl SelfProfiler { self.timer_stack.is_empty(), "there were timers running when print_results() was called"); - let out = io::stdout(); + let out = io::stderr(); let mut lock = out.lock(); let crate_name = diff --git a/src/librustc_allocator/Cargo.toml b/src/librustc_allocator/Cargo.toml index cd3ef6a1f04..03d33f413c8 100644 --- a/src/librustc_allocator/Cargo.toml +++ b/src/librustc_allocator/Cargo.toml @@ -16,4 +16,4 @@ rustc_target = { path = "../librustc_target" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } log = "0.4" -smallvec = { version = "0.6.5", features = ["union"] } +smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } diff --git a/src/librustc_apfloat/Cargo.toml b/src/librustc_apfloat/Cargo.toml index a8a5da90c7a..248f2d71f41 100644 --- a/src/librustc_apfloat/Cargo.toml +++ b/src/librustc_apfloat/Cargo.toml @@ -10,4 +10,4 @@ path = "lib.rs" [dependencies] bitflags = "1.0" rustc_cratesio_shim = { path = "../librustc_cratesio_shim" } -smallvec = { version = "0.6.5", features = ["union"] } +smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } diff --git a/src/librustc_apfloat/ieee.rs b/src/librustc_apfloat/ieee.rs index adcb9857ee3..60ddac1abfd 100644 --- a/src/librustc_apfloat/ieee.rs +++ b/src/librustc_apfloat/ieee.rs @@ -571,7 +571,7 @@ impl fmt::Display for IeeeFloat { } // Fill with zeros up to precision. if !truncate_zero && precision > digits - 1 { - for _ in 0..precision - digits + 1 { + for _ in 0..=precision - digits { f.write_char('0')?; } } @@ -926,7 +926,7 @@ impl Float for IeeeFloat { // In case MSB resides at the left-hand side of radix point, shift the // mantissa right by some amount to make sure the MSB reside right before - // the radix point (i.e. "MSB . rest-significant-bits"). + // the radix point (i.e., "MSB . rest-significant-bits"). if omsb > S::PRECISION { let bits = omsb - S::PRECISION; loss = sig::shift_right(&mut wide_sig, &mut self.exp, bits).combine(loss); @@ -1969,7 +1969,7 @@ impl IeeeFloat { // in a Limb. When this would overflow do we do a single // bignum multiplication, and then revert again to multiplication // in a Limb. - let mut chars = s[first_sig_digit..last_sig_digit + 1].chars(); + let mut chars = s[first_sig_digit..=last_sig_digit].chars(); loop { let mut val = 0; let mut multiplier = 1; @@ -2674,7 +2674,7 @@ mod sig { // In case MSB resides at the left-hand side of radix point, shift the // mantissa right by some amount to make sure the MSB reside right before - // the radix point (i.e. "MSB . rest-significant-bits"). + // the radix point (i.e., "MSB . rest-significant-bits"). // // Note that the result is not normalized when "omsb < precision". So, the // caller needs to call IeeeFloat::normalize() if normalized value is diff --git a/src/librustc_apfloat/lib.rs b/src/librustc_apfloat/lib.rs index 69c9f385409..c9019171601 100644 --- a/src/librustc_apfloat/lib.rs +++ b/src/librustc_apfloat/lib.rs @@ -26,8 +26,8 @@ //! Comments have been preserved where possible, only slightly adapted. //! //! Instead of keeping a pointer to a configuration struct and inspecting it -//! dynamically on every operation, types (e.g. `ieee::Double`), traits -//! (e.g. `ieee::Semantics`) and associated constants are employed for +//! dynamically on every operation, types (e.g., `ieee::Double`), traits +//! (e.g., `ieee::Semantics`) and associated constants are employed for //! increased type safety and performance. //! //! On-heap bigints are replaced everywhere (except in decimal conversion), @@ -179,7 +179,7 @@ pub struct ParseError(pub &'static str); /// implemented operations. Currently implemented operations are add, subtract, /// multiply, divide, fused-multiply-add, conversion-to-float, /// conversion-to-integer and conversion-from-integer. New rounding modes -/// (e.g. away from zero) can be added with three or four lines of code. +/// (e.g., away from zero) can be added with three or four lines of code. /// /// Four formats are built-in: IEEE single precision, double precision, /// quadruple precision, and x87 80-bit extended double (when operating with @@ -589,7 +589,7 @@ pub trait Float pub trait FloatConvert: Float { /// Convert a value of one floating point type to another. /// The return value corresponds to the IEEE754 exceptions. *loses_info - /// records whether the transformation lost information, i.e. whether + /// records whether the transformation lost information, i.e., whether /// converting the result back to the original type will produce the /// original value (this is almost the same as return value==Status::OK, /// but there are edge cases where this is not so). diff --git a/src/librustc_apfloat/ppc.rs b/src/librustc_apfloat/ppc.rs index e662088e82f..aaf6b29a99e 100644 --- a/src/librustc_apfloat/ppc.rs +++ b/src/librustc_apfloat/ppc.rs @@ -288,7 +288,7 @@ where // \ / // Normal // - // e.g. NaN * NaN = NaN + // e.g., NaN * NaN = NaN // Zero * Inf = NaN // Normal * Zero = Zero // Normal * Inf = Inf diff --git a/src/librustc_asan/Cargo.toml b/src/librustc_asan/Cargo.toml index 734564c2d85..836caf22abf 100644 --- a/src/librustc_asan/Cargo.toml +++ b/src/librustc_asan/Cargo.toml @@ -16,4 +16,4 @@ cmake = "0.1.18" [dependencies] alloc = { path = "../liballoc" } core = { path = "../libcore" } -compiler_builtins = { path = "../rustc/compiler_builtins_shim" } +compiler_builtins = "0.1.0" diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index a802729e3fb..51afb43d973 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -105,7 +105,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> { debug!("consume(consume_id={}, cmt={:?}, mode={:?})", consume_id, cmt, mode); - let hir_id = self.tcx().hir.node_to_hir_id(consume_id); + let hir_id = self.tcx().hir().node_to_hir_id(consume_id); self.consume_common(hir_id.local_id, consume_span, cmt, mode); } @@ -139,7 +139,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> { borrow_id, cmt, loan_region, bk, loan_cause); - let hir_id = self.tcx().hir.node_to_hir_id(borrow_id); + let hir_id = self.tcx().hir().node_to_hir_id(borrow_id); if let Some(lp) = opt_loan_path(cmt) { let moved_value_use_kind = match loan_cause { euv::ClosureCapture(_) => MovedInCapture, @@ -185,7 +185,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> { } } } - self.check_assignment(self.tcx().hir.node_to_hir_id(assignment_id).local_id, + self.check_assignment(self.tcx().hir().node_to_hir_id(assignment_id).local_id, assignment_span, assignee_cmt); } @@ -199,10 +199,10 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, body: &hir::Body) { debug!("check_loans(body id={})", body.value.id); - let def_id = bccx.tcx.hir.body_owner_def_id(body.id()); + let def_id = bccx.tcx.hir().body_owner_def_id(body.id()); - let node_id = bccx.tcx.hir.as_local_node_id(def_id).unwrap(); - let movable_generator = !match bccx.tcx.hir.get(node_id) { + let node_id = bccx.tcx.hir().as_local_node_id(def_id).unwrap(); + let movable_generator = !match bccx.tcx.hir().get(node_id) { Node::Expr(&hir::Expr { node: hir::ExprKind::Closure(.., Some(hir::GeneratorMovability::Static)), .. @@ -615,7 +615,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { let new_loan_str = &new_loan.kind.to_user_str(); self.bccx.cannot_reborrow_already_uniquely_borrowed( new_loan.span, "closure", &nl, &new_loan_msg, new_loan_str, - old_loan.span, &old_loan_msg, previous_end_span, Origin::Ast) + old_loan.span, &old_loan_msg, previous_end_span, "", Origin::Ast) } (..) => self.bccx.cannot_reborrow_already_borrowed( @@ -907,7 +907,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { let lp = opt_loan_path(assignee_cmt).unwrap(); self.move_data.each_assignment_of(assignment_id, &lp, |assign| { if assignee_cmt.mutbl.is_mutable() { - let hir_id = self.bccx.tcx.hir.node_to_hir_id(local_id); + let hir_id = self.bccx.tcx.hir().node_to_hir_id(local_id); self.bccx.used_mut_nodes.borrow_mut().insert(hir_id); } else { self.bccx.report_reassigned_immutable_variable( diff --git a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs index 7bb5f411752..9fa541cdd07 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs @@ -57,9 +57,9 @@ pub enum PatternSource<'tcx> { /// with a reference to the let fn get_pattern_source<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pat: &Pat) -> PatternSource<'tcx> { - let parent = tcx.hir.get_parent_node(pat.id); + let parent = tcx.hir().get_parent_node(pat.id); - match tcx.hir.get(parent) { + match tcx.hir().get(parent) { Node::Expr(ref e) => { // the enclosing expression must be a `match` or something else assert!(match e.node { @@ -79,7 +79,7 @@ pub fn gather_decl<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, var_id: ast::NodeId, var_ty: Ty<'tcx>) { let loan_path = Rc::new(LoanPath::new(LpVar(var_id), var_ty)); - let hir_id = bccx.tcx.hir.node_to_hir_id(var_id); + let hir_id = bccx.tcx.hir().node_to_hir_id(var_id); move_data.add_move(bccx.tcx, loan_path, hir_id.local_id, Declared); } diff --git a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs index 6ef5d65d10d..ccc091a6a1c 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs @@ -114,7 +114,7 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> { self.bccx.tcx.mk_region(ty::ReScope(self.item_scope)) } Categorization::Local(local_id) => { - let hir_id = self.bccx.tcx.hir.node_to_hir_id(local_id); + let hir_id = self.bccx.tcx.hir().node_to_hir_id(local_id); self.bccx.tcx.mk_region(ty::ReScope( self.bccx.region_scope_tree.var_scope(hir_id.local_id))) } diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index 21fb0cdf90a..7ed4d4910d7 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -38,13 +38,13 @@ mod move_error; pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, body: hir::BodyId) -> (Vec>, move_data::MoveData<'tcx>) { - let def_id = bccx.tcx.hir.body_owner_def_id(body); + let def_id = bccx.tcx.hir().body_owner_def_id(body); let param_env = bccx.tcx.param_env(def_id); let mut glcx = GatherLoanCtxt { bccx, all_loans: Vec::new(), item_ub: region::Scope { - id: bccx.tcx.hir.body(body).value.hir_id.local_id, + id: bccx.tcx.hir().body(body).value.hir_id.local_id, data: region::ScopeData::Node }, move_data: MoveData::default(), @@ -88,7 +88,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> { euv::Move(move_reason) => { gather_moves::gather_move_from_expr( self.bccx, &self.move_data, &mut self.move_error_collector, - self.bccx.tcx.hir.node_to_hir_id(consume_id).local_id, cmt, move_reason); + self.bccx.tcx.hir().node_to_hir_id(consume_id).local_id, cmt, move_reason); } euv::Copy => { } } @@ -135,7 +135,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> { bk={:?}, loan_cause={:?})", borrow_id, cmt, loan_region, bk, loan_cause); - let hir_id = self.bccx.tcx.hir.node_to_hir_id(borrow_id); + let hir_id = self.bccx.tcx.hir().node_to_hir_id(borrow_id); self.guarantee_valid(hir_id.local_id, borrow_span, cmt, @@ -158,7 +158,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> { fn decl_without_init(&mut self, id: ast::NodeId, _span: Span) { let ty = self.bccx .tables - .node_id_to_type(self.bccx.tcx.hir.node_to_hir_id(id)); + .node_id_to_type(self.bccx.tcx.hir().node_to_hir_id(id)); gather_moves::gather_decl(self.bccx, &self.move_data, id, ty); } } @@ -280,13 +280,13 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { self.mark_loan_path_as_mutated(&lp); } gather_moves::gather_assignment(self.bccx, &self.move_data, - self.bccx.tcx.hir.node_to_hir_id(assignment_id) + self.bccx.tcx.hir().node_to_hir_id(assignment_id) .local_id, assignment_span, lp); } None => { - // This can occur with e.g. `*foo() = 5`. In such + // This can occur with e.g., `*foo() = 5`. In such // cases, there is no need to check for conflicts // with moves etc, just ignore. } @@ -448,7 +448,7 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { wrapped_path = match current_path.kind { LpVar(local_id) => { if !through_borrow { - let hir_id = self.bccx.tcx.hir.node_to_hir_id(local_id); + let hir_id = self.bccx.tcx.hir().node_to_hir_id(local_id); self.bccx.used_mut_nodes.borrow_mut().insert(hir_id); } None diff --git a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs index cfd530b7e3d..08c5b247b2f 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs @@ -97,8 +97,8 @@ fn report_move_errors<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, errors: &[MoveErr } } if let NoteClosureEnv(upvar_id) = error.move_from.note { - let var_node_id = bccx.tcx.hir.hir_to_node_id(upvar_id.var_path.hir_id); - err.span_label(bccx.tcx.hir.span(var_node_id), + let var_node_id = bccx.tcx.hir().hir_to_node_id(upvar_id.var_path.hir_id); + err.span_label(bccx.tcx.hir().span(var_node_id), "captured outer variable"); } err.emit(); diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index d189460d088..cb1200f462f 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -93,9 +93,9 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) debug!("borrowck(body_owner_def_id={:?})", owner_def_id); - let owner_id = tcx.hir.as_local_node_id(owner_def_id).unwrap(); + let owner_id = tcx.hir().as_local_node_id(owner_def_id).unwrap(); - match tcx.hir.get(owner_id) { + match tcx.hir().get(owner_id) { Node::StructCtor(_) | Node::Variant(_) => { // We get invoked with anything that has MIR, but some of @@ -110,10 +110,10 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) _ => { } } - let body_id = tcx.hir.body_owned_by(owner_id); + let body_id = tcx.hir().body_owned_by(owner_id); let tables = tcx.typeck_tables_of(owner_def_id); let region_scope_tree = tcx.region_scope_tree(owner_def_id); - let body = tcx.hir.body(body_id); + let body = tcx.hir().body(body_id); let mut bccx = BorrowckCtxt { tcx, tables, @@ -169,7 +169,7 @@ fn build_borrowck_dataflow_data<'a, 'c, 'tcx, F>(this: &mut BorrowckCtxt<'a, 'tc // Check the body of fn items. let tcx = this.tcx; let id_range = { - let mut visitor = intravisit::IdRangeComputingVisitor::new(&tcx.hir); + let mut visitor = intravisit::IdRangeComputingVisitor::new(&tcx.hir()); visitor.visit_body(this.body); visitor.result() }; @@ -217,18 +217,18 @@ fn build_borrowck_dataflow_data<'a, 'c, 'tcx, F>(this: &mut BorrowckCtxt<'a, 'tc } /// Accessor for introspective clients inspecting `AnalysisData` and -/// the `BorrowckCtxt` itself , e.g. the flowgraph visualizer. +/// the `BorrowckCtxt` itself , e.g., the flowgraph visualizer. pub fn build_borrowck_dataflow_data_for_fn<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, body_id: hir::BodyId, cfg: &cfg::CFG) -> (BorrowckCtxt<'a, 'tcx>, AnalysisData<'a, 'tcx>) { - let owner_id = tcx.hir.body_owner(body_id); - let owner_def_id = tcx.hir.local_def_id(owner_id); + let owner_id = tcx.hir().body_owner(body_id); + let owner_def_id = tcx.hir().local_def_id(owner_id); let tables = tcx.typeck_tables_of(owner_def_id); let region_scope_tree = tcx.region_scope_tree(owner_def_id); - let body = tcx.hir.body(body_id); + let body = tcx.hir().body(body_id); let mut bccx = BorrowckCtxt { tcx, tables, @@ -418,8 +418,8 @@ pub enum LoanPathElem<'tcx> { fn closure_to_block(closure_id: LocalDefId, tcx: TyCtxt) -> ast::NodeId { - let closure_id = tcx.hir.local_def_id_to_node_id(closure_id); - match tcx.hir.get(closure_id) { + let closure_id = tcx.hir().local_def_id_to_node_id(closure_id); + match tcx.hir().get(closure_id) { Node::Expr(expr) => match expr.node { hir::ExprKind::Closure(.., body_id, _, _) => { body_id.node_id @@ -436,12 +436,12 @@ impl<'a, 'tcx> LoanPath<'tcx> { pub fn kill_scope(&self, bccx: &BorrowckCtxt<'a, 'tcx>) -> region::Scope { match self.kind { LpVar(local_id) => { - let hir_id = bccx.tcx.hir.node_to_hir_id(local_id); + let hir_id = bccx.tcx.hir().node_to_hir_id(local_id); bccx.region_scope_tree.var_scope(hir_id.local_id) } 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); + let hir_id = bccx.tcx.hir().node_to_hir_id(block_id); region::Scope { id: hir_id.local_id, data: region::ScopeData::Node } } LpDowncast(ref base, _) | @@ -700,8 +700,8 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { Origin::Ast); let need_note = match lp.ty.sty { ty::Closure(id, _) => { - let node_id = self.tcx.hir.as_local_node_id(id).unwrap(); - let hir_id = self.tcx.hir.node_to_hir_id(node_id); + let node_id = self.tcx.hir().as_local_node_id(id).unwrap(); + let hir_id = self.tcx.hir().node_to_hir_id(node_id); if let Some((span, name)) = self.tables.closure_kind_origins().get(hir_id) { err.span_note(*span, &format!( "closure cannot be invoked more than once because \ @@ -721,7 +721,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { // Get type of value and span where it was previously // moved. - let node_id = self.tcx.hir.hir_to_node_id(hir::HirId { + let node_id = self.tcx.hir().hir_to_node_id(hir::HirId { owner: self.body.value.hir_id.owner, local_id: the_move.id }); @@ -731,10 +731,10 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { } move_data::MoveExpr | - move_data::MovePat => (self.tcx.hir.span(node_id), ""), + move_data::MovePat => (self.tcx.hir().span(node_id), ""), move_data::Captured => - (match self.tcx.hir.expect_expr(node_id).node { + (match self.tcx.hir().expect_expr(node_id).node { hir::ExprKind::Closure(.., fn_decl_span, _) => fn_decl_span, ref r => bug!("Captured({:?}) maps to non-closure: {:?}", the_move.id, r), @@ -846,8 +846,8 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { MutabilityViolation => { let mut db = self.cannot_assign(error_span, &descr, Origin::Ast); if let mc::NoteClosureEnv(upvar_id) = err.cmt.note { - let node_id = self.tcx.hir.hir_to_node_id(upvar_id.var_path.hir_id); - let sp = self.tcx.hir.span(node_id); + let node_id = self.tcx.hir().hir_to_node_id(upvar_id.var_path.hir_id); + let sp = self.tcx.hir().span(node_id); let fn_closure_msg = "`Fn` closures cannot capture their enclosing \ environment for modifications"; match (self.tcx.sess.source_map().span_to_snippet(sp), &err.cmt.cat) { @@ -916,8 +916,8 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { // to implement two traits for "one operator" is not very intuitive for // many programmers. if err.cmt.note == mc::NoteIndex { - let node_id = self.tcx.hir.hir_to_node_id(err.cmt.hir_id); - let node = self.tcx.hir.get(node_id); + let node_id = self.tcx.hir().hir_to_node_id(err.cmt.hir_id); + let node = self.tcx.hir().get(node_id); // This pattern probably always matches. if let Node::Expr( @@ -937,7 +937,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { self.note_immutability_blame( &mut db, err.cmt.immutability_blame(), - self.tcx.hir.hir_to_node_id(err.cmt.hir_id) + self.tcx.hir().hir_to_node_id(err.cmt.hir_id) ); db.emit(); self.signal_error(); @@ -1043,7 +1043,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { if let ty::ReScope(scope) = *super_scope { let node_id = scope.node_id(self.tcx, &self.region_scope_tree); - match self.tcx.hir.find(node_id) { + match self.tcx.hir().find(node_id) { Some(Node::Stmt(_)) => { if *sub_scope != ty::ReStatic { db.note("consider using a `let` binding to increase its lifetime"); @@ -1138,8 +1138,8 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { } else { "consider changing this closure to take self by mutable reference" }; - let node_id = self.tcx.hir.local_def_id_to_node_id(id); - let help_span = self.tcx.hir.span(node_id); + let node_id = self.tcx.hir().local_def_id_to_node_id(id); + let help_span = self.tcx.hir().span(node_id); self.cannot_act_on_capture_in_sharable_fn(span, prefix, (help_span, help_msg), @@ -1153,7 +1153,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { self.note_immutability_blame( &mut err, blame, - self.tcx.hir.hir_to_node_id(cmt.hir_id) + self.tcx.hir().hir_to_node_id(cmt.hir_id) ); if is_closure { @@ -1194,7 +1194,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { } fn local_binding_mode(&self, node_id: ast::NodeId) -> ty::BindingMode { - let pat = match self.tcx.hir.get(node_id) { + let pat = match self.tcx.hir().get(node_id) { Node::Binding(pat) => pat, node => bug!("bad node for local: {:?}", node) }; @@ -1211,13 +1211,13 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { } fn local_ty(&self, node_id: ast::NodeId) -> (Option<&hir::Ty>, bool) { - let parent = self.tcx.hir.get_parent_node(node_id); - let parent_node = self.tcx.hir.get(parent); + let parent = self.tcx.hir().get_parent_node(node_id); + let parent_node = self.tcx.hir().get(parent); // The parent node is like a fn if let Some(fn_like) = FnLikeNode::from_node(parent_node) { // `nid`'s parent's `Body` - let fn_body = self.tcx.hir.body(fn_like.body()); + let fn_body = self.tcx.hir().body(fn_like.body()); // Get the position of `node_id` in the arguments list let arg_pos = fn_body.arguments.iter().position(|arg| arg.pat.id == node_id); if let Some(i) = arg_pos { @@ -1245,7 +1245,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { Some(ImmutabilityBlame::LocalDeref(node_id)) => { match self.local_binding_mode(node_id) { ty::BindByReference(..) => { - let let_span = self.tcx.hir.span(node_id); + 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_with_applicability( @@ -1272,12 +1272,12 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { } } Some(ImmutabilityBlame::AdtFieldDeref(_, field)) => { - let node_id = match self.tcx.hir.as_local_node_id(field.did) { + let node_id = match self.tcx.hir().as_local_node_id(field.did) { Some(node_id) => node_id, None => return }; - if let Node::Field(ref field) = self.tcx.hir.get(node_id) { + if let Node::Field(ref field) = self.tcx.hir().get(node_id) { if let Some(msg) = self.suggest_mut_for_immutable(&field.ty, false) { db.span_label(field.ty.span, msg); } @@ -1293,7 +1293,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { db: &mut DiagnosticBuilder, borrowed_node_id: ast::NodeId, binding_node_id: ast::NodeId) { - let let_span = self.tcx.hir.span(binding_node_id); + let let_span = self.tcx.hir().span(binding_node_id); if let ty::BindByValue(..) = self.local_binding_mode(binding_node_id) { if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(let_span) { let (ty, is_implicit_self) = self.local_ty(binding_node_id); @@ -1309,9 +1309,9 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { }, )) = ty.map(|t| &t.node) { - let borrow_expr_id = self.tcx.hir.get_parent_node(borrowed_node_id); + let borrow_expr_id = self.tcx.hir().get_parent_node(borrowed_node_id); db.span_suggestion_with_applicability( - self.tcx.hir.span(borrow_expr_id), + self.tcx.hir().span(borrow_expr_id), "consider removing the `&mut`, as it is an \ immutable binding to a mutable reference", snippet, @@ -1381,8 +1381,8 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { }; if *kind == ty::ClosureKind::Fn { let closure_node_id = - self.tcx.hir.local_def_id_to_node_id(upvar_id.closure_expr_id); - db.span_help(self.tcx.hir.span(closure_node_id), + self.tcx.hir().local_def_id_to_node_id(upvar_id.closure_expr_id); + db.span_help(self.tcx.hir().span(closure_node_id), "consider changing this closure to take \ self by mutable reference"); } @@ -1391,7 +1391,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { if let Categorization::Deref(..) = err.cmt.cat { db.span_label(*error_span, "cannot borrow as mutable"); } else if let Categorization::Local(local_id) = err.cmt.cat { - let span = self.tcx.hir.span(local_id); + let span = self.tcx.hir().span(local_id); if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { if snippet.starts_with("ref mut ") || snippet.starts_with("&mut ") { db.span_label(*error_span, "cannot reborrow mutably"); @@ -1416,10 +1416,10 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { out: &mut String) { match loan_path.kind { LpUpvar(ty::UpvarId { var_path: ty::UpvarPath { hir_id: id}, closure_expr_id: _ }) => { - out.push_str(&self.tcx.hir.name(self.tcx.hir.hir_to_node_id(id)).as_str()); + out.push_str(&self.tcx.hir().name(self.tcx.hir().hir_to_node_id(id)).as_str()); } LpVar(id) => { - out.push_str(&self.tcx.hir.name(id).as_str()); + out.push_str(&self.tcx.hir().name(id).as_str()); } LpDowncast(ref lp_base, variant_def_id) => { @@ -1530,13 +1530,13 @@ impl<'tcx> fmt::Debug for LoanPath<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.kind { LpVar(id) => { - write!(f, "$({})", ty::tls::with(|tcx| tcx.hir.node_to_string(id))) + write!(f, "$({})", ty::tls::with(|tcx| tcx.hir().node_to_string(id))) } LpUpvar(ty::UpvarId{ var_path: ty::UpvarPath {hir_id: var_id}, closure_expr_id }) => { let s = ty::tls::with(|tcx| { - let var_node_id = tcx.hir.hir_to_node_id(var_id); - tcx.hir.node_to_string(var_node_id) + let var_node_id = tcx.hir().hir_to_node_id(var_id); + tcx.hir().node_to_string(var_node_id) }); write!(f, "$({} captured by id={:?})", s, closure_expr_id) } @@ -1565,13 +1565,13 @@ impl<'tcx> fmt::Display for LoanPath<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.kind { LpVar(id) => { - write!(f, "$({})", ty::tls::with(|tcx| tcx.hir.node_to_user_string(id))) + write!(f, "$({})", ty::tls::with(|tcx| tcx.hir().node_to_user_string(id))) } LpUpvar(ty::UpvarId{ var_path: ty::UpvarPath { hir_id }, closure_expr_id: _ }) => { let s = ty::tls::with(|tcx| { - let var_node_id = tcx.hir.hir_to_node_id(hir_id); - tcx.hir.node_to_string(var_node_id) + let var_node_id = tcx.hir().hir_to_node_id(hir_id); + tcx.hir().node_to_string(var_node_id) }); write!(f, "$({} captured by closure)", s) } diff --git a/src/librustc_borrowck/borrowck/unused.rs b/src/librustc_borrowck/borrowck/unused.rs index 85794c5b10a..a9a33f35842 100644 --- a/src/librustc_borrowck/borrowck/unused.rs +++ b/src/librustc_borrowck/borrowck/unused.rs @@ -100,7 +100,7 @@ impl<'a, 'tcx> UnusedMutCx<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for UnusedMutCx<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.bccx.tcx.hir) + NestedVisitorMap::OnlyBodies(&self.bccx.tcx.hir()) } fn visit_arm(&mut self, arm: &hir::Arm) { @@ -114,12 +114,12 @@ impl<'a, 'tcx> Visitor<'tcx> for UnusedMutCx<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for UsedMutFinder<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.bccx.tcx.hir) + NestedVisitorMap::OnlyBodies(&self.bccx.tcx.hir()) } fn visit_nested_body(&mut self, id: hir::BodyId) { - let def_id = self.bccx.tcx.hir.body_owner_def_id(id); + let def_id = self.bccx.tcx.hir().body_owner_def_id(id); self.set.extend(self.bccx.tcx.borrowck(def_id).used_mut_nodes.iter().cloned()); - self.visit_body(self.bccx.tcx.hir.body(id)); + self.visit_body(self.bccx.tcx.hir().body(id)); } } diff --git a/src/librustc_borrowck/dataflow.rs b/src/librustc_borrowck/dataflow.rs index 1760fb138ea..d12c22109c6 100644 --- a/src/librustc_borrowck/dataflow.rs +++ b/src/librustc_borrowck/dataflow.rs @@ -71,7 +71,7 @@ pub struct DataFlowContext<'a, 'tcx: 'a, O> { scope_kills: Vec, /// bits killed as we exit the cfg node directly; if it is jumped - /// over, e.g. via `break`, the kills are not reflected in the + /// over, e.g., via `break`, the kills are not reflected in the /// jump's effects. Updated by `add_kill(KillFrom::Execution)`. action_kills: Vec, @@ -111,7 +111,7 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { impl<'a, 'tcx, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, 'tcx, O> { fn nested(&self, state: &mut pprust::State, nested: pprust::Nested) -> io::Result<()> { - pprust::PpAnn::nested(&self.tcx.hir, state, nested) + pprust::PpAnn::nested(self.tcx.hir(), state, nested) } fn pre(&self, ps: &mut pprust::State, @@ -172,7 +172,7 @@ fn build_local_id_to_index(body: Option<&hir::Body>, let mut index = FxHashMap::default(); // FIXME(#15020) Would it be better to fold formals from decl - // into cfg itself? i.e. introduce a fn-based flow-graph in + // into cfg itself? i.e., introduce a fn-based flow-graph in // addition to the current block-based flow-graph, rather than // have to put traversals like this here? if let Some(body) = body { @@ -430,7 +430,7 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { for offset in 0..usize_bits { let bit = 1 << offset; if (word & bit) != 0 { - // NB: we round up the total number of bits + // N.B., we round up the total number of bits // that we store in any given bit set so that // it is an even multiple of usize::BITS. This // means that there may be some stray bits at diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index 5b6d157043d..b8954dee794 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -185,7 +185,7 @@ pub trait ArgTypeExt<'ll, 'tcx> { impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> { /// Get the LLVM type for a place of the original Rust type of - /// this argument/return, i.e. the result of `type_of::type_of`. + /// this argument/return, i.e., the result of `type_of::type_of`. fn memory_ty(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type { self.layout.llvm_type(cx) } diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index 38ab1302cfa..48e0a3a12c9 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -15,14 +15,16 @@ use rustc::hir::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::session::Session; use rustc::session::config::Sanitizer; -use rustc::ty::TyCtxt; +use rustc::ty::{self, TyCtxt, PolyFnSig}; use rustc::ty::layout::HasTyCtxt; use rustc::ty::query::Providers; +use rustc_data_structures::small_c_str::SmallCStr; use rustc_data_structures::sync::Lrc; use rustc_data_structures::fx::FxHashMap; use rustc_target::spec::PanicStrategy; use rustc_codegen_ssa::traits::*; +use abi::Abi; use attributes; use llvm::{self, Attribute}; use llvm::AttributePlace::Function; @@ -60,7 +62,7 @@ pub fn emit_uwtable(val: &'ll Value, emit: bool) { /// Tell LLVM whether the function can or cannot unwind. #[inline] -pub fn unwind(val: &'ll Value, can_unwind: bool) { +fn unwind(val: &'ll Value, can_unwind: bool) { Attribute::NoUnwind.toggle_llfn(Function, val, !can_unwind); } @@ -71,7 +73,7 @@ pub fn set_optimize_for_size(val: &'ll Value, optimize: bool) { Attribute::OptimizeForSize.toggle_llfn(Function, val, optimize); } -/// Tell LLVM if this function should be 'naked', i.e. skip the epilogue and prologue. +/// Tell LLVM if this function should be 'naked', i.e., skip the epilogue and prologue. #[inline] pub fn naked(val: &'ll Value, is_naked: bool) { Attribute::Naked.toggle_llfn(Function, val, is_naked); @@ -129,8 +131,7 @@ pub fn llvm_target_features(sess: &Session) -> impl Iterator { } pub fn apply_target_cpu_attr(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { - let cpu = llvm_util::target_cpu(cx.tcx.sess); - let target_cpu = CString::new(cpu).unwrap(); + let target_cpu = SmallCStr::new(llvm_util::target_cpu(cx.tcx.sess)); llvm::AddFunctionAttrStringValue( llfn, llvm::AttributePlace::Function, @@ -147,12 +148,13 @@ pub fn non_lazy_bind(sess: &Session, llfn: &'ll Value) { } } -/// Composite function which sets LLVM attributes for function depending on its AST (#[attribute]) +/// Composite function which sets LLVM attributes for function depending on its AST (`#[attribute]`) /// attributes. pub fn from_fn_attrs( - cx: &CodegenCx<'ll, '_>, + cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, id: Option, + sig: PolyFnSig<'tcx>, ) { let codegen_fn_attrs = id.map(|id| cx.tcx.codegen_fn_attrs(id)) .unwrap_or_else(|| CodegenFnAttrs::new()); @@ -194,37 +196,42 @@ pub fn from_fn_attrs( llvm::AttributePlace::ReturnValue, llfn); } - let can_unwind = if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::UNWIND) { - Some(true) + unwind(llfn, if cx.tcx.sess.panic_strategy() != PanicStrategy::Unwind { + // In panic=abort mode we assume nothing can unwind anywhere, so + // optimize based on this! + false + } else if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::UNWIND) { + // If a specific #[unwind] attribute is present, use that + true } else if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_ALLOCATOR_NOUNWIND) { - Some(false) - - // Perhaps questionable, but we assume that anything defined - // *in Rust code* may unwind. Foreign items like `extern "C" { - // fn foo(); }` are assumed not to unwind **unless** they have - // a `#[unwind]` attribute. - } else if id.map(|id| !cx.tcx.is_foreign_item(id)).unwrap_or(false) { - Some(true) - } else { - None - }; - - match can_unwind { - Some(false) => attributes::unwind(llfn, false), - Some(true) if cx.tcx.sess.panic_strategy() == PanicStrategy::Unwind => { - attributes::unwind(llfn, true); + // Special attribute for allocator functions, which can't unwind + false + } else if let Some(id) = id { + let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); + if cx.tcx.is_foreign_item(id) { + // Foreign items like `extern "C" { fn foo(); }` are assumed not to + // unwind + false + } else if sig.abi != Abi::Rust && sig.abi != Abi::RustCall { + // Any items defined in Rust that *don't* have the `extern` ABI are + // defined to not unwind. We insert shims to abort if an unwind + // happens to enforce this. + false + } else { + // Anything else defined in Rust is assumed that it can possibly + // unwind + true } - Some(true) | None => {} - } + } else { + // assume this can possibly unwind, avoiding the application of a + // `nounwind` attribute below. + true + }); // Always annotate functions with the target-cpu they are compiled for. // Without this, ThinLTO won't inline Rust functions into Clang generated // functions (because Clang annotates functions this way too). - // NOTE: For now we just apply this if -Zcross-lang-lto is specified, since - // it introduce a little overhead and isn't really necessary otherwise. - if cx.tcx.sess.opts.debugging_opts.cross_lang_lto.enabled() { - apply_target_cpu_attr(cx, llfn); - } + apply_target_cpu_attr(cx, llfn); let features = llvm_target_features(cx.tcx.sess) .map(|s| s.to_string()) diff --git a/src/librustc_codegen_llvm/back/link.rs b/src/librustc_codegen_llvm/back/link.rs index 68da14570e4..55ab0724e94 100644 --- a/src/librustc_codegen_llvm/back/link.rs +++ b/src/librustc_codegen_llvm/back/link.rs @@ -212,12 +212,7 @@ fn link_binary_output(sess: &Session, } fn archive_search_paths(sess: &Session) -> Vec { - let mut search = Vec::new(); - sess.target_filesearch(PathKind::Native).for_each_lib_search_path(|path, _| { - search.push(path.to_path_buf()); - }); - - search + sess.target_filesearch(PathKind::Native).search_path_dirs() } fn archive_config<'a>(sess: &'a Session, @@ -462,6 +457,21 @@ fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLibrary]) { } } +fn get_file_path(sess: &Session, name: &str) -> PathBuf { + let fs = sess.target_filesearch(PathKind::Native); + let file_path = fs.get_lib_path().join(name); + if file_path.exists() { + return file_path + } + for search_path in fs.search_paths() { + let file_path = search_path.dir.join(name); + if file_path.exists() { + return file_path + } + } + PathBuf::from(name) +} + // Create a dynamic library or executable // // This will invoke the system linker/cc to create the resulting file. This @@ -477,7 +487,6 @@ fn link_natively(sess: &Session, // The invocations of cc share some flags across platforms let (pname, mut cmd) = get_linker(sess, &linker, flavor); - let root = sess.target_filesearch(PathKind::Native).get_lib_path(); if let Some(args) = sess.target.target.options.pre_link_args.get(&flavor) { cmd.args(args); } @@ -505,12 +514,12 @@ fn link_natively(sess: &Session, &sess.target.target.options.pre_link_objects_dll }; for obj in pre_link_objects { - cmd.arg(root.join(obj)); + cmd.arg(get_file_path(sess, obj)); } if crate_type == config::CrateType::Executable && sess.crt_static() { for obj in &sess.target.target.options.pre_link_objects_exe_crt { - cmd.arg(root.join(obj)); + cmd.arg(get_file_path(sess, obj)); } } @@ -534,11 +543,11 @@ fn link_natively(sess: &Session, cmd.args(args); } for obj in &sess.target.target.options.post_link_objects { - cmd.arg(root.join(obj)); + cmd.arg(get_file_path(sess, obj)); } if sess.crt_static() { for obj in &sess.target.target.options.post_link_objects_crt { - cmd.arg(root.join(obj)); + cmd.arg(get_file_path(sess, obj)); } } if let Some(args) = sess.target.target.options.post_link_args.get(&flavor) { @@ -994,7 +1003,7 @@ fn link_args(cmd: &mut dyn Linker, // // The rationale behind this ordering is that those items lower down in the // list can't depend on items higher up in the list. For example nothing can - // depend on what we just generated (e.g. that'd be a circular dependency). + // depend on what we just generated (e.g., that'd be a circular dependency). // Upstream rust libraries are not allowed to depend on our local native // libraries as that would violate the structure of the DAG, in that // scenario they are required to link to them as well in a shared fashion. @@ -1003,7 +1012,7 @@ fn link_args(cmd: &mut dyn Linker, // well, but they also can't depend on what we just started to add to the // link line. And finally upstream native libraries can't depend on anything // in this DAG so far because they're only dylibs and dylibs can only depend - // on other dylibs (e.g. other native deps). + // on other dylibs (e.g., other native deps). add_local_native_libraries(cmd, sess, codegen_results); add_upstream_rust_crates(cmd, sess, codegen_results, crate_type, tmpdir); add_upstream_native_libraries(cmd, sess, codegen_results, crate_type); @@ -1024,11 +1033,10 @@ fn link_args(cmd: &mut dyn Linker, // where extern libraries might live, based on the // addl_lib_search_paths if sess.opts.cg.rpath { - let sysroot = sess.sysroot(); let target_triple = sess.opts.target_triple.triple(); let mut get_install_prefix_lib_path = || { let install_prefix = option_env!("CFG_PREFIX").expect("CFG_PREFIX"); - let tlib = filesearch::relative_target_lib_path(sysroot, target_triple); + let tlib = filesearch::relative_target_lib_path(&sess.sysroot, target_triple); let mut path = PathBuf::from(install_prefix); path.push(&tlib); @@ -1068,12 +1076,13 @@ fn link_args(cmd: &mut dyn Linker, fn add_local_native_libraries(cmd: &mut dyn Linker, sess: &Session, codegen_results: &CodegenResults) { - sess.target_filesearch(PathKind::All).for_each_lib_search_path(|path, k| { - match k { - PathKind::Framework => { cmd.framework_path(path); } - _ => { cmd.include_path(&fix_windows_verbatim_for_gcc(path)); } + let filesearch = sess.target_filesearch(PathKind::All); + for search_path in filesearch.search_paths() { + match search_path.kind { + PathKind::Framework => { cmd.framework_path(&search_path.dir); } + _ => { cmd.include_path(&fix_windows_verbatim_for_gcc(&search_path.dir)); } } - }); + } let relevant_libs = codegen_results.crate_info.used_libraries.iter().filter(|l| { relevant_lib(sess, l) @@ -1205,7 +1214,7 @@ fn add_upstream_rust_crates(cmd: &mut dyn Linker, // compiler-builtins are always placed last to ensure that they're // linked correctly. // We must always link the `compiler_builtins` crate statically. Even if it - // was already "included" in a dylib (e.g. `libstd` when `-C prefer-dynamic` + // was already "included" in a dylib (e.g., `libstd` when `-C prefer-dynamic` // is used) if let Some(cnum) = compiler_builtins { add_static_crate(cmd, sess, codegen_results, tmpdir, crate_type, cnum); @@ -1385,7 +1394,7 @@ fn add_upstream_rust_crates(cmd: &mut dyn Linker, // because a `dylib` can be reused as an intermediate artifact. // // Note, though, that we don't want to include the whole of a - // compiler-builtins crate (e.g. compiler-rt) because it'll get + // compiler-builtins crate (e.g., compiler-rt) because it'll get // repeatedly linked anyway. if crate_type == config::CrateType::Dylib && codegen_results.crate_info.compiler_builtins != Some(cnum) { diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs index 99828e5b7fb..bddb45da10b 100644 --- a/src/librustc_codegen_llvm/back/lto.rs +++ b/src/librustc_codegen_llvm/back/lto.rs @@ -48,18 +48,11 @@ pub fn crate_type_allows_lto(crate_type: config::CrateType) -> bool { } } -/// Performs LTO, which in the case of full LTO means merging all modules into -/// a single one and returning it for further optimizing. For ThinLTO, it will -/// do the global analysis necessary and return two lists, one of the modules -/// the need optimization and another for modules that can simply be copied over -/// from the incr. comp. cache. -pub(crate) fn run(cgcx: &CodegenContext, - modules: Vec>, - cached_modules: Vec<(SerializedModule, WorkProduct)>, - timeline: &mut Timeline) - -> Result<(Vec>, Vec), FatalError> +fn prepare_lto(cgcx: &CodegenContext, + timeline: &mut Timeline, + diag_handler: &Handler) + -> Result<(Vec, Vec<(SerializedModule, CString)>), FatalError> { - let diag_handler = cgcx.create_diag_handler(); let export_threshold = match cgcx.lto { // We're just doing LTO for our one crate Lto::ThinLocal => SymbolExportLevel::Rust, @@ -144,36 +137,74 @@ pub(crate) fn run(cgcx: &CodegenContext, } } + Ok((symbol_white_list, upstream_modules)) +} + +/// Performs fat LTO by merging all modules into a single one and returning it +/// for further optimization. +pub(crate) fn run_fat(cgcx: &CodegenContext, + modules: Vec>, + timeline: &mut Timeline) + -> Result, FatalError> +{ + let diag_handler = cgcx.create_diag_handler(); + let (symbol_white_list, upstream_modules) = prepare_lto(cgcx, timeline, &diag_handler)?; let symbol_white_list = symbol_white_list.iter() .map(|c| c.as_ptr()) .collect::>(); - match cgcx.lto { - Lto::Fat => { - assert!(cached_modules.is_empty()); - let opt_jobs = fat_lto(cgcx, - &diag_handler, - modules, - upstream_modules, - &symbol_white_list, - timeline); - opt_jobs.map(|opt_jobs| (opt_jobs, vec![])) - } - Lto::Thin | - Lto::ThinLocal => { - if cgcx.opts.debugging_opts.cross_lang_lto.enabled() { - unreachable!("We should never reach this case if the LTO step \ - is deferred to the linker"); - } - thin_lto(cgcx, - &diag_handler, - modules, - upstream_modules, - cached_modules, - &symbol_white_list, - timeline) - } - Lto::No => unreachable!(), + fat_lto(cgcx, &diag_handler, modules, upstream_modules, &symbol_white_list, timeline) +} + +/// Performs thin LTO by performing necessary global analysis and returning two +/// lists, one of the modules that need optimization and another for modules that +/// can simply be copied over from the incr. comp. cache. +pub(crate) fn run_thin(cgcx: &CodegenContext, + modules: Vec<(String, ThinBuffer)>, + cached_modules: Vec<(SerializedModule, WorkProduct)>, + timeline: &mut Timeline) + -> Result<(Vec>, Vec), FatalError> +{ + let diag_handler = cgcx.create_diag_handler(); + let (symbol_white_list, upstream_modules) = prepare_lto(cgcx, timeline, &diag_handler)?; + let symbol_white_list = symbol_white_list.iter() + .map(|c| c.as_ptr()) + .collect::>(); + if cgcx.opts.debugging_opts.cross_lang_lto.enabled() { + unreachable!("We should never reach this case if the LTO step \ + is deferred to the linker"); } + thin_lto(cgcx, + &diag_handler, + modules, + upstream_modules, + cached_modules, + &symbol_white_list, + timeline) +} + +pub(crate) fn prepare_thin( + cgcx: &CodegenContext, + module: ModuleCodegen +) -> (String, ThinBuffer) { + let name = module.name.clone(); + let buffer = ThinBuffer::new(module.module_llvm.llmod()); + + // We emit the module after having serialized it into a ThinBuffer + // because only then it will contain the ThinLTO module summary. + if let Some(ref incr_comp_session_dir) = cgcx.incr_comp_session_dir { + if cgcx.config(module.kind).emit_pre_thin_lto_bc { + let path = incr_comp_session_dir + .join(pre_lto_bitcode_filename(&name)); + + fs::write(&path, buffer.data()).unwrap_or_else(|e| { + panic!("Error writing pre-lto-bitcode file `{}`: {}", + path.display(), + e); + }); + } + } + + (name, buffer) } fn fat_lto(cgcx: &CodegenContext, @@ -182,7 +213,7 @@ fn fat_lto(cgcx: &CodegenContext, mut serialized_modules: Vec<(SerializedModule, CString)>, symbol_white_list: &[*const libc::c_char], timeline: &mut Timeline) - -> Result>, FatalError> + -> Result, FatalError> { info!("going for a fat lto"); @@ -271,10 +302,10 @@ fn fat_lto(cgcx: &CodegenContext, timeline.record("passes"); } - Ok(vec![LtoModuleCodegen::Fat { + Ok(LtoModuleCodegen::Fat { module: Some(module), _serialized_bitcode: serialized_bitcode, - }]) + }) } struct Linker<'a>(&'a mut llvm::Linker<'a>); @@ -335,7 +366,7 @@ impl Drop for Linker<'a> { /// they all go out of scope. fn thin_lto(cgcx: &CodegenContext, diag_handler: &Handler, - modules: Vec>, + modules: Vec<(String, ThinBuffer)>, serialized_modules: Vec<(SerializedModule, CString)>, cached_modules: Vec<(SerializedModule, WorkProduct)>, symbol_white_list: &[*const libc::c_char], @@ -355,41 +386,17 @@ fn thin_lto(cgcx: &CodegenContext, let mut module_names = Vec::with_capacity(full_scope_len); let mut thin_modules = Vec::with_capacity(full_scope_len); - // FIXME: right now, like with fat LTO, we serialize all in-memory - // modules before working with them and ThinLTO. We really - // shouldn't do this, however, and instead figure out how to - // extract a summary from an in-memory module and then merge that - // into the global index. It turns out that this loop is by far - // the most expensive portion of this small bit of global - // analysis! - for (i, module) in modules.into_iter().enumerate() { - info!("local module: {} - {}", i, module.name); - let name = CString::new(module.name.clone()).unwrap(); - let buffer = ThinBuffer::new(module.module_llvm.llmod()); - - // We emit the module after having serialized it into a ThinBuffer - // because only then it will contain the ThinLTO module summary. - if let Some(ref incr_comp_session_dir) = cgcx.incr_comp_session_dir { - if cgcx.config(module.kind).emit_pre_thin_lto_bc { - let path = incr_comp_session_dir - .join(pre_lto_bitcode_filename(&module.name)); - - fs::write(&path, buffer.data()).unwrap_or_else(|e| { - panic!("Error writing pre-lto-bitcode file `{}`: {}", - path.display(), - e); - }); - } - } - + for (i, (name, buffer)) in modules.into_iter().enumerate() { + info!("local module: {} - {}", i, name); + let cname = CString::new(name.clone()).unwrap(); thin_modules.push(llvm::ThinLTOModule { - identifier: name.as_ptr(), + identifier: cname.as_ptr(), data: buffer.data().as_ptr(), len: buffer.data().len(), }); thin_buffers.push(buffer); - module_names.push(name); - timeline.record(&module.name); + module_names.push(cname); + timeline.record(&name); } // FIXME: All upstream crates are deserialized internally in the diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 2ddbd0c299a..78a3b6907a6 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -782,7 +782,7 @@ fn create_msvc_imps( } // The x86 ABI seems to require that leading underscores are added to symbol // names, so we need an extra underscore on 32-bit. There's also a leading - // '\x01' here which disables LLVM's symbol mangling (e.g. no extra + // '\x01' here which disables LLVM's symbol mangling (e.g., no extra // underscores added in front). let prefix = if cgcx.target_pointer_width == "32" { "\x01__imp__" diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index a95ddefc869..01b1387d9cc 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -1024,17 +1024,11 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn minnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("minnum"); - unsafe { - let instr = llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs); - instr.expect("LLVMRustBuildMinNum is not available in LLVM version < 6.0") - } + unsafe { llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs) } } fn maxnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("maxnum"); - unsafe { - let instr = llvm::LLVMRustBuildMaxNum(self.llbuilder, lhs, rhs); - instr.expect("LLVMRustBuildMaxNum is not available in LLVM version < 6.0") - } + unsafe { llvm::LLVMRustBuildMaxNum(self.llbuilder, lhs, rhs) } } fn select( diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs index f13eeb6692c..87185a20c50 100644 --- a/src/librustc_codegen_llvm/callee.rs +++ b/src/librustc_codegen_llvm/callee.rs @@ -94,7 +94,7 @@ pub fn get_fn( if instance.def.is_inline(tcx) { attributes::inline(cx, llfn, attributes::InlineAttr::Hint); } - attributes::from_fn_attrs(cx, llfn, Some(instance.def.def_id())); + attributes::from_fn_attrs(cx, llfn, Some(instance.def.def_id()), sig); let instance_def_id = instance.def_id(); diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs index fd13421835c..ad14ca7caf6 100644 --- a/src/librustc_codegen_llvm/common.rs +++ b/src/librustc_codegen_llvm/common.rs @@ -21,7 +21,7 @@ use value::Value; use rustc_codegen_ssa::traits::*; use rustc::ty::layout::{HasDataLayout, LayoutOf, self, TyLayout, Size}; -use rustc::mir::interpret::{Scalar, AllocType, Allocation}; +use rustc::mir::interpret::{Scalar, AllocKind, Allocation}; use consts::const_alloc_to_llvm; use rustc_codegen_ssa::mir::place::PlaceRef; @@ -63,7 +63,7 @@ pub use context::CodegenCx; /// /// Each `Block` may contain an instance of this, indicating whether the block /// is part of a landing pad or not. This is used to make decision about whether -/// to emit `invoke` instructions (e.g. in a landing pad we don't continue to +/// to emit `invoke` instructions (e.g., in a landing pad we don't continue to /// use `invoke`) and also about various function call metadata. /// /// For GNU exceptions (`landingpad` + `resume` instructions) this structure is @@ -316,9 +316,9 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { } }, Scalar::Ptr(ptr) => { - let alloc_type = self.tcx.alloc_map.lock().get(ptr.alloc_id); - let base_addr = match alloc_type { - Some(AllocType::Memory(alloc)) => { + let alloc_kind = self.tcx.alloc_map.lock().get(ptr.alloc_id); + let base_addr = match alloc_kind { + Some(AllocKind::Memory(alloc)) => { let init = const_alloc_to_llvm(self, alloc); if alloc.mutability == Mutability::Mutable { self.static_addr_of_mut(init, alloc.align, None) @@ -326,10 +326,10 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { self.static_addr_of(init, alloc.align, None) } } - Some(AllocType::Function(fn_instance)) => { + Some(AllocKind::Function(fn_instance)) => { self.get_fn(fn_instance) } - Some(AllocType::Static(def_id)) => { + Some(AllocKind::Static(def_id)) => { assert!(self.tcx.is_static(def_id).is_some()); self.get_static(def_id) } diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index 5311a6a3730..086fb1f5a93 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -223,10 +223,10 @@ impl CodegenCx<'ll, 'tcx> { debug!("get_static: sym={} instance={:?}", sym, instance); - let g = if let Some(id) = self.tcx.hir.as_local_node_id(def_id) { + let g = if let Some(id) = self.tcx.hir().as_local_node_id(def_id) { let llty = self.layout_of(ty).llvm_type(self); - let (g, attrs) = match self.tcx.hir.get(id) { + let (g, attrs) = match self.tcx.hir().get(id) { Node::Item(&hir::Item { ref attrs, span, node: hir::ItemKind::Static(..), .. }) => { @@ -295,7 +295,7 @@ impl CodegenCx<'ll, 'tcx> { self.tcx.sess.opts.cg.prefer_dynamic)); if needs_dll_storage_attr { - // This item is external but not foreign, i.e. it originates from an external Rust + // This item is external but not foreign, i.e., it originates from an external Rust // crate. Since we don't know whether this crate will be linked dynamically or // statically in the final application, we always mark such symbols as 'dllimport'. // If final linkage happens to be static, we rely on compiler-emitted __imp_ stubs @@ -426,7 +426,7 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> { // // By default a global's alignment can be freely increased. // This allows LLVM to generate more performant instructions - // e.g. using load-aligned into a SIMD register. + // e.g., using load-aligned into a SIMD register. // // However, on macOS 10.10 or below, the dynamic linker does not // respect any alignment given on the TLS (radar 24221680). diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 564e424cf6c..b75cd8f68b3 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -10,7 +10,6 @@ use attributes; use llvm; -use llvm_util; use rustc::dep_graph::DepGraphSafe; use rustc::hir; use debuginfo; @@ -233,7 +232,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { // they're not available to be linked against. This poses a few problems // for the compiler, some of which are somewhat fundamental, but we use // the `use_dll_storage_attrs` variable below to attach the `dllexport` - // attribute to all LLVM functions that are exported e.g. they're + // attribute to all LLVM functions that are exported e.g., they're // already tagged with external linkage). This is suboptimal for a few // reasons: // @@ -409,7 +408,6 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { )); let llfn = self.declare_fn("rust_eh_unwind_resume", sig); - attributes::unwind(llfn, true); attributes::apply_target_cpu_attr(self, llfn); unwresume.set(Some(llfn)); llfn @@ -447,10 +445,6 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { attributes::apply_target_cpu_attr(self, llfn) } - fn closure_env_needs_indirect_debuginfo(&self) -> bool { - llvm_util::get_major_version() < 6 - } - fn create_used_variable(&self) { let name = const_cstr!("llvm.used"); let section = const_cstr!("llvm.metadata"); diff --git a/src/librustc_codegen_llvm/debuginfo/doc.rs b/src/librustc_codegen_llvm/debuginfo/doc.rs index ce0476b07eb..5e2476e0918 100644 --- a/src/librustc_codegen_llvm/debuginfo/doc.rs +++ b/src/librustc_codegen_llvm/debuginfo/doc.rs @@ -166,7 +166,7 @@ //! //! (3) Tuple-, pointer and function types are structurally identified, which //! means that they are equivalent if their component types are equivalent -//! (i.e. (i32, i32) is the same regardless in which crate it is used). +//! (i.e., (i32, i32) is the same regardless in which crate it is used). //! //! This algorithm also provides a stable ID for types that are defined in one //! crate but instantiated from metadata within another crate. We just have to diff --git a/src/librustc_codegen_llvm/debuginfo/gdb.rs b/src/librustc_codegen_llvm/debuginfo/gdb.rs index 4be93d826b8..ff5ec20254e 100644 --- a/src/librustc_codegen_llvm/debuginfo/gdb.rs +++ b/src/librustc_codegen_llvm/debuginfo/gdb.rs @@ -76,7 +76,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx<'ll, '_>) pub fn needs_gdb_debug_scripts_section(cx: &CodegenCx) -> bool { let omit_gdb_pretty_printer_section = - attr::contains_name(&cx.tcx.hir.krate_attrs(), + attr::contains_name(&cx.tcx.hir().krate_attrs(), "omit_gdb_pretty_printer_section"); !omit_gdb_pretty_printer_section && diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 5a1c62e2536..d263b4e1237 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -509,7 +509,7 @@ pub fn type_metadata( }, None => { // The Ty is not in the TypeMap but maybe we have already seen - // an equivalent type (e.g. only differing in region arguments). + // an equivalent type (e.g., only differing in region arguments). // In order to find out, generate the unique type id and look // that up. let unique_type_id = type_map.get_unique_type_id_of_type(cx, t); diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs index 78bdf678f67..5b65b1fdda6 100644 --- a/src/librustc_codegen_llvm/debuginfo/mod.rs +++ b/src/librustc_codegen_llvm/debuginfo/mod.rs @@ -300,7 +300,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { let mut flags = DIFlags::FlagPrototyped; - let local_id = self.tcx().hir.as_local_node_id(def_id); + let local_id = self.tcx().hir().as_local_node_id(def_id); if let Some((id, _, _)) = *self.sess().entry_fn.borrow() { if local_id == Some(id) { flags |= DIFlags::FlagMainSubprogram; @@ -488,7 +488,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { ); // Only "class" methods are generally understood by LLVM, - // so avoid methods on other types (e.g. `<*mut T>::null`). + // so avoid methods on other types (e.g., `<*mut T>::null`). match impl_self_ty.sty { ty::Adt(def, ..) if !def.is_box() => { Some(type_metadata(cx, impl_self_ty, syntax_pos::DUMMY_SP)) diff --git a/src/librustc_codegen_llvm/debuginfo/type_names.rs b/src/librustc_codegen_llvm/debuginfo/type_names.rs index 60545f9e193..2e827cc6d06 100644 --- a/src/librustc_codegen_llvm/debuginfo/type_names.rs +++ b/src/librustc_codegen_llvm/debuginfo/type_names.rs @@ -19,9 +19,9 @@ use rustc_codegen_ssa::traits::*; use rustc::hir; // Compute the name of the type as it should be stored in debuginfo. Does not do -// any caching, i.e. calling the function twice with the same type will also do +// any caching, i.e., calling the function twice with the same type will also do // the work twice. The `qualified` parameter only affects the first level of the -// type name, further levels (i.e. type parameters) are always fully qualified. +// type name, further levels (i.e., type parameters) are always fully qualified. pub fn compute_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, t: Ty<'tcx>, qualified: bool) diff --git a/src/librustc_codegen_llvm/debuginfo/utils.rs b/src/librustc_codegen_llvm/debuginfo/utils.rs index 89262beb356..4b6ef30b138 100644 --- a/src/librustc_codegen_llvm/debuginfo/utils.rs +++ b/src/librustc_codegen_llvm/debuginfo/utils.rs @@ -26,7 +26,7 @@ use syntax_pos::{self, Span}; pub fn is_node_local_to_unit(cx: &CodegenCx, def_id: DefId) -> bool { // The is_local_to_unit flag indicates whether a function is local to the - // current compilation unit (i.e. if it is *static* in the C-sense). The + // current compilation unit (i.e., if it is *static* in the C-sense). The // *reachable* set should provide a good approximation of this, as it // contains everything that might leak out of the current crate (by being // externally visible or by being inlined into something externally diff --git a/src/librustc_codegen_llvm/declare.rs b/src/librustc_codegen_llvm/declare.rs index c23aab409a9..2964f2e5847 100644 --- a/src/librustc_codegen_llvm/declare.rs +++ b/src/librustc_codegen_llvm/declare.rs @@ -26,8 +26,7 @@ use rustc::ty::{self, PolyFnSig}; use rustc::ty::layout::LayoutOf; use rustc::session::config::Sanitizer; use rustc_data_structures::small_c_str::SmallCStr; -use rustc_target::spec::PanicStrategy; -use abi::{Abi, FnType, FnTypeExt}; +use abi::{FnType, FnTypeExt}; use attributes; use context::CodegenCx; use type_::Type; @@ -86,10 +85,6 @@ fn declare_raw_fn( _ => {}, } - if cx.tcx.sess.panic_strategy() != PanicStrategy::Unwind { - attributes::unwind(llfn, false); - } - attributes::non_lazy_bind(cx.sess(), llfn); llfn @@ -132,10 +127,6 @@ impl DeclareMethods<'tcx> for CodegenCx<'ll, 'tcx> { llvm::Attribute::NoReturn.apply_llfn(Function, llfn); } - if sig.abi != Abi::Rust && sig.abi != Abi::RustCall { - attributes::unwind(llfn, false); - } - fty.apply_attrs_llfn(llfn); llfn diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 313aa175106..e229f8d95cd 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -732,7 +732,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { // We found a tuple that needs squishing! So // run over the tuple and load each field. // - // This assumes the type is "simple", i.e. no + // This assumes the type is "simple", i.e., no // destructors, and the contents are SIMD // etc. assert!(!bx.type_needs_drop(arg.layout.ty)); @@ -997,7 +997,7 @@ fn codegen_msvc_try( } // Definition of the standard "try" function for Rust using the GNU-like model -// of exceptions (e.g. the normal semantics of LLVM's landingpad and invoke +// of exceptions (e.g., the normal semantics of LLVM's landingpad and invoke // instructions). // // This codegen is a little surprising because we always call a shim @@ -1081,7 +1081,7 @@ fn gen_fn<'ll, 'tcx>( Abi::Rust )); let llfn = cx.define_internal_fn(name, rust_fn_sig); - attributes::from_fn_attrs(cx, llfn, None); + attributes::from_fn_attrs(cx, llfn, None, rust_fn_sig); let bx = Builder::new_block(cx, llfn, "entry-block"); codegen(bx); llfn @@ -1171,7 +1171,28 @@ fn generic_simd_intrinsic( ); let arg_tys = sig.inputs(); - // every intrinsic takes a SIMD vector as its first argument + if name == "simd_select_bitmask" { + let in_ty = arg_tys[0]; + let m_len = match in_ty.sty { + // Note that this `.unwrap()` crashes for isize/usize, that's sort + // of intentional as there's not currently a use case for that. + ty::Int(i) => i.bit_width().unwrap(), + ty::Uint(i) => i.bit_width().unwrap(), + _ => return_error!("`{}` is not an integral type", in_ty), + }; + require_simd!(arg_tys[1], "argument"); + let v_len = arg_tys[1].simd_size(tcx); + require!(m_len == v_len, + "mismatched lengths: mask length `{}` != other vector length `{}`", + m_len, v_len + ); + let i1 = bx.type_i1(); + let i1xn = bx.type_vector(i1, m_len as u64); + let m_i1s = bx.bitcast(args[0].immediate(), i1xn); + return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate())); + } + + // every intrinsic below takes a SIMD vector as its first argument require_simd!(arg_tys[0], "input"); let in_ty = arg_tys[0]; let in_elem = arg_tys[0].simd_type(tcx); @@ -1275,6 +1296,7 @@ fn generic_simd_intrinsic( if name == "simd_select" { let m_elem_ty = in_elem; let m_len = in_len; + require_simd!(arg_tys[1], "argument"); let v_len = arg_tys[1].simd_size(tcx); require!(m_len == v_len, "mismatched lengths: mask length `{}` != other vector length `{}`", diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 4f90cb793b6..ff06d3759bd 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -176,13 +176,20 @@ impl WriteBackendMethods for LlvmCodegenBackend { fn print_pass_timings(&self) { unsafe { llvm::LLVMRustPrintPassTimings(); } } - fn run_lto( + fn run_fat_lto( cgcx: &CodegenContext, modules: Vec>, + timeline: &mut Timeline + ) -> Result, FatalError> { + back::lto::run_fat(cgcx, modules, timeline) + } + fn run_thin_lto( + cgcx: &CodegenContext, + modules: Vec<(String, Self::ThinBuffer)>, cached_modules: Vec<(SerializedModule, WorkProduct)>, timeline: &mut Timeline ) -> Result<(Vec>, Vec), FatalError> { - back::lto::run(cgcx, modules, cached_modules, timeline) + back::lto::run_thin(cgcx, modules, cached_modules, timeline) } unsafe fn optimize( cgcx: &CodegenContext, @@ -209,6 +216,12 @@ impl WriteBackendMethods for LlvmCodegenBackend { ) -> Result { back::write::codegen(cgcx, diag_handler, module, config, timeline) } + fn prepare_thin( + cgcx: &CodegenContext, + module: ModuleCodegen + ) -> (String, Self::ThinBuffer) { + back::lto::prepare_thin(cgcx, module) + } fn run_lto_pass_manager( cgcx: &CodegenContext, module: &ModuleCodegen, diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index 127759a4326..4732db88ec1 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -1222,12 +1222,12 @@ extern "C" { B: &Builder<'a>, LHS: &'a Value, LHS: &'a Value, - ) -> Option<&'a Value>; + ) -> &'a Value; pub fn LLVMRustBuildMaxNum( B: &Builder<'a>, LHS: &'a Value, LHS: &'a Value, - ) -> Option<&'a Value>; + ) -> &'a Value; // Atomic Operations pub fn LLVMRustBuildAtomicLoad(B: &Builder<'a>, diff --git a/src/librustc_codegen_llvm/llvm/mod.rs b/src/librustc_codegen_llvm/llvm/mod.rs index fbd5192a63f..3764c122dea 100644 --- a/src/librustc_codegen_llvm/llvm/mod.rs +++ b/src/librustc_codegen_llvm/llvm/mod.rs @@ -125,7 +125,7 @@ pub fn SetFunctionCallConv(fn_: &'a Value, cc: CallConv) { // example happen for generics when using multiple codegen units. This function simply uses the // value's name as the comdat value to make sure that it is in a 1-to-1 relationship to the // function. -// For more details on COMDAT sections see e.g. http://www.airs.com/blog/archives/52 +// For more details on COMDAT sections see e.g., http://www.airs.com/blog/archives/52 pub fn SetUniqueComdat(llmod: &Module, val: &'a Value) { unsafe { LLVMRustSetComdat(llmod, val, LLVMGetValueName(val)); diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs index fdb6373bea1..82b1d7e8b40 100644 --- a/src/librustc_codegen_llvm/llvm_util.rs +++ b/src/librustc_codegen_llvm/llvm_util.rs @@ -124,6 +124,7 @@ const AARCH64_WHITELIST: &[(&str, Option<&str>)] = &[ ]; const X86_WHITELIST: &[(&str, Option<&str>)] = &[ + ("adx", Some("adx_target_feature")), ("aes", None), ("avx", None), ("avx2", None), @@ -139,6 +140,7 @@ const X86_WHITELIST: &[(&str, Option<&str>)] = &[ ("avx512vpopcntdq", Some("avx512_target_feature")), ("bmi1", None), ("bmi2", None), + ("cmpxchg16b", Some("cmpxchg16b_target_feature")), ("fma", None), ("fxsr", None), ("lzcnt", None), @@ -211,6 +213,7 @@ pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str { ("x86", "pclmulqdq") => "pclmul", ("x86", "rdrand") => "rdrnd", ("x86", "bmi1") => "bmi", + ("x86", "cmpxchg16b") => "cx16", ("aarch64", "fp") => "fp-armv8", ("aarch64", "fp16") => "fullfp16", (_, s) => s, diff --git a/src/librustc_codegen_llvm/mono_item.rs b/src/librustc_codegen_llvm/mono_item.rs index 9b2d17d65ca..9c69d7d8cf4 100644 --- a/src/librustc_codegen_llvm/mono_item.rs +++ b/src/librustc_codegen_llvm/mono_item.rs @@ -63,7 +63,7 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> { llvm::SetUniqueComdat(self.llmod, lldecl); } - // If we're compiling the compiler-builtins crate, e.g. the equivalent of + // If we're compiling the compiler-builtins crate, e.g., the equivalent of // compiler-rt, then we want to implicitly compile everything with hidden // visibility as we're going to link this object all over the place but // don't want the symbols to get exported. @@ -82,7 +82,12 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> { if instance.def.is_inline(self.tcx) { attributes::inline(self, lldecl, attributes::InlineAttr::Hint); } - attributes::from_fn_attrs(self, lldecl, Some(instance.def.def_id())); + attributes::from_fn_attrs( + self, + lldecl, + Some(instance.def.def_id()), + mono_sig, + ); self.instances.borrow_mut().insert(instance, lldecl); } diff --git a/src/librustc_codegen_llvm/type_.rs b/src/librustc_codegen_llvm/type_.rs index b100b677803..313ab1f974f 100644 --- a/src/librustc_codegen_llvm/type_.rs +++ b/src/librustc_codegen_llvm/type_.rs @@ -255,7 +255,7 @@ impl Type { } } - // Creates an integer type with the given number of bits, e.g. i24 + // Creates an integer type with the given number of bits, e.g., i24 pub fn ix_llcx( llcx: &llvm::Context, num_bits: u64 diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs index 15b5bdeb44d..52b560c6625 100644 --- a/src/librustc_codegen_llvm/type_of.rs +++ b/src/librustc_codegen_llvm/type_of.rs @@ -15,8 +15,8 @@ use rustc::ty::{self, Ty, TypeFoldable}; use rustc::ty::layout::{self, Align, LayoutOf, Size, TyLayout}; use rustc_target::abi::FloatTy; use rustc_mir::monomorphize::item::DefPathBasedNames; -use type_::Type; use rustc_codegen_ssa::traits::*; +use type_::Type; use std::fmt::Write; @@ -84,10 +84,10 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, let packed = false; match name { None => { - cx.type_struct( &[fill], packed) + cx.type_struct(&[fill], packed) } Some(ref name) => { - let llty = cx.type_named_struct( name); + let llty = cx.type_named_struct(name); cx.set_struct_body(llty, &[fill], packed); llty } @@ -236,7 +236,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { } } - /// Get the LLVM type corresponding to a Rust type, i.e. `rustc::ty::Ty`. + /// Get the LLVM type corresponding to a Rust type, i.e., `rustc::ty::Ty`. /// The pointee type of the pointer in `PlaceRef` is always this type. /// For sized types, it is also the right LLVM type for an `alloca` /// containing a value of that type, and most immediates (except `bool`). @@ -470,9 +470,9 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { // (according to its type), or null (which the // niche field's scalar validity range encodes). // This allows using `dereferenceable_or_null` - // for e.g. `Option<&T>`, and this will continue + // for e.g., `Option<&T>`, and this will continue // to work as long as we don't start using more - // niches than just null (e.g. the first page + // niches than just null (e.g., the first page // of the address space, or unaligned pointers). if self.fields.offset(0) == offset { Some(self.for_variant(cx, dataful_variant)) diff --git a/src/librustc_codegen_llvm/va_arg.rs b/src/librustc_codegen_llvm/va_arg.rs index fbc3e6f06d1..1e5bb03ddb1 100644 --- a/src/librustc_codegen_llvm/va_arg.rs +++ b/src/librustc_codegen_llvm/va_arg.rs @@ -105,13 +105,30 @@ pub(super) fn emit_va_arg( ) -> &'ll Value { // Determine the va_arg implementation to use. The LLVM va_arg instruction // is lacking in some instances, so we should only use it as a fallback. + let target = &bx.cx.tcx.sess.target.target; let arch = &bx.cx.tcx.sess.target.target.arch; - match (&**arch, - bx.cx.tcx.sess.target.target.options.is_like_windows) { + match (&**arch, target.options.is_like_windows) { + // Windows x86 ("x86", true) => { emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(4).unwrap(), false) } + // Generic x86 + ("x86", _) => { + emit_ptr_va_arg(bx, addr, target_ty, false, + Align::from_bytes(4).unwrap(), true) + } + // Windows Aarch64 + ("aarch4", true) => { + emit_ptr_va_arg(bx, addr, target_ty, false, + Align::from_bytes(8).unwrap(), false) + } + // iOS Aarch64 + ("aarch4", _) if target.target_os == "ios" => { + emit_ptr_va_arg(bx, addr, target_ty, false, + Align::from_bytes(8).unwrap(), true) + } + // Windows x86_64 ("x86_64", true) => { let target_ty_size = bx.cx.size_of(target_ty).bytes(); let indirect = if target_ty_size > 8 || !target_ty_size.is_power_of_two() { @@ -122,15 +139,14 @@ pub(super) fn emit_va_arg( emit_ptr_va_arg(bx, addr, target_ty, indirect, Align::from_bytes(8).unwrap(), false) } - ("x86", false) => { - emit_ptr_va_arg(bx, addr, target_ty, false, - Align::from_bytes(4).unwrap(), true) - } + // For all other architecture/OS combinations fall back to using + // the LLVM va_arg instruction. + // https://llvm.org/docs/LangRef.html#va-arg-instruction _ => { - let va_list = if (bx.tcx().sess.target.target.arch == "aarch64" || - bx.tcx().sess.target.target.arch == "x86_64" || - bx.tcx().sess.target.target.arch == "powerpc") && - !bx.tcx().sess.target.target.options.is_like_windows { + let va_list = if (target.arch == "aarch64" || + target.arch == "x86_64" || + target.arch == "powerpc") && + !target.options.is_like_windows { bx.load(addr.immediate(), bx.tcx().data_layout.pointer_align.abi) } else { addr.immediate() diff --git a/src/librustc_codegen_ssa/Cargo.toml b/src/librustc_codegen_ssa/Cargo.toml index 7b1c7cfb56f..50994497c28 100644 --- a/src/librustc_codegen_ssa/Cargo.toml +++ b/src/librustc_codegen_ssa/Cargo.toml @@ -16,7 +16,7 @@ num_cpus = "1.0" rustc-demangle = "0.1.4" memmap = "0.6" log = "0.4.5" -libc = "0.2.43" +libc = "0.2.44" jobserver = "0.1.11" serialize = { path = "../libserialize" } diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 24a70dc7977..59102e09d4c 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -192,11 +192,7 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) { // linker and linker flavor specified via command line have precedence over what the target // specification specifies - if let Some(ret) = infer_from( - sess, - sess.opts.cg.linker.clone(), - sess.opts.debugging_opts.linker_flavor, - ) { + if let Some(ret) = infer_from(sess, sess.opts.cg.linker.clone(), sess.opts.cg.linker_flavor) { return ret; } diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs index f3cc344254f..4960c8922b9 100644 --- a/src/librustc_codegen_ssa/back/linker.rs +++ b/src/librustc_codegen_ssa/back/linker.rs @@ -107,7 +107,7 @@ impl LinkerInfo { /// This trait is the total list of requirements needed by `back::link` and /// represents the meaning of each option being passed down. This trait is then /// used to dispatch on whether a GNU-like linker (generally `ld.exe`) or an -/// MSVC linker (e.g. `link.exe`) is being used. +/// MSVC linker (e.g., `link.exe`) is being used. pub trait Linker { fn link_dylib(&mut self, lib: &str); fn link_rust_dylib(&mut self, lib: &str, path: &Path); @@ -606,8 +606,7 @@ impl<'a> Linker for MsvcLinker<'a> { self.cmd.arg("/DEBUG"); // This will cause the Microsoft linker to embed .natvis info into the PDB file - let sysroot = self.sess.sysroot(); - let natvis_dir_path = sysroot.join("lib\\rustlib\\etc"); + let natvis_dir_path = self.sess.sysroot.join("lib\\rustlib\\etc"); if let Ok(natvis_dir) = fs::read_dir(&natvis_dir_path) { // LLVM 5.0.0's lld-link frontend doesn't yet recognize, and chokes // on, the /NATVIS:... flags. LLVM 6 (or earlier) should at worst ignore diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs index d25917e51bf..a17a00ddb29 100644 --- a/src/librustc_codegen_ssa/back/symbol_export.rs +++ b/src/librustc_codegen_ssa/back/symbol_export.rs @@ -85,7 +85,7 @@ fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // categories: // // 1. Those that are included statically via a static library - // 2. Those included otherwise (e.g. dynamically or via a framework) + // 2. Those included otherwise (e.g., dynamically or via a framework) // // Although our LLVM module is not literally emitting code for the // statically included symbols, it's an export of our library which @@ -93,9 +93,9 @@ fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // // As a result, if this id is an FFI item (foreign item) then we only // let it through if it's included statically. - match tcx.hir.get(node_id) { + match tcx.hir().get(node_id) { Node::ForeignItem(..) => { - let def_id = tcx.hir.local_def_id(node_id); + let def_id = tcx.hir().local_def_id(node_id); if tcx.is_statically_included_foreign_item(def_id) { Some(def_id) } else { @@ -115,7 +115,7 @@ fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node: hir::ImplItemKind::Method(..), .. }) => { - let def_id = tcx.hir.local_def_id(node_id); + let def_id = tcx.hir().local_def_id(node_id); let generics = tcx.generics_of(def_id); if !generics.requires_monomorphization(tcx) && // Functions marked with #[inline] are only ever codegened @@ -158,12 +158,12 @@ fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, .collect(); if let Some(id) = *tcx.sess.proc_macro_decls_static.get() { - let def_id = tcx.hir.local_def_id(id); + let def_id = tcx.hir().local_def_id(id); reachable_non_generics.insert(def_id, SymbolExportLevel::C); } if let Some(id) = *tcx.sess.plugin_registrar_fn.get() { - let def_id = tcx.hir.local_def_id(id); + let def_id = tcx.hir().local_def_id(id); reachable_non_generics.insert(def_id, SymbolExportLevel::C); } @@ -225,7 +225,7 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // These are weak symbols that point to the profile version and the // profile name, which need to be treated as exported so LTO doesn't nix // them. - const PROFILER_WEAK_SYMBOLS: [&'static str; 2] = [ + const PROFILER_WEAK_SYMBOLS: [&str; 2] = [ "__llvm_profile_raw_version", "__llvm_profile_filename", ]; @@ -355,7 +355,7 @@ fn upstream_monomorphizations_for_provider<'a, 'tcx>( } fn is_unreachable_local_definition_provider(tcx: TyCtxt, def_id: DefId) -> bool { - if let Some(node_id) = tcx.hir.as_local_node_id(def_id) { + if let Some(node_id) = tcx.hir().as_local_node_id(def_id) { !tcx.reachable_set(LOCAL_CRATE).0.contains(&node_id) } else { bug!("is_unreachable_local_definition called with non-local DefId: {:?}", @@ -393,7 +393,7 @@ fn symbol_export_level(tcx: TyCtxt, sym_def_id: DefId) -> SymbolExportLevel { if let Some(Node::Item(&hir::Item { node: hir::ItemKind::Static(..), .. - })) = tcx.hir.get_if_local(sym_def_id) { + })) = tcx.hir().get_if_local(sym_def_id) { return SymbolExportLevel::Rust; } } diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 46aee5339ba..ec790e6c665 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -252,7 +252,8 @@ impl CodegenContext { fn generate_lto_work( cgcx: &CodegenContext, - modules: Vec>, + needs_fat_lto: Vec>, + needs_thin_lto: Vec<(String, B::ThinBuffer)>, import_only_modules: Vec<(SerializedModule, WorkProduct)> ) -> Vec<(WorkItem, u64)> { let mut timeline = cgcx.time_graph.as_ref().map(|tg| { @@ -260,22 +261,28 @@ fn generate_lto_work( CODEGEN_WORK_PACKAGE_KIND, "generate lto") }).unwrap_or(Timeline::noop()); - let (lto_modules, copy_jobs) = B::run_lto(cgcx, modules, import_only_modules, &mut timeline) - .unwrap_or_else(|e| e.raise()); - let lto_modules = lto_modules.into_iter().map(|module| { + let (lto_modules, copy_jobs) = if !needs_fat_lto.is_empty() { + assert!(needs_thin_lto.is_empty()); + assert!(import_only_modules.is_empty()); + let lto_module = B::run_fat_lto(cgcx, needs_fat_lto, &mut timeline) + .unwrap_or_else(|e| e.raise()); + (vec![lto_module], vec![]) + } else { + assert!(needs_fat_lto.is_empty()); + B::run_thin_lto(cgcx, needs_thin_lto, import_only_modules, &mut timeline) + .unwrap_or_else(|e| e.raise()) + }; + + lto_modules.into_iter().map(|module| { let cost = module.cost(); (WorkItem::LTO(module), cost) - }); - - let copy_jobs = copy_jobs.into_iter().map(|wp| { + }).chain(copy_jobs.into_iter().map(|wp| { (WorkItem::CopyPostLtoArtifacts(CachedModuleCodegen { name: wp.cgu_name.clone(), source: wp, }), 0) - }); - - lto_modules.chain(copy_jobs).collect() + })).collect() } pub struct CompiledModules { @@ -313,8 +320,8 @@ pub fn start_async_codegen( let sess = tcx.sess; let crate_name = tcx.crate_name(LOCAL_CRATE); let crate_hash = tcx.crate_hash(LOCAL_CRATE); - let no_builtins = attr::contains_name(&tcx.hir.krate().attrs, "no_builtins"); - let subsystem = attr::first_attr_value_str_by_name(&tcx.hir.krate().attrs, + let no_builtins = attr::contains_name(&tcx.hir().krate().attrs, "no_builtins"); + let subsystem = attr::first_attr_value_str_by_name(&tcx.hir().krate().attrs, "windows_subsystem"); let windows_subsystem = subsystem.map(|subsystem| { if subsystem != "windows" && subsystem != "console" { @@ -671,16 +678,17 @@ impl WorkItem { } } -enum WorkItemResult { +enum WorkItemResult { Compiled(CompiledModule), - NeedsLTO(ModuleCodegen), + NeedsFatLTO(ModuleCodegen), + NeedsThinLTO(String, B::ThinBuffer), } fn execute_work_item( cgcx: &CodegenContext, work_item: WorkItem, timeline: &mut Timeline -) -> Result, FatalError> { +) -> Result, FatalError> { let module_config = cgcx.config(work_item.module_kind()); match work_item { @@ -696,67 +704,80 @@ fn execute_work_item( } } +// Actual LTO type we end up chosing based on multiple factors. +enum ComputedLtoType { + No, + Thin, + Fat, +} + fn execute_optimize_work_item( cgcx: &CodegenContext, module: ModuleCodegen, module_config: &ModuleConfig, timeline: &mut Timeline -) -> Result, FatalError> { +) -> Result, FatalError> { let diag_handler = cgcx.create_diag_handler(); unsafe { B::optimize(cgcx, &diag_handler, &module, module_config, timeline)?; } - let linker_does_lto = cgcx.opts.debugging_opts.cross_lang_lto.enabled(); - // After we've done the initial round of optimizations we need to // decide whether to synchronously codegen this module or ship it // back to the coordinator thread for further LTO processing (which // has to wait for all the initial modules to be optimized). + + // If the linker does LTO, we don't have to do it. Note that we + // keep doing full LTO, if it is requested, as not to break the + // assumption that the output will be a single module. + let linker_does_lto = cgcx.opts.debugging_opts.cross_lang_lto.enabled(); + + // When we're automatically doing ThinLTO for multi-codegen-unit + // builds we don't actually want to LTO the allocator modules if + // it shows up. This is due to various linker shenanigans that + // we'll encounter later. + let is_allocator = module.kind == ModuleKind::Allocator; + + // We ignore a request for full crate grath LTO if the cate type + // is only an rlib, as there is no full crate graph to process, + // that'll happen later. // - // Here we dispatch based on the `cgcx.lto` and kind of module we're - // codegenning... - let needs_lto = match cgcx.lto { - Lto::No => false, - - // If the linker does LTO, we don't have to do it. Note that we - // keep doing full LTO, if it is requested, as not to break the - // assumption that the output will be a single module. - Lto::Thin | Lto::ThinLocal if linker_does_lto => false, - - // Here we've got a full crate graph LTO requested. We ignore - // this, however, if the crate type is only an rlib as there's - // no full crate graph to process, that'll happen later. - // - // This use case currently comes up primarily for targets that - // require LTO so the request for LTO is always unconditionally - // passed down to the backend, but we don't actually want to do - // anything about it yet until we've got a final product. - Lto::Fat | Lto::Thin => { - cgcx.crate_types.len() != 1 || - cgcx.crate_types[0] != config::CrateType::Rlib - } - - // When we're automatically doing ThinLTO for multi-codegen-unit - // builds we don't actually want to LTO the allocator modules if - // it shows up. This is due to various linker shenanigans that - // we'll encounter later. - Lto::ThinLocal => { - module.kind != ModuleKind::Allocator - } - }; + // This use case currently comes up primarily for targets that + // require LTO so the request for LTO is always unconditionally + // passed down to the backend, but we don't actually want to do + // anything about it yet until we've got a final product. + let is_rlib = cgcx.crate_types.len() == 1 + && cgcx.crate_types[0] == config::CrateType::Rlib; // Metadata modules never participate in LTO regardless of the lto // settings. - let needs_lto = needs_lto && module.kind != ModuleKind::Metadata; - - if needs_lto { - Ok(WorkItemResult::NeedsLTO(module)) + let lto_type = if module.kind == ModuleKind::Metadata { + ComputedLtoType::No } else { - let module = unsafe { B::codegen(cgcx, &diag_handler, module, module_config, timeline)? }; - Ok(WorkItemResult::Compiled(module)) - } + match cgcx.lto { + Lto::ThinLocal if !linker_does_lto && !is_allocator + => ComputedLtoType::Thin, + Lto::Thin if !linker_does_lto && !is_rlib + => ComputedLtoType::Thin, + Lto::Fat if !is_rlib => ComputedLtoType::Fat, + _ => ComputedLtoType::No, + } + }; + + Ok(match lto_type { + ComputedLtoType::No => { + let module = unsafe { + B::codegen(cgcx, &diag_handler, module, module_config, timeline)? + }; + WorkItemResult::Compiled(module) + } + ComputedLtoType::Thin => { + let (name, thin_buffer) = B::prepare_thin(cgcx, module); + WorkItemResult::NeedsThinLTO(name, thin_buffer) + } + ComputedLtoType::Fat => WorkItemResult::NeedsFatLTO(module), + }) } fn execute_copy_from_cache_work_item( @@ -764,7 +785,7 @@ fn execute_copy_from_cache_work_item( module: CachedModuleCodegen, module_config: &ModuleConfig, _: &mut Timeline -) -> Result, FatalError> { +) -> Result, FatalError> { let incr_comp_session_dir = cgcx.incr_comp_session_dir .as_ref() .unwrap(); @@ -826,7 +847,7 @@ fn execute_lto_work_item( mut module: lto::LtoModuleCodegen, module_config: &ModuleConfig, timeline: &mut Timeline -) -> Result, FatalError> { +) -> Result, FatalError> { let diag_handler = cgcx.create_diag_handler(); unsafe { @@ -838,10 +859,15 @@ fn execute_lto_work_item( pub enum Message { Token(io::Result), - NeedsLTO { + NeedsFatLTO { result: ModuleCodegen, worker_id: usize, }, + NeedsThinLTO { + name: String, + thin_buffer: B::ThinBuffer, + worker_id: usize, + }, Done { result: Result, worker_id: usize, @@ -1137,7 +1163,8 @@ fn start_executing_work( let mut compiled_modules = vec![]; let mut compiled_metadata_module = None; let mut compiled_allocator_module = None; - let mut needs_lto = Vec::new(); + let mut needs_fat_lto = Vec::new(); + let mut needs_thin_lto = Vec::new(); let mut lto_import_only_modules = Vec::new(); let mut started_lto = false; let mut codegen_aborted = false; @@ -1166,7 +1193,8 @@ fn start_executing_work( running > 0 || (!codegen_aborted && ( work_items.len() > 0 || - needs_lto.len() > 0 || + needs_fat_lto.len() > 0 || + needs_thin_lto.len() > 0 || lto_import_only_modules.len() > 0 || main_thread_worker_state != MainThreadWorkerState::Idle )) @@ -1212,12 +1240,17 @@ fn start_executing_work( running == 0 && main_thread_worker_state == MainThreadWorkerState::Idle { assert!(!started_lto); - assert!(needs_lto.len() + lto_import_only_modules.len() > 0); started_lto = true; - let modules = mem::replace(&mut needs_lto, Vec::new()); + + let needs_fat_lto = + mem::replace(&mut needs_fat_lto, Vec::new()); + let needs_thin_lto = + mem::replace(&mut needs_thin_lto, Vec::new()); let import_only_modules = mem::replace(&mut lto_import_only_modules, Vec::new()); - for (work, cost) in generate_lto_work(&cgcx, modules, import_only_modules) { + + for (work, cost) in generate_lto_work(&cgcx, needs_fat_lto, + needs_thin_lto, import_only_modules) { let insertion_index = work_items .binary_search_by_key(&cost, |&(_, cost)| cost) .unwrap_or_else(|e| e); @@ -1284,6 +1317,21 @@ fn start_executing_work( // Relinquish accidentally acquired extra tokens tokens.truncate(running); + // If a thread exits successfully then we drop a token associated + // with that worker and update our `running` count. We may later + // re-acquire a token to continue running more work. We may also not + // actually drop a token here if the worker was running with an + // "ephemeral token" + let mut free_worker = |worker_id| { + if main_thread_worker_state == MainThreadWorkerState::LLVMing { + main_thread_worker_state = MainThreadWorkerState::Idle; + } else { + running -= 1; + } + + free_worker_ids.push(worker_id); + }; + let msg = coordinator_receive.recv().unwrap(); match *msg.downcast::>().ok().unwrap() { // Save the token locally and the next turn of the loop will use @@ -1358,24 +1406,8 @@ fn start_executing_work( assert_eq!(main_thread_worker_state, MainThreadWorkerState::Codegenning); } - - // If a thread exits successfully then we drop a token associated - // with that worker and update our `running` count. We may later - // re-acquire a token to continue running more work. We may also not - // actually drop a token here if the worker was running with an - // "ephemeral token" - // - // Note that if the thread failed that means it panicked, so we - // abort immediately. Message::Done { result: Ok(compiled_module), worker_id } => { - if main_thread_worker_state == MainThreadWorkerState::LLVMing { - main_thread_worker_state = MainThreadWorkerState::Idle; - } else { - running -= 1; - } - - free_worker_ids.push(worker_id); - + free_worker(worker_id); match compiled_module.kind { ModuleKind::Regular => { compiled_modules.push(compiled_module); @@ -1390,15 +1422,15 @@ fn start_executing_work( } } } - Message::NeedsLTO { result, worker_id } => { + Message::NeedsFatLTO { result, worker_id } => { assert!(!started_lto); - if main_thread_worker_state == MainThreadWorkerState::LLVMing { - main_thread_worker_state = MainThreadWorkerState::Idle; - } else { - running -= 1; - } - free_worker_ids.push(worker_id); - needs_lto.push(result); + free_worker(worker_id); + needs_fat_lto.push(result); + } + Message::NeedsThinLTO { name, thin_buffer, worker_id } => { + assert!(!started_lto); + free_worker(worker_id); + needs_thin_lto.push((name, thin_buffer)); } Message::AddImportOnlyModule { module_data, work_product } => { assert!(!started_lto); @@ -1408,6 +1440,7 @@ fn start_executing_work( lto_import_only_modules.push((module_data, work_product)); main_thread_worker_state = MainThreadWorkerState::Idle; } + // If the thread failed that means it panicked, so we abort immediately. Message::Done { result: Err(()), worker_id: _ } => { bug!("worker thread panicked"); } @@ -1485,7 +1518,7 @@ fn spawn_work( // we exit. struct Bomb { coordinator_send: Sender>, - result: Option>, + result: Option>, worker_id: usize, } impl Drop for Bomb { @@ -1495,8 +1528,11 @@ fn spawn_work( Some(WorkItemResult::Compiled(m)) => { Message::Done:: { result: Ok(m), worker_id } } - Some(WorkItemResult::NeedsLTO(m)) => { - Message::NeedsLTO:: { result: m, worker_id } + Some(WorkItemResult::NeedsFatLTO(m)) => { + Message::NeedsFatLTO:: { result: m, worker_id } + } + Some(WorkItemResult::NeedsThinLTO(name, thin_buffer)) => { + Message::NeedsThinLTO:: { name, thin_buffer, worker_id } } None => Message::Done:: { result: Err(()), worker_id } }; diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index 266f78996b3..8a5b8bd2bab 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -268,7 +268,7 @@ pub fn coerce_unsized_into<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( let (base, info) = match bx.load_operand(src).val { OperandValue::Pair(base, info) => { // fat-ptr to fat-ptr unsize preserves the vtable - // i.e. &'a fmt::Debug+Send => &'a fmt::Debug + // i.e., &'a fmt::Debug+Send => &'a fmt::Debug // So we need to pointercast the base to ensure // the types match up. let thin_ptr = dst.layout.field(bx.cx(), FAT_PTR_ADDR); @@ -453,7 +453,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( ) { let (main_def_id, span) = match *cx.sess().entry_fn.borrow() { Some((id, span, _)) => { - (cx.tcx().hir.local_def_id(id), span) + (cx.tcx().hir().local_def_id(id), span) } None => return, }; diff --git a/src/librustc_codegen_ssa/common.rs b/src/librustc_codegen_ssa/common.rs index 8c53129abc3..70b7729b78b 100644 --- a/src/librustc_codegen_ssa/common.rs +++ b/src/librustc_codegen_ssa/common.rs @@ -158,7 +158,7 @@ pub fn langcall(tcx: TyCtxt, } // To avoid UB from LLVM, these two functions mask RHS with an -// appropriate mask unconditionally (i.e. the fallback behavior for +// appropriate mask unconditionally (i.e., the fallback behavior for // all shifts). For 32- and 64-bit types, this matches the semantics // of Java. (See related discussion on #1877 and #10183.) diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs index 24ede4db6e3..d0cdb8924df 100644 --- a/src/librustc_codegen_ssa/lib.rs +++ b/src/librustc_codegen_ssa/lib.rs @@ -61,7 +61,7 @@ use rustc_data_structures::svh::Svh; use rustc::middle::cstore::{LibSource, CrateSource, NativeLibrary}; use syntax_pos::symbol::Symbol; -// NB: This module needs to be declared first so diagnostics are +// N.B., this module needs to be declared first so diagnostics are // registered before they are used. mod diagnostics; diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index c7e2c76c3e5..81da7f5fb5c 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -43,7 +43,7 @@ pub fn non_ssa_locals<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( // These sorts of types require an alloca. Note that // is_llvm_immediate() may *still* be true, particularly // for newtypes, but we currently force some types - // (e.g. structs) into an alloca unconditionally, just so + // (e.g., structs) into an alloca unconditionally, just so // that we don't have to deal with having two pathways // (gep vs extractvalue etc). analyzer.not_ssa(mir::Local::new(index)); @@ -227,9 +227,9 @@ impl<'mir, 'a: 'mir, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) | PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => { - // Reads from uninitialized variables (e.g. in dead code, after + // Reads from uninitialized variables (e.g., in dead code, after // optimizations) require locals to be in (uninitialized) memory. - // NB: there can be uninitialized reads of a local visited after + // N.B., there can be uninitialized reads of a local visited after // an assignment to that local, if they happen on disjoint paths. let ssa_read = match self.first_assignment(local) { Some(assignment_location) => { diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index a992364959e..d316b3ec350 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -467,7 +467,7 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( }; if Some(local) == mir.spread_arg { - // This argument (e.g. the last argument in the "rust-call" ABI) + // This argument (e.g., the last argument in the "rust-call" ABI) // is a tuple that was spread at the ABI level and now we have // to reconstruct it into a tuple local variable, from multiple // individual LLVM function arguments. @@ -610,35 +610,13 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( }; let upvar_tys = upvar_substs.upvar_tys(def_id, tcx); - // Store the pointer to closure data in an alloca for debuginfo - // because that's what the llvm.dbg.declare intrinsic expects. - - // FIXME(eddyb) this shouldn't be necessary but SROA seems to - // mishandle DW_OP_plus not preceded by DW_OP_deref, i.e. it - // doesn't actually strip the offset when splitting the closure - // environment into its components so it ends up out of bounds. - // (cuviper) It seems to be fine without the alloca on LLVM 6 and later. - let env_alloca = !env_ref && bx.closure_env_needs_indirect_debuginfo(); - let env_ptr = if env_alloca { - let scratch = PlaceRef::alloca(bx, - bx.layout_of(tcx.mk_mut_ptr(arg.layout.ty)), - "__debuginfo_env_ptr"); - bx.store(place.llval, scratch.llval, scratch.align); - scratch.llval - } else { - place.llval - }; - for (i, (decl, ty)) in mir.upvar_decls.iter().zip(upvar_tys).enumerate() { let byte_offset_of_var_in_env = closure_layout.fields.offset(i).bytes(); let ops = bx.debuginfo_upvar_decls_ops_sequence(byte_offset_of_var_in_env); // The environment and the capture can each be indirect. - - // FIXME(eddyb) see above why we sometimes have to keep - // a pointer in an alloca for debuginfo atm. - let mut ops = if env_ref || env_alloca { &ops[..] } else { &ops[1..] }; + let mut ops = if env_ref { &ops[..] } else { &ops[1..] }; let ty = if let (true, &ty::Ref(_, ty, _)) = (decl.by_ref, &ty.sty) { ty @@ -648,7 +626,7 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( }; let variable_access = VariableAccess::IndirectVariable { - alloca: env_ptr, + alloca: place.llval, address_operations: &ops }; bx.declare_local( diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index 1aba53255e7..90aa9f6cbc7 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -229,9 +229,9 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> { layout::Variants::Tagged { ref tag, .. } => { let signed = match tag.value { // We use `i1` for bytes that are always `0` or `1`, - // e.g. `#[repr(i8)] enum E { A, B }`, but we can't + // e.g., `#[repr(i8)] enum E { A, B }`, but we can't // let LLVM interpret the `i1` as signed, because - // then `i1 1` (i.e. E::B) is effectively `i8 -1`. + // then `i1 1` (i.e., E::B) is effectively `i8 -1`. layout::Int(_, signed) => !tag.is_bool() && signed, _ => false }; diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index dc7b1ec37b2..c932ffd1c1b 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -319,9 +319,9 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if let layout::Abi::Scalar(ref scalar) = operand.layout.abi { if let layout::Int(_, s) = scalar.value { // We use `i1` for bytes that are always `0` or `1`, - // e.g. `#[repr(i8)] enum E { A, B }`, but we can't + // e.g., `#[repr(i8)] enum E { A, B }`, but we can't // let LLVM interpret the `i1` as signed, because - // then `i1 1` (i.e. E::B) is effectively `i8 -1`. + // then `i1 1` (i.e., E::B) is effectively `i8 -1`. signed = !scalar.is_bool() && s; let er = scalar.valid_range_exclusive(bx.cx()); diff --git a/src/librustc_codegen_ssa/mir/statement.rs b/src/librustc_codegen_ssa/mir/statement.rs index 568a7e7e160..80539b78c70 100644 --- a/src/librustc_codegen_ssa/mir/statement.rs +++ b/src/librustc_codegen_ssa/mir/statement.rs @@ -106,7 +106,6 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::StatementKind::FakeRead(..) | mir::StatementKind::Retag { .. } | - mir::StatementKind::EscapeToRaw { .. } | mir::StatementKind::AscribeUserType(..) | mir::StatementKind::Nop => bx, } diff --git a/src/librustc_codegen_ssa/mono_item.rs b/src/librustc_codegen_ssa/mono_item.rs index 8fe89791969..26f8a9a5dd4 100644 --- a/src/librustc_codegen_ssa/mono_item.rs +++ b/src/librustc_codegen_ssa/mono_item.rs @@ -42,7 +42,7 @@ pub trait MonoItemExt<'a, 'tcx: 'a>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> { cx.codegen_static(def_id, is_mutable); } MonoItem::GlobalAsm(node_id) => { - let item = cx.tcx().hir.expect_item(node_id); + let item = cx.tcx().hir().expect_item(node_id); if let hir::ItemKind::GlobalAsm(ref ga) = item.node { cx.codegen_global_asm(ga); } else { diff --git a/src/librustc_codegen_ssa/traits/declare.rs b/src/librustc_codegen_ssa/traits/declare.rs index f9a29652843..611e5f758a7 100644 --- a/src/librustc_codegen_ssa/traits/declare.rs +++ b/src/librustc_codegen_ssa/traits/declare.rs @@ -41,7 +41,7 @@ pub trait DeclareMethods<'tcx>: BackendTypes { /// Use this function when you intend to define a global. This function will /// return None if the name already has a definition associated with it. In that /// case an error should be reported to the user, because it usually happens due - /// to user’s fault (e.g. misuse of #[no_mangle] or #[export_name] attributes). + /// to user’s fault (e.g., misuse of #[no_mangle] or #[export_name] attributes). fn define_global(&self, name: &str, ty: Self::Type) -> Option; /// Declare a private global diff --git a/src/librustc_codegen_ssa/traits/misc.rs b/src/librustc_codegen_ssa/traits/misc.rs index d8871dd3a58..57afb800d01 100644 --- a/src/librustc_codegen_ssa/traits/misc.rs +++ b/src/librustc_codegen_ssa/traits/misc.rs @@ -32,7 +32,6 @@ pub trait MiscMethods<'tcx>: BackendTypes { fn stats(&self) -> &RefCell; fn consume_stats(self) -> RefCell; fn codegen_unit(&self) -> &Arc>; - fn closure_env_needs_indirect_debuginfo(&self) -> bool; fn used_statics(&self) -> &RefCell>; fn set_frame_pointer_elimination(&self, llfn: Self::Value); fn apply_target_cpu_attr(&self, llfn: Self::Value); diff --git a/src/librustc_codegen_ssa/traits/type_.rs b/src/librustc_codegen_ssa/traits/type_.rs index 1d31bdfa9f0..ed53c8fffa7 100644 --- a/src/librustc_codegen_ssa/traits/type_.rs +++ b/src/librustc_codegen_ssa/traits/type_.rs @@ -32,7 +32,7 @@ pub trait BaseTypeMethods<'tcx>: Backend<'tcx> { fn type_i64(&self) -> Self::Type; fn type_i128(&self) -> Self::Type; - // Creates an integer type with the given number of bits, e.g. i24 + // Creates an integer type with the given number of bits, e.g., i24 fn type_ix(&self, num_bits: u64) -> Self::Type; fn type_isize(&self) -> Self::Type; diff --git a/src/librustc_codegen_ssa/traits/write.rs b/src/librustc_codegen_ssa/traits/write.rs index 72522e19af2..edc5c2717bc 100644 --- a/src/librustc_codegen_ssa/traits/write.rs +++ b/src/librustc_codegen_ssa/traits/write.rs @@ -24,14 +24,19 @@ pub trait WriteBackendMethods: 'static + Sized + Clone { type ThinData: Send + Sync; type ThinBuffer: ThinBufferMethods; - /// Performs LTO, which in the case of full LTO means merging all modules into - /// a single one and returning it for further optimizing. For ThinLTO, it will - /// do the global analysis necessary and return two lists, one of the modules - /// the need optimization and another for modules that can simply be copied over - /// from the incr. comp. cache. - fn run_lto( + /// Performs fat LTO by merging all modules into a single one and returning it + /// for further optimization. + fn run_fat_lto( cgcx: &CodegenContext, modules: Vec>, + timeline: &mut Timeline, + ) -> Result, FatalError>; + /// Performs thin LTO by performing necessary global analysis and returning two + /// lists, one of the modules that need optimization and another for modules that + /// can simply be copied over from the incr. comp. cache. + fn run_thin_lto( + cgcx: &CodegenContext, + modules: Vec<(String, Self::ThinBuffer)>, cached_modules: Vec<(SerializedModule, WorkProduct)>, timeline: &mut Timeline, ) -> Result<(Vec>, Vec), FatalError>; @@ -55,6 +60,10 @@ pub trait WriteBackendMethods: 'static + Sized + Clone { config: &ModuleConfig, timeline: &mut Timeline, ) -> Result; + fn prepare_thin( + cgcx: &CodegenContext, + module: ModuleCodegen + ) -> (String, Self::ThinBuffer); fn run_lto_pass_manager( cgcx: &CodegenContext, llmod: &ModuleCodegen, diff --git a/src/librustc_codegen_utils/codegen_backend.rs b/src/librustc_codegen_utils/codegen_backend.rs index 046f0cccfee..74718460f56 100644 --- a/src/librustc_codegen_utils/codegen_backend.rs +++ b/src/librustc_codegen_utils/codegen_backend.rs @@ -22,8 +22,8 @@ #![feature(box_syntax)] use std::any::Any; -use std::io::{self, Write}; -use std::fs::File; +use std::io::Write; +use std::fs; use std::path::Path; use std::sync::{mpsc, Arc}; @@ -81,13 +81,9 @@ pub struct NoLlvmMetadataLoader; impl MetadataLoader for NoLlvmMetadataLoader { fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result { - let mut file = File::open(filename) - .map_err(|e| format!("metadata file open err: {:?}", e))?; - - let mut buf = Vec::new(); - io::copy(&mut file, &mut buf).unwrap(); - let buf: OwningRef, [u8]> = OwningRef::new(buf).into(); - return Ok(rustc_erase_owner!(buf.map_owner_box())); + let buf = fs::read(filename).map_err(|e| format!("metadata file open err: {:?}", e))?; + let buf: OwningRef, [u8]> = OwningRef::new(buf); + Ok(rustc_erase_owner!(buf.map_owner_box())) } fn get_dylib_metadata(&self, target: &Target, filename: &Path) -> Result { @@ -103,7 +99,7 @@ pub struct OngoingCodegen { } impl MetadataOnlyCodegenBackend { - pub fn new() -> Box { + pub fn boxed() -> Box { box MetadataOnlyCodegenBackend(()) } } @@ -165,15 +161,12 @@ impl CodegenBackend for MetadataOnlyCodegenBackend { tcx, collector::MonoItemCollectionMode::Eager ).0 { - match mono_item { - MonoItem::Fn(inst) => { - let def_id = inst.def_id(); - if def_id.is_local() { - let _ = inst.def.is_inline(tcx); - let _ = tcx.codegen_fn_attrs(def_id); - } + if let MonoItem::Fn(inst) = mono_item { + let def_id = inst.def_id(); + if def_id.is_local() { + let _ = inst.def.is_inline(tcx); + let _ = tcx.codegen_fn_attrs(def_id); } - _ => {} } } tcx.sess.abort_if_errors(); @@ -181,7 +174,7 @@ impl CodegenBackend for MetadataOnlyCodegenBackend { let metadata = tcx.encode_metadata(); box OngoingCodegen { - metadata: metadata, + metadata, metadata_version: tcx.metadata_encoding_version().to_vec(), crate_name: tcx.crate_name(LOCAL_CRATE), } @@ -212,8 +205,7 @@ impl CodegenBackend for MetadataOnlyCodegenBackend { } else { &ongoing_codegen.metadata.raw_data }; - let mut file = File::create(&output_name).unwrap(); - file.write_all(metadata).unwrap(); + fs::write(&output_name, metadata).unwrap(); } sess.abort_if_errors(); diff --git a/src/librustc_codegen_utils/lib.rs b/src/librustc_codegen_utils/lib.rs index ea8259d79a1..cbef3ff5b92 100644 --- a/src/librustc_codegen_utils/lib.rs +++ b/src/librustc_codegen_utils/lib.rs @@ -53,7 +53,7 @@ pub mod symbol_names_test; /// reporting an error. pub fn check_for_rustc_errors_attr(tcx: TyCtxt) { if let Some((id, span, _)) = *tcx.sess.entry_fn.borrow() { - let main_def_id = tcx.hir.local_def_id(id); + let main_def_id = tcx.hir().local_def_id(id); if tcx.has_attr(main_def_id, "rustc_error") { tcx.sess.span_fatal(span, "compilation successful"); diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 344a2525784..d5b95e77b1a 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -71,7 +71,7 @@ //! order to also avoid inter-crate conflicts two more measures are taken: //! //! - The name of the crate containing the symbol is prepended to the symbol -//! name, i.e. symbols are "crate qualified". For example, a function `foo` in +//! name, i.e., symbols are "crate qualified". For example, a function `foo` in //! module `bar` in crate `baz` would get a symbol name like //! `baz::bar::foo::{hash}` instead of just `bar::foo::{hash}`. This avoids //! simple conflicts between functions from different crates. @@ -250,7 +250,7 @@ fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance debug!("symbol_name(def_id={:?}, substs={:?})", def_id, substs); - let node_id = tcx.hir.as_local_node_id(def_id); + let node_id = tcx.hir().as_local_node_id(def_id); if let Some(id) = node_id { if *tcx.sess.plugin_registrar_fn.get() == Some(id) { @@ -265,7 +265,7 @@ fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance // FIXME(eddyb) Precompute a custom symbol name based on attributes. let is_foreign = if let Some(id) = node_id { - match tcx.hir.get(id) { + match tcx.hir().get(id) { Node::ForeignItem(_) => true, _ => false, } @@ -389,7 +389,7 @@ impl SymbolPathBuffer { impl ItemPathBuffer for SymbolPathBuffer { fn root_mode(&self) -> &RootMode { - const ABSOLUTE: &'static RootMode = &RootMode::Absolute; + const ABSOLUTE: &RootMode = &RootMode::Absolute; ABSOLUTE } diff --git a/src/librustc_codegen_utils/symbol_names_test.rs b/src/librustc_codegen_utils/symbol_names_test.rs index 6eaf0c1c08d..c4ad31ab021 100644 --- a/src/librustc_codegen_utils/symbol_names_test.rs +++ b/src/librustc_codegen_utils/symbol_names_test.rs @@ -33,7 +33,7 @@ pub fn report_symbol_names<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { tcx.dep_graph.with_ignore(|| { let mut visitor = SymbolNamesTest { tcx }; - tcx.hir.krate().visit_all_item_likes(&mut visitor); + tcx.hir().krate().visit_all_item_likes(&mut visitor); }) } @@ -45,7 +45,7 @@ impl<'a, 'tcx> SymbolNamesTest<'a, 'tcx> { fn process_attrs(&mut self, node_id: ast::NodeId) { let tcx = self.tcx; - let def_id = tcx.hir.local_def_id(node_id); + let def_id = tcx.hir().local_def_id(node_id); for attr in tcx.get_attrs(def_id).iter() { if attr.check_name(SYMBOL_NAME) { // for now, can only use on monomorphic names diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml index 188919d0633..1754376a5d7 100644 --- a/src/librustc_data_structures/Cargo.toml +++ b/src/librustc_data_structures/Cargo.toml @@ -19,7 +19,7 @@ stable_deref_trait = "1.0.0" rustc-rayon = "0.1.1" rustc-rayon-core = "0.1.1" rustc-hash = "1.0.1" -smallvec = { version = "0.6.5", features = ["union"] } +smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } [dependencies.parking_lot] version = "0.6" diff --git a/src/librustc_data_structures/fingerprint.rs b/src/librustc_data_structures/fingerprint.rs index aa9ddda2b93..f8638213b3a 100644 --- a/src/librustc_data_structures/fingerprint.rs +++ b/src/librustc_data_structures/fingerprint.rs @@ -86,6 +86,7 @@ impl ::std::fmt::Display for Fingerprint { } impl stable_hasher::StableHasherResult for Fingerprint { + #[inline] fn finish(hasher: stable_hasher::StableHasher) -> Self { let (_0, _1) = hasher.finalize(); Fingerprint(_0, _1) diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs index a59bf9d530c..6522dbe1179 100644 --- a/src/librustc_data_structures/indexed_vec.rs +++ b/src/librustc_data_structures/indexed_vec.rs @@ -98,12 +98,18 @@ macro_rules! newtype_index { @max [$max:expr] @vis [$v:vis] @debug_format [$debug_format:tt]) => ( - #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, $($derives),*)] + #[derive(Copy, PartialEq, Eq, Hash, PartialOrd, Ord, $($derives),*)] #[rustc_layout_scalar_valid_range_end($max)] $v struct $type { private: u32 } + impl Clone for $type { + fn clone(&self) -> Self { + *self + } + } + impl $type { $v const MAX_AS_U32: u32 = $max; @@ -145,7 +151,7 @@ macro_rules! newtype_index { #[inline] $v const unsafe fn from_u32_unchecked(value: u32) -> Self { - $type { private: value } + unsafe { $type { private: value } } } /// Extract value of this index as an integer. @@ -328,12 +334,13 @@ macro_rules! newtype_index { derive [$($derives:ident,)+] $($tokens:tt)*) => ( newtype_index!( - @derives [$($derives,)+ RustcDecodable, RustcEncodable,] + @derives [$($derives,)+ RustcEncodable,] @type [$type] @max [$max] @vis [$v] @debug_format [$debug_format] $($tokens)*); + newtype_index!(@decodable $type); ); // The case where no derives are added, but encodable is overridden. Don't @@ -360,12 +367,29 @@ macro_rules! newtype_index { @debug_format [$debug_format:tt] $($tokens:tt)*) => ( newtype_index!( - @derives [RustcDecodable, RustcEncodable,] + @derives [RustcEncodable,] @type [$type] @max [$max] @vis [$v] @debug_format [$debug_format] $($tokens)*); + newtype_index!(@decodable $type); + ); + + (@decodable $type:ident) => ( + impl $type { + fn __decodable__impl__hack() { + mod __more_hacks_because__self_doesnt_work_in_functions { + extern crate serialize; + use self::serialize::{Decodable, Decoder}; + impl Decodable for super::$type { + fn decode(d: &mut D) -> Result { + d.read_u32().map(Self::from) + } + } + } + } + } ); // Rewrite final without comma to one that includes comma diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 96cb235a933..066e1739841 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -28,8 +28,9 @@ #![feature(optin_builtin_traits)] #![feature(nll)] #![feature(allow_internal_unstable)] -#![feature(vec_resize_with)] #![feature(hash_raw_entry)] +#![feature(stmt_expr_attributes)] +#![feature(core_intrinsics)] #![cfg_attr(unix, feature(libc))] #![cfg_attr(test, feature(test))] @@ -58,6 +59,26 @@ extern crate rustc_cratesio_shim; pub use rustc_serialize::hex::ToHex; +#[macro_export] +macro_rules! likely { + ($e:expr) => { + #[allow(unused_unsafe)] + { + unsafe { std::intrinsics::likely($e) } + } + } +} + +#[macro_export] +macro_rules! unlikely { + ($e:expr) => { + #[allow(unused_unsafe)] + { + unsafe { std::intrinsics::unlikely($e) } + } + } +} + pub mod macros; pub mod svh; pub mod base_n; @@ -81,7 +102,6 @@ pub mod sync; pub mod tiny_list; pub mod thin_vec; pub mod transitive_relation; -pub mod tuple_slice; pub use ena::unify; pub mod vec_linked_list; pub mod work_queue; @@ -92,12 +112,14 @@ pub struct OnDrop(pub F); impl OnDrop { /// Forgets the function which prevents it from running. /// Ensure that the function owns no memory, otherwise it will be leaked. + #[inline] pub fn disable(self) { std::mem::forget(self); } } impl Drop for OnDrop { + #[inline] fn drop(&mut self) { (self.0)(); } diff --git a/src/librustc_data_structures/obligation_forest/mod.rs b/src/librustc_data_structures/obligation_forest/mod.rs index c211d888df1..2a1958357e0 100644 --- a/src/librustc_data_structures/obligation_forest/mod.rs +++ b/src/librustc_data_structures/obligation_forest/mod.rs @@ -531,7 +531,7 @@ impl ObligationForest { /// indices. Cannot be used during a transaction. /// /// Beforehand, all nodes must be marked as `Done` and no cycles - /// on these nodes may be present. This is done by e.g. `process_cycles`. + /// on these nodes may be present. This is done by e.g., `process_cycles`. #[inline(never)] fn compress(&mut self, do_completed: DoCompleted) -> Option> { let nodes_len = self.nodes.len(); diff --git a/src/librustc_data_structures/owning_ref/mod.rs b/src/librustc_data_structures/owning_ref/mod.rs index 27c2f8b718a..0b126e5c572 100644 --- a/src/librustc_data_structures/owning_ref/mod.rs +++ b/src/librustc_data_structures/owning_ref/mod.rs @@ -215,7 +215,7 @@ fn main() { ## Mutable reference When the owned container implements `DerefMut`, it is also possible to make -a _mutable owning reference_. (E.g. with `Box`, `RefMut`, `MutexGuard`) +a _mutable owning reference_. (e.g., with `Box`, `RefMut`, `MutexGuard`) ``` extern crate owning_ref; @@ -452,7 +452,7 @@ impl OwningRef { /// use owning_ref::{OwningRef, Erased}; /// /// fn main() { - /// // NB: Using the concrete types here for explicitness. + /// // N.B., using the concrete types here for explicitness. /// // For less verbose code type aliases like `BoxRef` are provided. /// /// let owning_ref_a: OwningRef, [i32; 4]> @@ -722,7 +722,7 @@ impl OwningRefMut { /// use owning_ref::{OwningRefMut, Erased}; /// /// fn main() { - /// // NB: Using the concrete types here for explicitness. + /// // N.B., using the concrete types here for explicitness. /// // For less verbose code type aliases like `BoxRef` are provided. /// /// let owning_ref_mut_a: OwningRefMut, [i32; 4]> @@ -1124,8 +1124,8 @@ impl ToHandleMut for RefCell { unsafe fn to_handle_mut(x: *const Self) -> Self::HandleMut { (*x).borrow_mut() } } -// NB: Implementing ToHandle{,Mut} for Mutex and RwLock requires a decision -// about which handle creation to use (i.e. read() vs try_read()) as well as +// N.B., implementing ToHandle{,Mut} for Mutex and RwLock requires a decision +// about which handle creation to use (i.e., read() vs try_read()) as well as // what to do with error results. /// Typedef of a owning reference that uses a `Box` as the owner. diff --git a/src/librustc_data_structures/sorted_map.rs b/src/librustc_data_structures/sorted_map.rs index 29d99a6aef3..3bd3d116607 100644 --- a/src/librustc_data_structures/sorted_map.rs +++ b/src/librustc_data_structures/sorted_map.rs @@ -10,7 +10,7 @@ use std::borrow::Borrow; use std::cmp::Ordering; -use std::convert::From; +use std::iter::FromIterator; use std::mem; use std::ops::{RangeBounds, Bound, Index, IndexMut}; @@ -25,11 +25,10 @@ use std::ops::{RangeBounds, Bound, Index, IndexMut}; #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug, RustcEncodable, RustcDecodable)] pub struct SortedMap { - data: Vec<(K,V)> + data: Vec<(K, V)> } impl SortedMap { - #[inline] pub fn new() -> SortedMap { SortedMap { @@ -82,7 +81,10 @@ impl SortedMap { } #[inline] - pub fn get(&self, key: &K) -> Option<&V> { + pub fn get(&self, key: &Q) -> Option<&V> + where K: Borrow, + Q: Ord + ?Sized + { match self.lookup_index_for(key) { Ok(index) => { unsafe { @@ -96,7 +98,10 @@ impl SortedMap { } #[inline] - pub fn get_mut(&mut self, key: &K) -> Option<&mut V> { + pub fn get_mut(&mut self, key: &Q) -> Option<&mut V> + where K: Borrow, + Q: Ord + ?Sized + { match self.lookup_index_for(key) { Ok(index) => { unsafe { @@ -122,13 +127,13 @@ impl SortedMap { /// Iterate over the keys, sorted #[inline] - pub fn keys(&self) -> impl Iterator + ExactSizeIterator { + pub fn keys(&self) -> impl Iterator + ExactSizeIterator { self.data.iter().map(|&(ref k, _)| k) } /// Iterate over values, sorted by key #[inline] - pub fn values(&self) -> impl Iterator + ExactSizeIterator { + pub fn values(&self) -> impl Iterator + ExactSizeIterator { self.data.iter().map(|&(_, ref v)| v) } @@ -137,6 +142,11 @@ impl SortedMap { self.data.len() } + #[inline] + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + #[inline] pub fn range(&self, range: R) -> &[(K, V)] where R: RangeBounds @@ -207,8 +217,11 @@ impl SortedMap { /// Looks up the key in `self.data` via `slice::binary_search()`. #[inline(always)] - fn lookup_index_for(&self, key: &K) -> Result { - self.data.binary_search_by(|&(ref x, _)| x.cmp(key)) + fn lookup_index_for(&self, key: &Q) -> Result + where K: Borrow, + Q: Ord + ?Sized + { + self.data.binary_search_by(|&(ref x, _)| x.borrow().cmp(key)) } #[inline] @@ -247,38 +260,54 @@ impl SortedMap { (start, end) } + + #[inline] + pub fn contains_key(&self, key: &Q) -> bool + where K: Borrow, + Q: Ord + ?Sized + { + self.get(key).is_some() + } } impl IntoIterator for SortedMap { type Item = (K, V); type IntoIter = ::std::vec::IntoIter<(K, V)>; + fn into_iter(self) -> Self::IntoIter { self.data.into_iter() } } -impl> Index for SortedMap { +impl<'a, K, Q, V> Index<&'a Q> for SortedMap + where K: Ord + Borrow, + Q: Ord + ?Sized +{ type Output = V; - fn index(&self, index: Q) -> &Self::Output { - let k: &K = index.borrow(); - self.get(k).unwrap() + + fn index(&self, key: &Q) -> &Self::Output { + self.get(key).expect("no entry found for key") } } -impl> IndexMut for SortedMap { - fn index_mut(&mut self, index: Q) -> &mut Self::Output { - let k: &K = index.borrow(); - self.get_mut(k).unwrap() +impl<'a, K, Q, V> IndexMut<&'a Q> for SortedMap + where K: Ord + Borrow, + Q: Ord + ?Sized +{ + fn index_mut(&mut self, key: &Q) -> &mut Self::Output { + self.get_mut(key).expect("no entry found for key") } } -impl> From for SortedMap { - fn from(data: I) -> Self { - let mut data: Vec<(K, V)> = data.collect(); +impl FromIterator<(K, V)> for SortedMap { + fn from_iter>(iter: T) -> Self { + let mut data: Vec<(K, V)> = iter.into_iter().collect(); + data.sort_unstable_by(|&(ref k1, _), &(ref k2, _)| k1.cmp(k2)); data.dedup_by(|&mut (ref k1, _), &mut (ref k2, _)| { k1.cmp(k2) == Ordering::Equal }); + SortedMap { data } diff --git a/src/librustc_data_structures/thin_vec.rs b/src/librustc_data_structures/thin_vec.rs index 546686b46b8..5b7ea161b28 100644 --- a/src/librustc_data_structures/thin_vec.rs +++ b/src/librustc_data_structures/thin_vec.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/// A vector type optimized for cases where this size is usually 0 (c.f. `SmallVector`). +/// A vector type optimized for cases where this size is usually 0 (cf. `SmallVector`). /// The `Option>` wrapping allows us to represent a zero sized vector with `None`, /// which uses only a single (null) pointer. #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] diff --git a/src/librustc_data_structures/transitive_relation.rs b/src/librustc_data_structures/transitive_relation.rs index fd5dfab9e61..250dad8136e 100644 --- a/src/librustc_data_structures/transitive_relation.rs +++ b/src/librustc_data_structures/transitive_relation.rs @@ -304,7 +304,7 @@ impl TransitiveRelation { /// /// The intuition is that this moves "one step up" through a lattice /// (where the relation is encoding the `<=` relation for the lattice). - /// So e.g. if the relation is `->` and we have + /// So e.g., if the relation is `->` and we have /// /// ``` /// a -> b -> d -> f diff --git a/src/librustc_data_structures/tuple_slice.rs b/src/librustc_data_structures/tuple_slice.rs deleted file mode 100644 index b7c71dd3664..00000000000 --- a/src/librustc_data_structures/tuple_slice.rs +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2014 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::slice; - -/// Allows to view uniform tuples as slices -pub trait TupleSlice { - fn as_slice(&self) -> &[T]; - fn as_mut_slice(&mut self) -> &mut [T]; -} - -macro_rules! impl_tuple_slice { - ($tuple_type:ty, $size:expr) => { - impl TupleSlice for $tuple_type { - fn as_slice(&self) -> &[T] { - unsafe { - let ptr = &self.0 as *const T; - slice::from_raw_parts(ptr, $size) - } - } - - fn as_mut_slice(&mut self) -> &mut [T] { - unsafe { - let ptr = &mut self.0 as *mut T; - slice::from_raw_parts_mut(ptr, $size) - } - } - } - } -} - -impl_tuple_slice!((T, T), 2); -impl_tuple_slice!((T, T, T), 3); -impl_tuple_slice!((T, T, T, T), 4); -impl_tuple_slice!((T, T, T, T, T), 5); -impl_tuple_slice!((T, T, T, T, T, T), 6); -impl_tuple_slice!((T, T, T, T, T, T, T), 7); -impl_tuple_slice!((T, T, T, T, T, T, T, T), 8); - -#[test] -fn test_sliced_tuples() { - let t2 = (100, 101); - assert_eq!(t2.as_slice(), &[100, 101]); - - let t3 = (102, 103, 104); - assert_eq!(t3.as_slice(), &[102, 103, 104]); - - let t4 = (105, 106, 107, 108); - assert_eq!(t4.as_slice(), &[105, 106, 107, 108]); - - let t5 = (109, 110, 111, 112, 113); - assert_eq!(t5.as_slice(), &[109, 110, 111, 112, 113]); - - let t6 = (114, 115, 116, 117, 118, 119); - assert_eq!(t6.as_slice(), &[114, 115, 116, 117, 118, 119]); - - let t7 = (120, 121, 122, 123, 124, 125, 126); - assert_eq!(t7.as_slice(), &[120, 121, 122, 123, 124, 125, 126]); - - let t8 = (127, 128, 129, 130, 131, 132, 133, 134); - assert_eq!(t8.as_slice(), &[127, 128, 129, 130, 131, 132, 133, 134]); - -} diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index 1e32f5ef6f0..0356cc9bd54 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -35,7 +35,7 @@ rustc_codegen_utils = { path = "../librustc_codegen_utils" } rustc_typeck = { path = "../librustc_typeck" } serialize = { path = "../libserialize" } syntax = { path = "../libsyntax" } -smallvec = { version = "0.6.5", features = ["union"] } +smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } syntax_ext = { path = "../libsyntax_ext" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 777cc09b8b1..55e052882ea 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -9,15 +9,9 @@ // except according to those terms. use rustc::dep_graph::DepGraph; -use rustc::hir::{self, map as hir_map}; +use rustc::hir; use rustc::hir::lowering::lower_crate; -use rustc_data_structures::fingerprint::Fingerprint; -use rustc_data_structures::stable_hasher::StableHasher; -use rustc_mir as mir; -use rustc::session::{CompileResult, CrateDisambiguator, Session}; -use rustc::session::CompileIncomplete; -use rustc::session::config::{self, Input, OutputFilenames, OutputType}; -use rustc::session::search_paths::PathKind; +use rustc::hir::map as hir_map; use rustc::lint; use rustc::middle::{self, reachable, resolve_lifetime, stability}; use rustc::middle::privacy::AccessLevels; @@ -25,32 +19,27 @@ use rustc::ty::{self, AllArenas, Resolutions, TyCtxt}; use rustc::traits; use rustc::util::common::{install_panic_hook, time, ErrorReported}; use rustc::util::profiling::ProfileCategory; +use rustc::session::{CompileResult, CrateDisambiguator, Session}; +use rustc::session::CompileIncomplete; +use rustc::session::config::{self, Input, OutputFilenames, OutputType}; +use rustc::session::search_paths::PathKind; use rustc_allocator as allocator; use rustc_borrowck as borrowck; +use rustc_codegen_utils::codegen_backend::CodegenBackend; +use rustc_data_structures::fingerprint::Fingerprint; +use rustc_data_structures::stable_hasher::StableHasher; +use rustc_data_structures::sync::{self, Lrc, Lock}; use rustc_incremental; -use rustc_resolve::{MakeGlobMap, Resolver, ResolverArenas}; use rustc_metadata::creader::CrateLoader; use rustc_metadata::cstore::{self, CStore}; -use rustc_traits; -use rustc_codegen_utils::codegen_backend::CodegenBackend; -use rustc_typeck as typeck; -use rustc_privacy; -use rustc_plugin::registry::Registry; -use rustc_plugin as plugin; +use rustc_mir as mir; use rustc_passes::{self, ast_validation, hir_stats, loops, rvalue_promotion}; -use super::Compilation; - -use serialize::json; - -use std::any::Any; -use std::env; -use std::ffi::OsString; -use std::fs; -use std::io::{self, Write}; -use std::iter; -use std::path::{Path, PathBuf}; -use rustc_data_structures::sync::{self, Lrc, Lock}; -use std::sync::mpsc; +use rustc_plugin as plugin; +use rustc_plugin::registry::Registry; +use rustc_privacy; +use rustc_resolve::{MakeGlobMap, Resolver, ResolverArenas}; +use rustc_traits; +use rustc_typeck as typeck; use syntax::{self, ast, attr, diagnostics, visit}; use syntax::early_buffered_lints::BufferedEarlyLint; use syntax::ext::base::ExtCtxt; @@ -62,10 +51,21 @@ use syntax::symbol::Symbol; use syntax_pos::{FileName, hygiene}; use syntax_ext; -use proc_macro_decls; -use pretty::ReplaceBodyWithLoop; +use serialize::json; +use std::any::Any; +use std::env; +use std::ffi::OsString; +use std::fs; +use std::io::{self, Write}; +use std::iter; +use std::path::{Path, PathBuf}; +use std::sync::mpsc; + +use pretty::ReplaceBodyWithLoop; +use proc_macro_decls; use profile; +use super::Compilation; #[cfg(not(parallel_queries))] pub fn spawn_thread_pool R + sync::Send, R: sync::Send>( @@ -246,8 +246,6 @@ pub fn compile_input( } } - let arenas = AllArenas::new(); - // Construct the HIR map let hir_map = time(sess, "indexing hir", || { hir_map::map_crate(sess, cstore, &mut hir_forest, &defs) @@ -263,7 +261,6 @@ pub fn compile_input( sess, outdir, output, - &arenas, &cstore, &hir_map, &analysis, @@ -284,6 +281,8 @@ pub fn compile_input( None }; + let mut arenas = AllArenas::new(); + phase_3_run_analysis_passes( &*codegen_backend, control, @@ -292,7 +291,7 @@ pub fn compile_input( hir_map, analysis, resolutions, - &arenas, + &mut arenas, &crate_name, &outputs, |tcx, analysis, rx, result| { @@ -305,7 +304,7 @@ pub fn compile_input( outdir, output, opt_crate, - tcx.hir.krate(), + tcx.hir().krate(), &analysis, tcx, &crate_name, @@ -356,10 +355,10 @@ pub fn compile_input( if sess.opts.debugging_opts.self_profile { sess.print_profiler_results(); + } - if sess.opts.debugging_opts.profile_json { - sess.save_json_results(); - } + if sess.opts.debugging_opts.profile_json { + sess.save_json_results(); } controller_entry_point!( @@ -533,7 +532,6 @@ pub struct CompileState<'a, 'tcx: 'a> { pub output_filenames: Option<&'a OutputFilenames>, pub out_dir: Option<&'a Path>, pub out_file: Option<&'a Path>, - pub arenas: Option<&'tcx AllArenas<'tcx>>, pub expanded_crate: Option<&'a ast::Crate>, pub hir_crate: Option<&'a hir::Crate>, pub hir_map: Option<&'a hir_map::Map<'tcx>>, @@ -549,7 +547,6 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> { session, out_dir: out_dir.as_ref().map(|s| &**s), out_file: None, - arenas: None, krate: None, registry: None, cstore: None, @@ -605,7 +602,6 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> { session: &'tcx Session, out_dir: &'a Option, out_file: &'a Option, - arenas: &'tcx AllArenas<'tcx>, cstore: &'tcx CStore, hir_map: &'a hir_map::Map<'tcx>, analysis: &'a ty::CrateAnalysis, @@ -617,7 +613,6 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> { ) -> Self { CompileState { crate_name: Some(crate_name), - arenas: Some(arenas), cstore: Some(cstore), hir_map: Some(hir_map), analysis: Some(analysis), @@ -730,9 +725,9 @@ pub struct ExpansionResult { pub hir_forest: hir_map::Forest, } -pub struct InnerExpansionResult<'a, 'b: 'a> { +pub struct InnerExpansionResult<'a> { pub expanded_crate: ast::Crate, - pub resolver: Resolver<'a, 'b>, + pub resolver: Resolver<'a>, pub hir_forest: hir_map::Forest, } @@ -811,7 +806,7 @@ where /// Same as phase_2_configure_and_expand, but doesn't let you keep the resolver /// around -pub fn phase_2_configure_and_expand_inner<'a, 'b: 'a, F>( +pub fn phase_2_configure_and_expand_inner<'a, F>( sess: &'a Session, cstore: &'a CStore, mut krate: ast::Crate, @@ -820,9 +815,9 @@ pub fn phase_2_configure_and_expand_inner<'a, 'b: 'a, F>( addl_plugins: Option>, make_glob_map: MakeGlobMap, resolver_arenas: &'a ResolverArenas<'a>, - crate_loader: &'a mut CrateLoader<'b>, + crate_loader: &'a mut CrateLoader<'a>, after_expand: F, -) -> Result, CompileIncomplete> +) -> Result, CompileIncomplete> where F: FnOnce(&ast::Crate) -> CompileResult, { @@ -908,7 +903,6 @@ where } }); - let whitelisted_legacy_custom_derives = registry.take_whitelisted_custom_derives(); let Registry { syntax_exts, early_lint_passes, @@ -955,7 +949,6 @@ where crate_loader, &resolver_arenas, ); - resolver.whitelisted_legacy_custom_derives = whitelisted_legacy_custom_derives; syntax_ext::register_builtins(&mut resolver, syntax_exts, sess.features_untracked().quote); // Expand all macros @@ -977,7 +970,7 @@ where let mut old_path = OsString::new(); if cfg!(windows) { old_path = env::var_os("PATH").unwrap_or(old_path); - let mut new_path = sess.host_filesearch(PathKind::All).get_dylib_search_paths(); + let mut new_path = sess.host_filesearch(PathKind::All).search_path_dirs(); for path in env::split_paths(&old_path) { if !new_path.contains(&path) { new_path.push(path); @@ -1218,7 +1211,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>( hir_map: hir_map::Map<'tcx>, mut analysis: ty::CrateAnalysis, resolutions: Resolutions, - arenas: &'tcx AllArenas<'tcx>, + arenas: &'tcx mut AllArenas<'tcx>, name: &str, output_filenames: &OutputFilenames, f: F, diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 061c19eca36..5527c0ad387 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -25,7 +25,6 @@ #![feature(rustc_diagnostic_macros)] #![feature(slice_sort_by_cached_key)] #![feature(set_stdio)] -#![feature(rustc_stack_internals)] #![feature(no_debug)] #![recursion_limit="256"] @@ -258,7 +257,7 @@ pub fn get_codegen_backend(sess: &Session) -> Box { .unwrap_or(&sess.target.target.options.codegen_backend); let backend = match &codegen_name[..] { "metadata_only" => { - rustc_codegen_utils::codegen_backend::MetadataOnlyCodegenBackend::new + rustc_codegen_utils::codegen_backend::MetadataOnlyCodegenBackend::boxed } filename if filename.contains(".") => { load_backend_from_dylib(filename.as_ref()) @@ -291,7 +290,7 @@ fn get_codegen_sysroot(backend_name: &str) -> fn() -> Box { // let's just return a dummy creation function which won't be used in // general anyway. if cfg!(test) { - return rustc_codegen_utils::codegen_backend::MetadataOnlyCodegenBackend::new + return rustc_codegen_utils::codegen_backend::MetadataOnlyCodegenBackend::boxed } let target = session::config::host_triple(); @@ -594,7 +593,7 @@ fn make_input(free_matches: &[String]) -> Option<(Input, Option, Option } else { None }; - Some((Input::Str { name: FileName::Anon, input: src }, + Some((Input::Str { name: FileName::anon_source_code(&src), input: src }, None, err)) } else { Some((Input::File(PathBuf::from(ifile)), @@ -911,7 +910,6 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { &state.expanded_crate.take().unwrap(), state.crate_name.unwrap(), ppm, - state.arenas.unwrap(), state.output_filenames.unwrap(), opt_uii.clone(), state.out_file); @@ -1042,7 +1040,7 @@ impl RustcDefaultCalls { targets.sort(); println!("{}", targets.join("\n")); }, - Sysroot => println!("{}", sess.sysroot().display()), + Sysroot => println!("{}", sess.sysroot.display()), TargetSpec => println!("{}", sess.target.target.to_json().pretty()), FileNames | CrateName => { let input = input.unwrap_or_else(|| @@ -1482,69 +1480,13 @@ pub fn in_named_rustc_thread(name: String, f: F) -> Result R + Send + 'static, R: Send + 'static, { - #[cfg(all(unix, not(target_os = "haiku")))] - let spawn_thread = unsafe { - // Fetch the current resource limits - let mut rlim = libc::rlimit { - rlim_cur: 0, - rlim_max: 0, - }; - if libc::getrlimit(libc::RLIMIT_STACK, &mut rlim) != 0 { - let err = io::Error::last_os_error(); - error!("in_rustc_thread: error calling getrlimit: {}", err); - true - } else if rlim.rlim_max < STACK_SIZE as libc::rlim_t { - true - } else if rlim.rlim_cur < STACK_SIZE as libc::rlim_t { - std::rt::deinit_stack_guard(); - rlim.rlim_cur = STACK_SIZE as libc::rlim_t; - if libc::setrlimit(libc::RLIMIT_STACK, &mut rlim) != 0 { - let err = io::Error::last_os_error(); - error!("in_rustc_thread: error calling setrlimit: {}", err); - std::rt::update_stack_guard(); - true - } else { - std::rt::update_stack_guard(); - false - } - } else { - false - } - }; - - // We set the stack size at link time. See src/rustc/rustc.rs. - #[cfg(windows)] - let spawn_thread = false; - - #[cfg(target_os = "haiku")] - let spawn_thread = unsafe { - // Haiku does not have setrlimit implemented for the stack size. - // By default it does have the 16 MB stack limit, but we check this in - // case the minimum STACK_SIZE changes or Haiku's defaults change. - let mut rlim = libc::rlimit { - rlim_cur: 0, - rlim_max: 0, - }; - if libc::getrlimit(libc::RLIMIT_STACK, &mut rlim) != 0 { - let err = io::Error::last_os_error(); - error!("in_rustc_thread: error calling getrlimit: {}", err); - true - } else if rlim.rlim_cur >= STACK_SIZE { - false - } else { - true - } - }; - - #[cfg(not(any(windows, unix)))] - let spawn_thread = true; - - // The or condition is added from backward compatibility. - if spawn_thread || env::var_os("RUST_MIN_STACK").is_some() { + // We need a thread for soundness of thread local storage in rustc. For debugging purposes + // we allow an escape hatch where everything runs on the main thread. + if env::var_os("RUSTC_UNSTABLE_NO_MAIN_THREAD").is_none() { let mut cfg = thread::Builder::new().name(name); - // FIXME: Hacks on hacks. If the env is trying to override the stack size - // then *don't* set it explicitly. + // If the env is trying to override the stack size then *don't* set it explicitly. + // The libstd thread impl will fetch the `RUST_MIN_STACK` env var itself. if env::var_os("RUST_MIN_STACK").is_none() { cfg = cfg.stack_size(STACK_SIZE); } diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index fb8093d1d77..bc991016bbe 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -8,25 +8,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! The various pretty print routines. +//! The various pretty-printing routines. -pub use self::UserIdentifiedItem::*; -pub use self::PpSourceMode::*; -pub use self::PpMode::*; -use self::NodesMatchingUII::*; - -use {abort_on_err, driver}; - -use rustc::ty::{self, TyCtxt, Resolutions, AllArenas}; use rustc::cfg; use rustc::cfg::graphviz::LabelledCFG; +use rustc::hir; +use rustc::hir::map as hir_map; +use rustc::hir::map::blocks; +use rustc::hir::print as pprust_hir; use rustc::session::Session; use rustc::session::config::{Input, OutputFilenames}; +use rustc::ty::{self, TyCtxt, Resolutions, AllArenas}; use rustc_borrowck as borrowck; use rustc_borrowck::graphviz as borrowck_dot; use rustc_data_structures::thin_vec::ThinVec; use rustc_metadata::cstore::CStore; - use rustc_mir::util::{write_mir_pretty, write_mir_graphviz}; use syntax::ast::{self, BlockCheckMode}; @@ -47,10 +43,11 @@ use std::path::Path; use std::str::FromStr; use std::mem; -use rustc::hir::map as hir_map; -use rustc::hir::map::blocks; -use rustc::hir; -use rustc::hir::print as pprust_hir; +pub use self::UserIdentifiedItem::*; +pub use self::PpSourceMode::*; +pub use self::PpMode::*; +use self::NodesMatchingUII::*; +use {abort_on_err, driver}; #[derive(Copy, Clone, PartialEq, Debug)] pub enum PpSourceMode { @@ -205,7 +202,6 @@ impl PpSourceMode { hir_map: &hir_map::Map<'tcx>, analysis: &ty::CrateAnalysis, resolutions: &Resolutions, - arenas: &'tcx AllArenas<'tcx>, output_filenames: &OutputFilenames, id: &str, f: F @@ -231,6 +227,7 @@ impl PpSourceMode { PpmTyped => { let control = &driver::CompileController::basic(); let codegen_backend = ::get_codegen_backend(sess); + let mut arenas = AllArenas::new(); abort_on_err(driver::phase_3_run_analysis_passes(&*codegen_backend, control, sess, @@ -238,7 +235,7 @@ impl PpSourceMode { hir_map.clone(), analysis.clone(), resolutions.clone(), - arenas, + &mut arenas, id, output_filenames, |tcx, _, _, _| { @@ -495,7 +492,7 @@ impl<'b, 'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'b, 'tcx> { } fn hir_map<'a>(&'a self) -> Option<&'a hir_map::Map<'tcx>> { - Some(&self.tcx.hir) + Some(&self.tcx.hir()) } fn pp_ann<'a>(&'a self) -> &'a dyn pprust_hir::PpAnn { @@ -514,7 +511,7 @@ impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> { if let pprust_hir::Nested::Body(id) = nested { self.tables.set(self.tcx.body_tables(id)); } - pprust_hir::PpAnn::nested(&self.tcx.hir, state, nested)?; + pprust_hir::PpAnn::nested(self.tcx.hir(), state, nested)?; self.tables.set(old_tables); Ok(()) } @@ -851,18 +848,18 @@ fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec, // Find the function this expression is from. let mut node_id = expr.id; loop { - let node = tcx.hir.get(node_id); + let node = tcx.hir().get(node_id); if let Some(n) = hir::map::blocks::FnLikeNode::from_node(node) { break n.body(); } - let parent = tcx.hir.get_parent_node(node_id); + let parent = tcx.hir().get_parent_node(node_id); assert_ne!(node_id, parent); node_id = parent; } } blocks::Code::FnLike(fn_like) => fn_like.body(), }; - let body = tcx.hir.body(body_id); + let body = tcx.hir().body(body_id); let cfg = cfg::CFG::new(tcx, &body); let labelled_edges = mode != PpFlowGraphMode::UnlabelledEdges; let lcfg = LabelledCFG { @@ -980,7 +977,6 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, krate: &ast::Crate, crate_name: &str, ppm: PpMode, - arenas: &'tcx AllArenas<'tcx>, output_filenames: &OutputFilenames, opt_uii: Option, ofile: Option<&Path>) { @@ -991,7 +987,6 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, analysis, resolutions, crate_name, - arenas, output_filenames, ppm, opt_uii, @@ -1029,7 +1024,6 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, hir_map, analysis, resolutions, - arenas, output_filenames, crate_name, move |annotation, krate| { @@ -1053,7 +1047,6 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, hir_map, analysis, resolutions, - arenas, output_filenames, crate_name, move |_annotation, krate| { @@ -1069,7 +1062,6 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, hir_map, analysis, resolutions, - arenas, output_filenames, crate_name, move |annotation, _| { @@ -1103,7 +1095,6 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, hir_map, analysis, resolutions, - arenas, output_filenames, crate_name, move |_annotation, _krate| { @@ -1133,7 +1124,6 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session, analysis: &ty::CrateAnalysis, resolutions: &Resolutions, crate_name: &str, - arenas: &'tcx AllArenas<'tcx>, output_filenames: &OutputFilenames, ppm: PpMode, uii: Option, @@ -1150,6 +1140,7 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session, let control = &driver::CompileController::basic(); let codegen_backend = ::get_codegen_backend(sess); + let mut arenas = AllArenas::new(); abort_on_err(driver::phase_3_run_analysis_passes(&*codegen_backend, control, sess, @@ -1157,14 +1148,14 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session, hir_map.clone(), analysis.clone(), resolutions.clone(), - arenas, + &mut arenas, crate_name, output_filenames, |tcx, _, _, _| { match ppm { PpmMir | PpmMirCFG => { if let Some(nodeid) = nodeid { - let def_id = tcx.hir.local_def_id(nodeid); + let def_id = tcx.hir().local_def_id(nodeid); match ppm { PpmMir => write_mir_pretty(tcx, Some(def_id), &mut out), PpmMirCFG => write_mir_graphviz(tcx, Some(def_id), &mut out), @@ -1183,11 +1174,11 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session, let nodeid = nodeid.expect("`pretty flowgraph=..` needs NodeId (int) or unique path \ suffix (b::c::d)"); - let node = tcx.hir.find(nodeid).unwrap_or_else(|| { + let node = tcx.hir().find(nodeid).unwrap_or_else(|| { tcx.sess.fatal(&format!("--pretty flowgraph couldn't find id: {}", nodeid)) }); - match blocks::Code::from_node(&tcx.hir, nodeid) { + match blocks::Code::from_node(&tcx.hir(), nodeid) { Some(code) => { let variants = gather_flowgraph_variants(tcx.sess); @@ -1200,7 +1191,7 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session, got {:?}", node); - tcx.sess.span_fatal(tcx.hir.span(nodeid), &message) + tcx.sess.span_fatal(tcx.hir().span(nodeid), &message) } } } diff --git a/src/librustc_driver/profile/mod.rs b/src/librustc_driver/profile/mod.rs index d334a9476ce..0d4610d288c 100644 --- a/src/librustc_driver/profile/mod.rs +++ b/src/librustc_driver/profile/mod.rs @@ -64,9 +64,7 @@ struct StackFrame { } fn total_duration(traces: &[trace::Rec]) -> Duration { - let mut sum : Duration = Duration::new(0, 0); - for t in traces.iter() { sum += t.dur_total; } - return sum + Duration::new(0, 0) + traces.iter().map(|t| t.dur_total).sum() } // profiling thread; retains state (in local variables) and dump traces, upon request. @@ -93,40 +91,38 @@ fn profile_queries_thread(r: Receiver) { ProfileQueriesMsg::Dump(params) => { assert!(stack.is_empty()); assert!(frame.parse_st == ParseState::Clear); - { - // write log of all messages - if params.dump_profq_msg_log { - let mut log_file = - File::create(format!("{}.log.txt", params.path)).unwrap(); - for m in profq_msgs.iter() { - writeln!(&mut log_file, "{:?}", m).unwrap() - }; - } - // write HTML file, and counts file - let html_path = format!("{}.html", params.path); - let mut html_file = File::create(&html_path).unwrap(); - - let counts_path = format!("{}.counts.txt", params.path); - let mut counts_file = File::create(&counts_path).unwrap(); - - writeln!(html_file, - "\n\n", - "profile_queries.css").unwrap(); - writeln!(html_file, "\n\n").unwrap(); - trace::write_traces(&mut html_file, &mut counts_file, &frame.traces); - writeln!(html_file, "\n").unwrap(); - - let ack_path = format!("{}.ack", params.path); - let ack_file = File::create(&ack_path).unwrap(); - drop(ack_file); - - // Tell main thread that we are done, e.g., so it can exit - params.ack.send(()).unwrap(); + // write log of all messages + if params.dump_profq_msg_log { + let mut log_file = + File::create(format!("{}.log.txt", params.path)).unwrap(); + for m in profq_msgs.iter() { + writeln!(&mut log_file, "{:?}", m).unwrap() + }; } - continue + + // write HTML file, and counts file + let html_path = format!("{}.html", params.path); + let mut html_file = File::create(&html_path).unwrap(); + + let counts_path = format!("{}.counts.txt", params.path); + let mut counts_file = File::create(&counts_path).unwrap(); + + writeln!(html_file, + "\n\n", + "profile_queries.css").unwrap(); + writeln!(html_file, "\n\n").unwrap(); + trace::write_traces(&mut html_file, &mut counts_file, &frame.traces); + writeln!(html_file, "\n").unwrap(); + + let ack_path = format!("{}.ack", params.path); + let ack_file = File::create(&ack_path).unwrap(); + drop(ack_file); + + // Tell main thread that we are done, e.g., so it can exit + params.ack.send(()).unwrap(); } // Actual query message: msg => { @@ -134,9 +130,9 @@ fn profile_queries_thread(r: Receiver) { profq_msgs.push(msg.clone()); // Respond to the message, knowing that we've already handled Halt and Dump, above. match (frame.parse_st.clone(), msg) { - (_,ProfileQueriesMsg::Halt) => unreachable!(), - (_,ProfileQueriesMsg::Dump(_)) => unreachable!(), - + (_, ProfileQueriesMsg::Halt) | (_, ProfileQueriesMsg::Dump(_)) => { + unreachable!(); + }, // Parse State: Clear (ParseState::Clear, ProfileQueriesMsg::QueryBegin(span, querymsg)) => { @@ -163,8 +159,8 @@ fn profile_queries_thread(r: Receiver) { ParseState::HaveQuery(q, start) => { let duration = start.elapsed(); frame = StackFrame{ - parse_st:ParseState::Clear, - traces:old_frame.traces + parse_st: ParseState::Clear, + traces: old_frame.traces }; let dur_extent = total_duration(&provider_extent); let trace = Rec { @@ -181,18 +177,16 @@ fn profile_queries_thread(r: Receiver) { } } }, - - (ParseState::Clear, ProfileQueriesMsg::TimeBegin(msg)) => { let start = Instant::now(); frame.parse_st = ParseState::HaveTimeBegin(msg, start); stack.push(frame); - frame = StackFrame{parse_st:ParseState::Clear, traces:vec![]}; + frame = StackFrame{parse_st: ParseState::Clear, traces: vec![]}; + }, + (_, ProfileQueriesMsg::TimeBegin(_)) => { + panic!("parse error; did not expect time begin here"); }, - (_, ProfileQueriesMsg::TimeBegin(_)) => - panic!("parse error; did not expect time begin here"), - (ParseState::Clear, ProfileQueriesMsg::TimeEnd) => { let provider_extent = frame.traces; @@ -204,8 +198,8 @@ fn profile_queries_thread(r: Receiver) { ParseState::HaveTimeBegin(msg, start) => { let duration = start.elapsed(); frame = StackFrame{ - parse_st:ParseState::Clear, - traces:old_frame.traces + parse_st: ParseState::Clear, + traces: old_frame.traces }; let dur_extent = total_duration(&provider_extent); let trace = Rec { @@ -222,18 +216,19 @@ fn profile_queries_thread(r: Receiver) { } } }, - (_, ProfileQueriesMsg::TimeEnd) => { panic!("parse error") } - + (_, ProfileQueriesMsg::TimeEnd) => { + panic!("parse error") + }, (ParseState::Clear, ProfileQueriesMsg::TaskBegin(key)) => { let start = Instant::now(); frame.parse_st = ParseState::HaveTaskBegin(key, start); stack.push(frame); - frame = StackFrame{parse_st:ParseState::Clear, traces:vec![]}; + frame = StackFrame{ parse_st: ParseState::Clear, traces: vec![] }; + }, + (_, ProfileQueriesMsg::TaskBegin(_)) => { + panic!("parse error; did not expect time begin here"); }, - (_, ProfileQueriesMsg::TaskBegin(_)) => - panic!("parse error; did not expect time begin here"), - (ParseState::Clear, ProfileQueriesMsg::TaskEnd) => { let provider_extent = frame.traces; @@ -245,8 +240,8 @@ fn profile_queries_thread(r: Receiver) { ParseState::HaveTaskBegin(key, start) => { let duration = start.elapsed(); frame = StackFrame{ - parse_st:ParseState::Clear, - traces:old_frame.traces + parse_st: ParseState::Clear, + traces: old_frame.traces }; let dur_extent = total_duration(&provider_extent); let trace = Rec { @@ -263,8 +258,9 @@ fn profile_queries_thread(r: Receiver) { } } }, - (_, ProfileQueriesMsg::TaskEnd) => { panic!("parse error") } - + (_, ProfileQueriesMsg::TaskEnd) => { + panic!("parse error") + }, // Parse State: HaveQuery (ParseState::HaveQuery(q,start), ProfileQueriesMsg::CacheHit) => { @@ -279,26 +275,25 @@ fn profile_queries_thread(r: Receiver) { frame.traces.push( trace ); frame.parse_st = ParseState::Clear; }, - (ParseState::HaveQuery(_,_), + (ParseState::HaveQuery(_, _), ProfileQueriesMsg::ProviderBegin) => { stack.push(frame); - frame = StackFrame{parse_st:ParseState::Clear, traces:vec![]}; + frame = StackFrame{ parse_st: ParseState::Clear, traces: vec![] }; }, // Parse errors: - (ParseState::HaveQuery(q,_), + (ParseState::HaveQuery(q, _), ProfileQueriesMsg::ProviderEnd) => { panic!("parse error: unexpected ProviderEnd; \ expected something else to follow BeginQuery for {:?}", q) }, - (ParseState::HaveQuery(q1,_), - ProfileQueriesMsg::QueryBegin(span2,querymsg2)) => { + (ParseState::HaveQuery(q1, _), + ProfileQueriesMsg::QueryBegin(span2, querymsg2)) => { panic!("parse error: unexpected QueryBegin; \ earlier query is unfinished: {:?} and now {:?}", - q1, Query{span:span2, msg:querymsg2}) + q1, Query{span:span2, msg: querymsg2}) }, - (ParseState::HaveTimeBegin(_, _), _) => { unreachable!() }, diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 8865c7e438e..5b337fbf5be 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -10,13 +10,11 @@ //! # Standalone Tests for the Inference Module -use std::path::PathBuf; -use std::sync::mpsc; - use driver; use errors; use errors::emitter::Emitter; use errors::{DiagnosticBuilder, Level}; +use rustc::hir; use rustc::hir::map as hir_map; use rustc::infer::outlives::env::OutlivesEnvironment; use rustc::infer::type_variable::TypeVariableOrigin; @@ -40,7 +38,8 @@ use syntax::source_map::{FileName, FilePathMapping, SourceMap}; use syntax::symbol::Symbol; use syntax_pos::DUMMY_SP; -use rustc::hir; +use std::path::PathBuf; +use std::sync::mpsc; struct Env<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { infcx: &'a infer::InferCtxt<'a, 'gcx, 'tcx>, @@ -98,7 +97,7 @@ fn errors(msgs: &[&str]) -> (Box, usize) { fn test_env(source_string: &str, args: (Box, usize), body: F) where - F: FnOnce(Env), + F: FnOnce(Env) + sync::Send, { syntax::with_globals(|| { let mut options = config::Options::default(); @@ -129,7 +128,7 @@ fn test_env_with_pool( let cstore = CStore::new(::get_codegen_backend(&sess).metadata_loader()); rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); let input = config::Input::Str { - name: FileName::Anon, + name: FileName::anon_source_code(&source_string), input: source_string.to_string(), }; let krate = @@ -152,10 +151,10 @@ fn test_env_with_pool( ).expect("phase 2 aborted") }; - let arenas = ty::AllArenas::new(); + let mut arenas = ty::AllArenas::new(); let hir_map = hir_map::map_crate(&sess, &cstore, &mut hir_forest, &defs); - // run just enough stuff to build a tcx: + // Run just enough stuff to build a tcx. let (tx, _rx) = mpsc::channel(); let outputs = OutputFilenames { out_directory: PathBuf::new(), @@ -169,7 +168,7 @@ fn test_env_with_pool( &cstore, ty::query::Providers::default(), ty::query::Providers::default(), - &arenas, + &mut arenas, resolutions, hir_map, OnDiskCache::new_empty(sess.source_map()), @@ -186,7 +185,7 @@ fn test_env_with_pool( param_env: param_env, }); let outlives_env = OutlivesEnvironment::new(param_env); - let def_id = tcx.hir.local_def_id(ast::CRATE_NODE_ID); + let def_id = tcx.hir().local_def_id(ast::CRATE_NODE_ID); infcx.resolve_regions_and_report_errors( def_id, ®ion_scope_tree, @@ -228,8 +227,8 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { } pub fn create_simple_region_hierarchy(&mut self) { - // creates a region hierarchy where 1 is root, 10 and 11 are - // children of 1, etc + // Creates a region hierarchy where 1 is root, 10 and 11 are + // children of 1, etc. let dscope = region::Scope { id: hir::ItemLocalId::from_u32(1), @@ -256,7 +255,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { #[allow(dead_code)] // this seems like it could be useful, even if we don't use it now pub fn lookup_item(&self, names: &[String]) -> ast::NodeId { - return match search_mod(self, &self.infcx.tcx.hir.krate().module, 0, names) { + return match search_mod(self, &self.infcx.tcx.hir().krate().module, 0, names) { Some(id) => id, None => { panic!("no item found: `{}`", names.join("::")); @@ -271,7 +270,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { ) -> Option { assert!(idx < names.len()); for item in &m.item_ids { - let item = this.infcx.tcx.hir.expect_item(item.id); + let item = this.infcx.tcx.hir().expect_item(item.id); if item.name.to_string() == names[idx] { return search(this, item, idx + 1, names); } @@ -364,7 +363,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { self.infcx .tcx .mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion { - def_id: self.infcx.tcx.hir.local_def_id(ast::CRATE_NODE_ID), + def_id: self.infcx.tcx.hir().local_def_id(ast::CRATE_NODE_ID), index, name, })) @@ -410,7 +409,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { pub fn re_free(&self, id: u32) -> ty::Region<'tcx> { self.infcx.tcx.mk_region(ty::ReFree(ty::FreeRegion { - scope: self.infcx.tcx.hir.local_def_id(ast::CRATE_NODE_ID), + scope: self.infcx.tcx.hir().local_def_id(ast::CRATE_NODE_ID), bound_region: ty::BrAnon(id), })) } @@ -434,7 +433,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { obligations, value: (), }) => { - // None of these tests should require nested obligations: + // None of these tests should require nested obligations. assert!(obligations.is_empty()); } Err(ref e) => { @@ -476,7 +475,7 @@ fn contravariant_region_ptr_err() { env.assert_eq(t_rptr1, t_rptr1); env.assert_eq(t_rptr10, t_rptr10); - // will cause an error when regions are resolved + // This will cause an error when regions are resolved. env.make_subtype(t_rptr10, t_rptr1); }) } @@ -487,7 +486,7 @@ fn sub_free_bound_false() { //! //! fn(&'a isize) <: for<'b> fn(&'b isize) //! - //! does NOT hold. + //! *does not* hold. test_env(EMPTY_SOURCE_STR, errors(&[]), |mut env| { env.create_simple_region_hierarchy(); @@ -506,7 +505,7 @@ fn sub_bound_free_true() { //! //! for<'a> fn(&'a isize) <: fn(&'b isize) //! - //! DOES hold. + //! *does* hold. test_env(EMPTY_SOURCE_STR, errors(&[]), |mut env| { env.create_simple_region_hierarchy(); @@ -578,11 +577,11 @@ fn subst_ty_renumber_bound() { fn subst_ty_renumber_some_bounds() { test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { // Situation: - // Theta = [A -> &'a foo] + // `Theta = [A -> &'a foo]` let t_rptr_bound1 = env.t_rptr_late_bound(1); - // t_source = (A, fn(A)) + // `t_source = (A, fn(A))` let t_source = { let t_param = env.t_param(0); env.t_pair(t_param, env.t_fn(&[t_param], env.t_nil())) @@ -591,9 +590,9 @@ fn subst_ty_renumber_some_bounds() { let substs = env.infcx.tcx.intern_substs(&[t_rptr_bound1.into()]); let t_substituted = t_source.subst(env.infcx.tcx, substs); - // t_expected = (&'a isize, fn(&'a isize)) + // `t_expected = (&'a isize, fn(&'a isize))` // - // but not that the Debruijn index is different in the different cases. + // However, note that the Debruijn index is different in the different cases. let t_expected = { let t_rptr_bound2 = env.t_rptr_late_bound_with_debruijn(1, d2()); env.t_pair(t_rptr_bound1, env.t_fn(&[t_rptr_bound2], env.t_nil())) @@ -613,7 +612,7 @@ fn subst_ty_renumber_some_bounds() { fn escaping() { test_env(EMPTY_SOURCE_STR, errors(&[]), |mut env| { // Situation: - // Theta = [A -> &'a foo] + // `Theta = [A -> &'a foo]` env.create_simple_region_hierarchy(); assert!(!env.t_nil().has_escaping_bound_vars()); @@ -627,7 +626,7 @@ fn escaping() { let t_rptr_bound2 = env.t_rptr_late_bound_with_debruijn(1, d2()); assert!(t_rptr_bound2.has_escaping_bound_vars()); - // t_fn = fn(A) + // `t_fn = fn(A)` let t_param = env.t_param(0); assert!(!t_param.has_escaping_bound_vars()); let t_fn = env.t_fn(&[t_param], env.t_nil()); @@ -642,7 +641,7 @@ fn subst_region_renumber_region() { test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { let re_bound1 = env.re_late_bound_with_debruijn(1, d1()); - // type t_source<'a> = fn(&'a isize) + // `type t_source<'a> = fn(&'a isize)` let t_source = { let re_early = env.re_early_bound(0, "'a"); env.t_fn(&[env.t_rptr(re_early)], env.t_nil()) @@ -651,7 +650,7 @@ fn subst_region_renumber_region() { let substs = env.infcx.tcx.intern_substs(&[re_bound1.into()]); let t_substituted = t_source.subst(env.infcx.tcx, substs); - // t_expected = fn(&'a isize) + // `t_expected = fn(&'a isize)` // // but not that the Debruijn index is different in the different cases. let t_expected = { diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 7e69e98071d..7bd0f0f8fc4 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -549,7 +549,7 @@ impl EmitterWriter { // 3 | // 4 | } // | - for pos in 0..line_len + 1 { + for pos in 0..=line_len { draw_col_separator(buffer, line_offset + pos + 1, width_offset - 2); buffer.putc(line_offset + pos + 1, width_offset - 2, @@ -617,7 +617,7 @@ impl EmitterWriter { let pos = pos + 1; if pos > 1 && (annotation.has_label() || annotation.takes_space()) { - for p in line_offset + 1..line_offset + pos + 1 { + for p in line_offset + 1..=line_offset + pos { buffer.putc(p, code_offset + annotation.start_col, '|', @@ -634,7 +634,7 @@ impl EmitterWriter { } } AnnotationType::MultilineEnd(depth) => { - for p in line_offset..line_offset + pos + 1 { + for p in line_offset..=line_offset + pos { buffer.putc(p, width_offset + depth - 1, '|', @@ -1044,7 +1044,7 @@ impl EmitterWriter { buffer.append(buffer_msg_line_offset, &format!("{}:{}:{}", loc.file.name, - sm.doctest_offset_line(loc.line), + sm.doctest_offset_line(&loc.file.name, loc.line), loc.col.0 + 1), Style::LineAndColumn); for _ in 0..max_line_num_len { @@ -1054,7 +1054,7 @@ impl EmitterWriter { buffer.prepend(0, &format!("{}:{}:{}: ", loc.file.name, - sm.doctest_offset_line(loc.line), + sm.doctest_offset_line(&loc.file.name, loc.line), loc.col.0 + 1), Style::LineAndColumn); } @@ -1075,7 +1075,8 @@ impl EmitterWriter { }; format!("{}:{}{}", annotated_file.file.name, - sm.doctest_offset_line(first_line.line_index), + sm.doctest_offset_line( + &annotated_file.file.name, first_line.line_index), col) } else { annotated_file.file.name.to_string() @@ -1261,7 +1262,7 @@ impl EmitterWriter { // Do not underline the leading... let start = part.snippet.len() - .saturating_sub(part.snippet.trim_left().len()); + .saturating_sub(part.snippet.trim_start().len()); // ...or trailing spaces. Account for substitutions containing unicode // characters. let sub_len = part.snippet.trim().chars().fold(0, |acc, ch| { diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 0fb77a7a3ab..b6528cbe2c8 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -130,7 +130,7 @@ pub trait SourceMapper { fn merge_spans(&self, sp_lhs: Span, sp_rhs: Span) -> Option; fn call_span_if_macro(&self, sp: Span) -> Span; fn ensure_source_file_source_present(&self, source_file: Lrc) -> bool; - fn doctest_offset_line(&self, line: usize) -> usize; + fn doctest_offset_line(&self, file: &FileName, line: usize) -> usize; } impl CodeSuggestion { diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs index 22a0cc983da..15c0dbabd0c 100644 --- a/src/librustc_incremental/assert_dep_graph.rs +++ b/src/librustc_incremental/assert_dep_graph.rs @@ -79,8 +79,8 @@ pub fn assert_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let mut visitor = IfThisChanged { tcx, if_this_changed: vec![], then_this_would_need: vec![] }; - visitor.process_attrs(ast::CRATE_NODE_ID, &tcx.hir.krate().attrs); - tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor()); + visitor.process_attrs(ast::CRATE_NODE_ID, &tcx.hir().krate().attrs); + tcx.hir().krate().visit_all_item_likes(&mut visitor.as_deep_visitor()); (visitor.if_this_changed, visitor.then_this_would_need) }; @@ -121,7 +121,7 @@ impl<'a, 'tcx> IfThisChanged<'a, 'tcx> { } fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) { - let def_id = self.tcx.hir.local_def_id(node_id); + let def_id = self.tcx.hir().local_def_id(node_id); let def_path_hash = self.tcx.def_path_hash(def_id); for attr in attrs { if attr.check_name(ATTR_IF_THIS_CHANGED) { @@ -170,7 +170,7 @@ impl<'a, 'tcx> IfThisChanged<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for IfThisChanged<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir) + NestedVisitorMap::OnlyBodies(&self.tcx.hir()) } fn visit_item(&mut self, item: &'tcx hir::Item) { diff --git a/src/librustc_incremental/assert_module_sources.rs b/src/librustc_incremental/assert_module_sources.rs index 4ff2529b26d..8c562ff24fd 100644 --- a/src/librustc_incremental/assert_module_sources.rs +++ b/src/librustc_incremental/assert_module_sources.rs @@ -40,9 +40,9 @@ use syntax::ast; use rustc::ich::{ATTR_PARTITION_REUSED, ATTR_PARTITION_CODEGENED, ATTR_EXPECTED_CGU_REUSE}; -const MODULE: &'static str = "module"; -const CFG: &'static str = "cfg"; -const KIND: &'static str = "kind"; +const MODULE: &str = "module"; +const CFG: &str = "cfg"; +const KIND: &str = "kind"; pub fn assert_module_sources<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { tcx.dep_graph.with_ignore(|| { @@ -62,7 +62,7 @@ pub fn assert_module_sources<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { available_cgus }; - for attr in &tcx.hir.krate().attrs { + for attr in &tcx.hir().krate().attrs { ams.check_attr(attr); } }) diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index f76086139ed..e17663c41e5 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -78,7 +78,7 @@ const BASE_IMPL: &[&str] = &[ ]; /// DepNodes for MirValidated/Optimized, which is relevant in "executable" -/// code, i.e. functions+methods +/// code, i.e., functions+methods const BASE_MIR: &[&str] = &[ label_strs::MirOptimized, label_strs::MirValidated, @@ -223,7 +223,7 @@ pub fn check_dirty_clean_annotations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { } tcx.dep_graph.with_ignore(|| { - let krate = tcx.hir.krate(); + let krate = tcx.hir().krate(); let mut dirty_clean_visitor = DirtyCleanVisitor { tcx, checked_attrs: Default::default(), @@ -333,7 +333,7 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { /// Return all DepNode labels that should be asserted for this item. /// index=0 is the "name" used for error messages fn auto_labels(&mut self, item_id: ast::NodeId, attr: &Attribute) -> (&'static str, Labels) { - let node = self.tcx.hir.get(item_id); + let node = self.tcx.hir().get(item_id); let (name, labels) = match node { HirNode::Item(item) => { match item.node { @@ -364,16 +364,16 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { // Module-level inline assembly (from global_asm!) HirItem::GlobalAsm(..) => ("ItemGlobalAsm", LABELS_HIR_ONLY), - // A type alias, e.g. `type Foo = Bar` + // A type alias, e.g., `type Foo = Bar` HirItem::Ty(..) => ("ItemTy", LABELS_HIR_ONLY), - // An enum definition, e.g. `enum Foo {C, D}` + // An enum definition, e.g., `enum Foo {C, D}` HirItem::Enum(..) => ("ItemEnum", LABELS_ADT), - // A struct definition, e.g. `struct Foo {x: A}` + // A struct definition, e.g., `struct Foo {x: A}` HirItem::Struct(..) => ("ItemStruct", LABELS_ADT), - // A union definition, e.g. `union Foo {x: A, y: B}` + // A union definition, e.g., `union Foo {x: A, y: B}` HirItem::Union(..) => ("ItemUnion", LABELS_ADT), // Represents a Trait Declaration @@ -511,7 +511,7 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { } fn check_item(&mut self, item_id: ast::NodeId, item_span: Span) { - let def_id = self.tcx.hir.local_def_id(item_id); + let def_id = self.tcx.hir().local_def_id(item_id); for attr in self.tcx.get_attrs(def_id).iter() { let assertion = match self.assertion_maybe(item_id, attr) { Some(a) => a, @@ -630,7 +630,7 @@ impl<'a, 'tcx> FindAllAttrs<'a, 'tcx> { impl<'a, 'tcx> intravisit::Visitor<'tcx> for FindAllAttrs<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> { - intravisit::NestedVisitorMap::All(&self.tcx.hir) + intravisit::NestedVisitorMap::All(&self.tcx.hir()) } fn visit_attribute(&mut self, attr: &'tcx Attribute) { diff --git a/src/librustc_incremental/persist/file_format.rs b/src/librustc_incremental/persist/file_format.rs index 98f7873fda0..e5faba61782 100644 --- a/src/librustc_incremental/persist/file_format.rs +++ b/src/librustc_incremental/persist/file_format.rs @@ -28,7 +28,7 @@ use rustc::session::config::nightly_options; use rustc_serialize::opaque::Encoder; /// The first few bytes of files generated by incremental compilation -const FILE_MAGIC: &'static [u8] = b"RSIC"; +const FILE_MAGIC: &[u8] = b"RSIC"; /// Change this if the header format changes const HEADER_FORMAT_VERSION: u16 = 0; @@ -36,7 +36,7 @@ const HEADER_FORMAT_VERSION: u16 = 0; /// A version string that hopefully is always different for compiler versions /// with different encodings of incremental compilation artifacts. Contains /// the git commit hash. -const RUSTC_VERSION: Option<&'static str> = option_env!("CFG_VERSION"); +const RUSTC_VERSION: Option<&str> = option_env!("CFG_VERSION"); pub fn write_file_header(stream: &mut Encoder) { stream.emit_raw_bytes(FILE_MAGIC); diff --git a/src/librustc_incremental/persist/fs.rs b/src/librustc_incremental/persist/fs.rs index 75cdefaf49f..11ce10fd4a7 100644 --- a/src/librustc_incremental/persist/fs.rs +++ b/src/librustc_incremental/persist/fs.rs @@ -128,10 +128,10 @@ use std::time::{UNIX_EPOCH, SystemTime, Duration}; use rand::{RngCore, thread_rng}; -const LOCK_FILE_EXT: &'static str = ".lock"; -const DEP_GRAPH_FILENAME: &'static str = "dep-graph.bin"; -const WORK_PRODUCTS_FILENAME: &'static str = "work-products.bin"; -const QUERY_CACHE_FILENAME: &'static str = "query-cache.bin"; +const LOCK_FILE_EXT: &str = ".lock"; +const DEP_GRAPH_FILENAME: &str = "dep-graph.bin"; +const WORK_PRODUCTS_FILENAME: &str = "work-products.bin"; +const QUERY_CACHE_FILENAME: &str = "query-cache.bin"; // We encode integers using the following base, so they are shorter than decimal // or hexadecimal numbers (we want short file and directory names). Since these @@ -354,7 +354,7 @@ pub fn finalize_session_directory(sess: &Session, svh: Svh) { } // State: "s-{timestamp}-{random-number}-" - let mut new_sub_dir_name = String::from(&old_sub_dir_name[.. dash_indices[2] + 1]); + let mut new_sub_dir_name = String::from(&old_sub_dir_name[..= dash_indices[2]]); // Append the svh base_n::push_str(svh.as_u64() as u128, INT_ENCODE_BASE, &mut new_sub_dir_name); diff --git a/src/librustc_incremental/persist/work_product.rs b/src/librustc_incremental/persist/work_product.rs index cfe59b1f672..ddd28eb5393 100644 --- a/src/librustc_incremental/persist/work_product.rs +++ b/src/librustc_incremental/persist/work_product.rs @@ -29,7 +29,7 @@ pub fn copy_cgu_workproducts_to_incr_comp_cache_dir( return None } - let saved_files: Option> = + let saved_files = files.iter() .map(|&(kind, ref path)| { let extension = match kind { @@ -51,11 +51,7 @@ pub fn copy_cgu_workproducts_to_incr_comp_cache_dir( } } }) - .collect(); - let saved_files = match saved_files { - None => return None, - Some(v) => v, - }; + .collect::>>()?; let work_product = WorkProduct { cgu_name: cgu_name.to_string(), diff --git a/src/librustc_lint/Cargo.toml b/src/librustc_lint/Cargo.toml index fe197e3e2e2..7fb7a06ea1a 100644 --- a/src/librustc_lint/Cargo.toml +++ b/src/librustc_lint/Cargo.toml @@ -12,7 +12,6 @@ test = false [dependencies] log = "0.4" rustc = { path = "../librustc" } -rustc_mir = { path = "../librustc_mir"} rustc_target = { path = "../librustc_target" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 7dd1ca3493e..7dd5d3c1cbc 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -131,7 +131,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoxPointers { hir::ItemKind::Enum(..) | hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => { - let def_id = cx.tcx.hir.local_def_id(it.id); + let def_id = cx.tcx.hir().local_def_id(it.id); self.check_heap_type(cx, it.span, cx.tcx.type_of(def_id)) } _ => () @@ -142,7 +142,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoxPointers { hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => { for struct_field in struct_def.fields() { - let def_id = cx.tcx.hir.local_def_id(struct_field.id); + let def_id = cx.tcx.hir().local_def_id(struct_field.id); self.check_heap_type(cx, struct_field.span, cx.tcx.type_of(def_id)); } @@ -424,8 +424,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { // If the trait is private, add the impl items to private_traits so they don't get // reported for missing docs. let real_trait = trait_ref.path.def.def_id(); - if let Some(node_id) = cx.tcx.hir.as_local_node_id(real_trait) { - match cx.tcx.hir.find(node_id) { + if let Some(node_id) = cx.tcx.hir().as_local_node_id(real_trait) { + match cx.tcx.hir().find(node_id) { Some(Node::Item(item)) => { if let hir::VisibilityKind::Inherited = item.vis.node { for impl_item_ref in impl_item_refs { @@ -527,21 +527,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingCopyImplementations { if !ast_generics.params.is_empty() { return; } - let def = cx.tcx.adt_def(cx.tcx.hir.local_def_id(item.id)); + let def = cx.tcx.adt_def(cx.tcx.hir().local_def_id(item.id)); (def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[]))) } hir::ItemKind::Union(_, ref ast_generics) => { if !ast_generics.params.is_empty() { return; } - let def = cx.tcx.adt_def(cx.tcx.hir.local_def_id(item.id)); + let def = cx.tcx.adt_def(cx.tcx.hir().local_def_id(item.id)); (def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[]))) } hir::ItemKind::Enum(_, ref ast_generics) => { if !ast_generics.params.is_empty() { return; } - let def = cx.tcx.adt_def(cx.tcx.hir.local_def_id(item.id)); + let def = cx.tcx.adt_def(cx.tcx.hir().local_def_id(item.id)); (def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[]))) } _ => return, @@ -606,7 +606,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDebugImplementations { let mut impls = NodeSet::default(); cx.tcx.for_each_impl(debug, |d| { if let Some(ty_def) = cx.tcx.type_of(d).ty_adt_def() { - if let Some(node_id) = cx.tcx.hir.as_local_node_id(ty_def.did) { + if let Some(node_id) = cx.tcx.hir().as_local_node_id(ty_def.did) { impls.insert(node_id); } } @@ -871,7 +871,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PluginAsLibrary { _ => return, }; - let def_id = cx.tcx.hir.local_def_id(it.id); + let def_id = cx.tcx.hir().local_def_id(it.id); let prfn = match cx.tcx.extern_mod_stmt_cnum(def_id) { Some(cnum) => cx.tcx.plugin_registrar_fn(cnum), None => { @@ -1073,7 +1073,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnionsWithDropFields { fn check_item(&mut self, ctx: &LateContext, item: &hir::Item) { if let hir::ItemKind::Union(ref vdata, _) = item.node { for field in vdata.fields() { - let field_ty = ctx.tcx.type_of(ctx.tcx.hir.local_def_id(field.id)); + let field_ty = ctx.tcx.type_of(ctx.tcx.hir().local_def_id(field.id)); if field_ty.needs_drop(ctx.tcx, ctx.param_env) { ctx.span_lint(UNIONS_WITH_DROP_FIELDS, field.span, @@ -1275,7 +1275,7 @@ impl LintPass for UnusedBrokenConst { } } fn check_const(cx: &LateContext, body_id: hir::BodyId) { - let def_id = cx.tcx.hir.body_owner_def_id(body_id); + let def_id = cx.tcx.hir().body_owner_def_id(body_id); let is_static = cx.tcx.is_static(def_id).is_some(); let param_env = if is_static { // Use the same param_env as `codegen_static_initializer`, to reuse the cache. @@ -1332,7 +1332,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TrivialConstraints { if cx.tcx.features().trivial_bounds { - let def_id = cx.tcx.hir.local_def_id(item.id); + let def_id = cx.tcx.hir().local_def_id(item.id); let predicates = cx.tcx.predicates_of(def_id); for &(predicate, span) in &predicates.predicates { let predicate_kind_name = match predicate { @@ -1540,8 +1540,8 @@ impl KeywordIdents { } _ => {}, } - TokenTree::Delimited(_, ref delim) => { - self.check_tokens(cx, delim.tts.clone().into()) + TokenTree::Delimited(_, _, tts) => { + self.check_tokens(cx, tts.stream()) }, } } @@ -1573,7 +1573,7 @@ impl EarlyLintPass for KeywordIdents { } } - // no new keywords yet for 2018 edition and beyond + // There are no new keywords yet for the 2018 edition and beyond. // However, `await` is a "false" keyword in the 2018 edition, // and can only be used if the `async_await` feature is enabled. // Otherwise, we emit an error. @@ -1746,7 +1746,7 @@ impl ExplicitOutlivesRequirements { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExplicitOutlivesRequirements { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item) { let infer_static = cx.tcx.features().infer_static_outlives_requirements; - let def_id = cx.tcx.hir.local_def_id(item.id); + let def_id = cx.tcx.hir().local_def_id(item.id); if let hir::ItemKind::Struct(_, ref generics) = item.node { let mut bound_count = 0; let mut lint_spans = Vec::new(); diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 71efc5654ef..9dbc9cbc43b 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -8,14 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Lints in the Rust compiler. +//! # Lints in the Rust compiler //! //! This currently only contains the definitions and implementations //! of most of the lints that `rustc` supports directly, it does not //! contain the infrastructure for defining/registering lints. That is //! available in `rustc::lint` and `rustc_plugin` respectively. //! -//! # Note +//! ## Note //! //! This API is completely unstable and subject to change. @@ -36,11 +36,16 @@ extern crate syntax; extern crate rustc; #[macro_use] extern crate log; -extern crate rustc_mir; extern crate rustc_target; extern crate syntax_pos; extern crate rustc_data_structures; +mod diagnostics; +mod nonstandard_style; +pub mod builtin; +mod types; +mod unused; + use rustc::lint; use rustc::lint::{LateContext, LateLintPass, LintPass, LintArray}; use rustc::lint::builtin::{ @@ -48,6 +53,9 @@ use rustc::lint::builtin::{ ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, ELIDED_LIFETIMES_IN_PATHS, EXPLICIT_OUTLIVES_REQUIREMENTS, + INTRA_DOC_LINK_RESOLUTION_FAILURE, + MISSING_DOC_CODE_EXAMPLES, + PRIVATE_DOC_TESTS, parser::QUESTION_MARK_MACRO_SEP }; use rustc::session; @@ -55,19 +63,13 @@ use rustc::util; use rustc::hir; use syntax::ast; +use syntax::edition::Edition; use syntax_pos::Span; use session::Session; -use syntax::edition::Edition; use lint::LintId; use lint::FutureIncompatibleInfo; -mod diagnostics; -mod nonstandard_style; -pub mod builtin; -mod types; -mod unused; - use nonstandard_style::*; use builtin::*; use types::*; @@ -205,6 +207,12 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { // MACRO_USE_EXTERN_CRATE, ); + add_lint_group!(sess, + "rustdoc", + INTRA_DOC_LINK_RESOLUTION_FAILURE, + MISSING_DOC_CODE_EXAMPLES, + PRIVATE_DOC_TESTS); + // Guidelines for creating a future incompatibility lint: // // - Create a lint defaulting to warn as normal, with ideally the same error @@ -213,8 +221,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { // and include the full URL, sort items in ascending order of issue numbers. // - Later, change lint to error // - Eventually, remove lint - store.register_future_incompatible(sess, - vec![ + store.register_future_incompatible(sess, vec![ FutureIncompatibleInfo { id: LintId::of(PRIVATE_IN_PUBLIC), reference: "issue #34537 ", @@ -295,6 +302,11 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { reference: "issue #46205 ", edition: None, }, + FutureIncompatibleInfo { + id: LintId::of(ORDER_DEPENDENT_TRAIT_OBJECTS), + reference: "issue #56484 ", + edition: None, + }, FutureIncompatibleInfo { id: LintId::of(TYVAR_BEHIND_RAW_POINTER), reference: "issue #46906 ", @@ -334,7 +346,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { }, ]); - // Register renamed and removed lints + // Register renamed and removed lints. store.register_renamed("single_use_lifetime", "single_use_lifetimes"); store.register_renamed("elided_lifetime_in_path", "elided_lifetimes_in_paths"); store.register_renamed("bare_trait_object", "bare_trait_objects"); @@ -345,10 +357,10 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { store.register_removed("unsigned_negation", "replaced by negate_unsigned feature gate"); store.register_removed("negate_unsigned", "cast a signed value instead"); store.register_removed("raw_pointer_derive", "using derive with raw pointers is ok"); - // Register lint group aliases + // Register lint group aliases. store.register_group_alias("nonstandard_style", "bad_style"); - // This was renamed to raw_pointer_derive, which was then removed, - // so it is also considered removed + // This was renamed to `raw_pointer_derive`, which was then removed, + // so it is also considered removed. store.register_removed("raw_pointer_deriving", "using derive with raw pointers is ok"); store.register_removed("drop_with_repr_extern", "drop flags have been removed"); store.register_removed("fat_ptr_transmutes", "was accidentally removed back in 2014"); @@ -378,7 +390,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { store.register_removed("resolve_trait_on_defaulted_unit", "converted into hard error, see https://github.com/rust-lang/rust/issues/48950"); store.register_removed("private_no_mangle_fns", - "no longer an warning, #[no_mangle] functions always exported"); + "no longer a warning, #[no_mangle] functions always exported"); store.register_removed("private_no_mangle_statics", - "no longer an warning, #[no_mangle] statics always exported"); + "no longer a warning, #[no_mangle] statics always exported"); } diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs index 40781b0771d..e071c34ff7f 100644 --- a/src/librustc_lint/nonstandard_style.rs +++ b/src/librustc_lint/nonstandard_style.rs @@ -8,19 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use rustc::hir::{self, GenericParamKind, PatKind}; use rustc::hir::def::Def; +use rustc::hir::intravisit::FnKind; use rustc::ty; +use rustc_target::spec::abi::Abi; use lint::{LateContext, LintContext, LintArray}; use lint::{LintPass, LateLintPass}; - -use rustc_target::spec::abi::Abi; use syntax::ast; use syntax::attr; use syntax_pos::Span; -use rustc::hir::{self, GenericParamKind, PatKind}; -use rustc::hir::intravisit::FnKind; - #[derive(PartialEq)] pub enum MethodLateContext { TraitAutoImpl, @@ -29,7 +27,7 @@ pub enum MethodLateContext { } pub fn method_context(cx: &LateContext, id: ast::NodeId) -> MethodLateContext { - let def_id = cx.tcx.hir.local_def_id(id); + let def_id = cx.tcx.hir().local_def_id(id); let item = cx.tcx.associated_item(def_id); match item.container { ty::TraitContainer(..) => MethodLateContext::TraitAutoImpl, @@ -169,7 +167,7 @@ impl NonSnakeCase { fn to_snake_case(mut str: &str) -> String { let mut words = vec![]; // Preserve leading underscores - str = str.trim_left_matches(|c: char| { + str = str.trim_start_matches(|c: char| { if c == '_' { words.push(String::new()); true @@ -201,7 +199,7 @@ impl NonSnakeCase { if ident.is_empty() { return true; } - let ident = ident.trim_left_matches('\''); + let ident = ident.trim_start_matches('\''); let ident = ident.trim_matches('_'); let mut allow_underscore = true; diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 82ace620c8a..e225e642e72 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -139,8 +139,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { _ => bug!(), }; if lit_val < min || lit_val > max { - let parent_id = cx.tcx.hir.get_parent_node(e.id); - if let Node::Expr(parent_expr) = cx.tcx.hir.get(parent_id) { + let parent_id = cx.tcx.hir().get_parent_node(e.id); + if let Node::Expr(parent_expr) = cx.tcx.hir().get(parent_id) { if let hir::ExprKind::Cast(..) = parent_expr.node { if let ty::Char = cx.tables.expr_ty(parent_expr).sty { let mut err = cx.struct_span_lint( @@ -756,7 +756,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { diag.help(s); } if let ty::Adt(def, _) = unsafe_ty.sty { - if let Some(sp) = self.cx.tcx.hir.span_if_local(def.did) { + if let Some(sp) = self.cx.tcx.hir().span_if_local(def.did) { diag.span_note(sp, "type defined here"); } } @@ -766,7 +766,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } fn check_foreign_fn(&mut self, id: ast::NodeId, decl: &hir::FnDecl) { - let def_id = self.cx.tcx.hir.local_def_id(id); + let def_id = self.cx.tcx.hir().local_def_id(id); let sig = self.cx.tcx.fn_sig(def_id); let sig = self.cx.tcx.erase_late_bound_regions(&sig); @@ -783,7 +783,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } fn check_foreign_static(&mut self, id: ast::NodeId, span: Span) { - let def_id = self.cx.tcx.hir.local_def_id(id); + let def_id = self.cx.tcx.hir().local_def_id(id); let ty = self.cx.tcx.type_of(def_id); self.check_type_for_ffi_and_report_errors(span, ty); } @@ -801,7 +801,7 @@ impl LintPass for ImproperCTypes { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImproperCTypes { fn check_foreign_item(&mut self, cx: &LateContext, it: &hir::ForeignItem) { let mut vis = ImproperCTypesVisitor { cx }; - let abi = cx.tcx.hir.get_foreign_abi(it.id); + let abi = cx.tcx.hir().get_foreign_abi(it.id); if abi != Abi::RustIntrinsic && abi != Abi::PlatformIntrinsic { match it.node { hir::ForeignItemKind::Fn(ref decl, _, _) => { @@ -827,7 +827,7 @@ impl LintPass for VariantSizeDifferences { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences { fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { if let hir::ItemKind::Enum(ref enum_definition, _) = it.node { - let item_def_id = cx.tcx.hir.local_def_id(it.id); + let item_def_id = cx.tcx.hir().local_def_id(it.id); let t = cx.tcx.type_of(item_def_id); let ty = cx.tcx.erase_regions(&t); match cx.layout_of(ty) { diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index fab618d9c8e..d3e1af70c21 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -61,7 +61,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { let t = cx.tables.expr_ty(&expr); let type_permits_lack_of_use = if t.is_unit() - || cx.tcx.is_ty_uninhabited_from(cx.tcx.hir.get_module_parent(expr.id), t) { + || cx.tcx.is_ty_uninhabited_from(cx.tcx.hir().get_module_parent(expr.id), t) { true } else { match t.sty { @@ -473,7 +473,7 @@ impl UnusedImportBraces { match items[0].0.kind { ast::UseTreeKind::Simple(rename, ..) => { let orig_ident = items[0].0.prefix.segments.last().unwrap().ident; - if orig_ident.name == keywords::SelfValue.name() { + if orig_ident.name == keywords::SelfLower.name() { return; } node_ident = rename.unwrap_or(orig_ident); diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index 7d01ed556c8..ce482087bba 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -192,11 +192,11 @@ fn main() { // On MSVC llvm-config will print the full name to libraries, but // we're only interested in the name part let name = Path::new(lib).file_name().unwrap().to_str().unwrap(); - name.trim_right_matches(".lib") + name.trim_end_matches(".lib") } else if lib.ends_with(".lib") { // Some MSVC libraries just come up with `.lib` tacked on, so chop // that off - lib.trim_right_matches(".lib") + lib.trim_end_matches(".lib") } else { continue; }; diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 1c48d844739..10f35e5598b 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -22,7 +22,7 @@ extern crate rustc_cratesio_shim; // NOTE: This crate only exists to allow linking on mingw targets. /// Initialize targets enabled by the build script via `cfg(llvm_component = "...")`. -/// NB: this function can't be moved to `rustc_codegen_llvm` because of the `cfg`s. +/// N.B., this function can't be moved to `rustc_codegen_llvm` because of the `cfg`s. pub fn initialize_available_targets() { macro_rules! init_target( ($cfg:meta, $($method:ident),*) => { { diff --git a/src/librustc_lsan/Cargo.toml b/src/librustc_lsan/Cargo.toml index 2573825a5ff..a8e11df7670 100644 --- a/src/librustc_lsan/Cargo.toml +++ b/src/librustc_lsan/Cargo.toml @@ -16,4 +16,4 @@ cmake = "0.1.18" [dependencies] alloc = { path = "../liballoc" } core = { path = "../libcore" } -compiler_builtins = { path = "../rustc/compiler_builtins_shim" } +compiler_builtins = "0.1.0" diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 2be9883d03d..f650db5aafa 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -56,7 +56,7 @@ pub struct CrateMetadata { /// Original name of the crate. pub name: Symbol, - /// Name of the crate as imported. I.e. if imported with + /// Name of the crate as imported. I.e., if imported with /// `extern crate foo as bar;` this will be `bar`. pub imported_name: Symbol, diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index d0fa63a6163..da2ba392c5e 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -307,7 +307,7 @@ pub fn provide<'tcx>(providers: &mut Providers<'tcx>) { Lrc::new(link_args::collect(tcx)) }, - // Returns a map from a sufficiently visible external item (i.e. an + // Returns a map from a sufficiently visible external item (i.e., an // external item that is visible from at least one local module) to a // sufficiently visible parent (considering modules that re-export the // external item to be parents). diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 2736c60ffb6..feed70c6122 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -318,7 +318,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } fn encode_info_for_items(&mut self) -> Index { - let krate = self.tcx.hir.krate(); + let krate = self.tcx.hir().krate(); let mut index = IndexBuilder::new(self); let vis = Spanned { span: syntax_pos::DUMMY_SP, node: hir::VisibilityKind::Public }; index.record(DefId::local(CRATE_DEF_INDEX), @@ -333,7 +333,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } fn encode_def_path_table(&mut self) -> Lazy { - let definitions = self.tcx.hir.definitions(); + let definitions = self.tcx.hir().definitions(); self.lazy(definitions.def_path_table()) } @@ -475,7 +475,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let index = items.write_index(&mut self.opaque); let index_bytes = self.position() - i; - let attrs = tcx.hir.krate_attrs(); + let attrs = tcx.hir().krate_attrs(); let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro); let has_default_lib_allocator = attr::contains_name(&attrs, "default_lib_allocator"); let has_global_allocator = *tcx.sess.has_global_allocator.get(); @@ -495,10 +495,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { plugin_registrar_fn: tcx.sess .plugin_registrar_fn .get() - .map(|id| tcx.hir.local_def_id(id).index), + .map(|id| tcx.hir().local_def_id(id).index), proc_macro_decls_static: if is_proc_macro { let id = tcx.sess.proc_macro_decls_static.get().unwrap(); - Some(tcx.hir.local_def_id(id).index) + Some(tcx.hir().local_def_id(id).index) } else { None }, @@ -600,8 +600,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } }; - let enum_id = tcx.hir.as_local_node_id(enum_did).unwrap(); - let enum_vis = &tcx.hir.expect_item(enum_id).vis; + let enum_id = tcx.hir().as_local_node_id(enum_did).unwrap(); + let enum_vis = &tcx.hir().expect_item(enum_id).vis; Entry { kind: EntryKind::Variant(self.lazy(&data)), @@ -636,7 +636,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { &hir::Visibility)>) -> Entry<'tcx> { let tcx = self.tcx; - let def_id = tcx.hir.local_def_id(id); + let def_id = tcx.hir().local_def_id(id); debug!("IsolatedEncoder::encode_info_for_mod({:?})", def_id); let data = ModData { @@ -652,7 +652,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { span: self.lazy(&tcx.def_span(def_id)), attributes: self.encode_attributes(attrs), children: self.lazy_seq(md.item_ids.iter().map(|item_id| { - tcx.hir.local_def_id(item_id.id).index + tcx.hir().local_def_id(item_id.id).index })), stability: self.encode_stability(def_id), deprecation: self.encode_deprecation(def_id), @@ -686,8 +686,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { let def_id = field.did; debug!("IsolatedEncoder::encode_field({:?})", def_id); - let variant_id = tcx.hir.as_local_node_id(variant.did).unwrap(); - let variant_data = tcx.hir.expect_variant_data(variant_id); + let variant_id = tcx.hir().as_local_node_id(variant.did).unwrap(); + let variant_data = tcx.hir().expect_variant_data(variant_id); Entry { kind: EntryKind::Field, @@ -726,8 +726,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } }; - let struct_id = tcx.hir.as_local_node_id(adt_def_id).unwrap(); - let struct_vis = &tcx.hir.expect_item(struct_id).vis; + let struct_id = tcx.hir().as_local_node_id(adt_def_id).unwrap(); + let struct_vis = &tcx.hir().expect_item(struct_id).vis; let mut ctor_vis = ty::Visibility::from_hir(struct_vis, struct_id, tcx); for field in &variant.fields { if ctor_vis.is_at_least(field.vis, tcx) { @@ -791,8 +791,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { debug!("IsolatedEncoder::encode_info_for_trait_item({:?})", def_id); let tcx = self.tcx; - let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); - let ast_item = tcx.hir.expect_trait_item(node_id); + let node_id = tcx.hir().as_local_node_id(def_id).unwrap(); + let ast_item = tcx.hir().expect_trait_item(node_id); let trait_item = tcx.associated_item(def_id); let container = match trait_item.defaultness { @@ -814,7 +814,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { }; let rendered = - hir::print::to_string(&self.tcx.hir, |s| s.print_trait_item(ast_item)); + hir::print::to_string(self.tcx.hir(), |s| s.print_trait_item(ast_item)); let rendered_const = self.lazy(&RenderedConst(rendered)); EntryKind::AssociatedConst(container, const_qualif, rendered_const) @@ -891,7 +891,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } fn const_qualif(&self, mir: u8, body_id: hir::BodyId) -> ConstQualif { - let body_owner_def_id = self.tcx.hir.body_owner_def_id(body_id); + let body_owner_def_id = self.tcx.hir().body_owner_def_id(body_id); let ast_promotable = self.tcx.const_is_rvalue_promotable_to_static(body_owner_def_id); ConstQualif { mir, ast_promotable } @@ -901,8 +901,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { debug!("IsolatedEncoder::encode_info_for_impl_item({:?})", def_id); let tcx = self.tcx; - let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap(); - let ast_item = self.tcx.hir.expect_impl_item(node_id); + let node_id = self.tcx.hir().as_local_node_id(def_id).unwrap(); + let ast_item = self.tcx.hir().expect_impl_item(node_id); let impl_item = self.tcx.associated_item(def_id); let container = match impl_item.defaultness { @@ -987,7 +987,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { fn encode_fn_arg_names_for_body(&mut self, body_id: hir::BodyId) -> LazySeq { self.tcx.dep_graph.with_ignore(|| { - let body = self.tcx.hir.body(body_id); + let body = self.tcx.hir().body(body_id); self.lazy_seq(body.arguments.iter().map(|arg| { match arg.pat.node { PatKind::Binding(_, _, ident, _) => ident.name, @@ -1036,8 +1036,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } fn encode_rendered_const_for_body(&mut self, body_id: hir::BodyId) -> Lazy { - let body = self.tcx.hir.body(body_id); - let rendered = hir::print::to_string(&self.tcx.hir, |s| s.print_expr(&body.value)); + let body = self.tcx.hir().body(body_id); + let rendered = hir::print::to_string(self.tcx.hir(), |s| s.print_expr(&body.value)); let rendered_const = &RenderedConst(rendered); self.lazy(rendered_const) } @@ -1081,7 +1081,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { // for methods, write all the stuff get_trait_method // needs to know let struct_ctor = if !struct_def.is_struct() { - Some(tcx.hir.local_def_id(struct_def.id()).index) + Some(tcx.hir().local_def_id(struct_def.id()).index) } else { None }; @@ -1141,7 +1141,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { EntryKind::Impl(self.lazy(&data)) } - hir::ItemKind::Trait(..) => { + hir::ItemKind::Trait(..) | + hir::ItemKind::TraitAlias(..) => { let trait_def = tcx.trait_def(def_id); let data = TraitData { unsafety: trait_def.unsafety, @@ -1154,7 +1155,6 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { EntryKind::Trait(self.lazy(&data)) } hir::ItemKind::ExternCrate(_) | - hir::ItemKind::TraitAlias(..) | hir::ItemKind::Use(..) => bug!("cannot encode info for item {:?}", item), }; @@ -1167,7 +1167,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { hir::ItemKind::ForeignMod(ref fm) => { self.lazy_seq(fm.items .iter() - .map(|foreign_item| tcx.hir.local_def_id(foreign_item.id).index)) + .map(|foreign_item| tcx.hir().local_def_id(foreign_item.id).index)) } hir::ItemKind::Enum(..) => { let def = self.tcx.adt_def(def_id); @@ -1282,7 +1282,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { /// Serialize the text of exported macros fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef) -> Entry<'tcx> { use syntax::print::pprust; - let def_id = self.tcx.hir.local_def_id(macro_def.id); + let def_id = self.tcx.hir().local_def_id(macro_def.id); Entry { kind: EntryKind::MacroDef(self.lazy(&MacroDef { body: pprust::tts_to_string(¯o_def.body.trees().collect::>()), @@ -1339,8 +1339,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { let tcx = self.tcx; let tables = self.tcx.typeck_tables_of(def_id); - let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap(); - let hir_id = self.tcx.hir.node_to_hir_id(node_id); + let node_id = self.tcx.hir().as_local_node_id(def_id).unwrap(); + let hir_id = self.tcx.hir().node_to_hir_id(node_id); let kind = match tables.node_id_to_type(hir_id).sty { ty::Generator(def_id, ..) => { let layout = self.tcx.generator_layout(def_id); @@ -1382,8 +1382,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { fn encode_info_for_anon_const(&mut self, def_id: DefId) -> Entry<'tcx> { debug!("IsolatedEncoder::encode_info_for_anon_const({:?})", def_id); let tcx = self.tcx; - let id = tcx.hir.as_local_node_id(def_id).unwrap(); - let body_id = tcx.hir.body_owned_by(id); + let id = tcx.hir().as_local_node_id(def_id).unwrap(); + let body_id = tcx.hir().body_owned_by(id); let const_data = self.encode_rendered_const_for_body(body_id); let mir = tcx.mir_const_qualif(def_id).0; @@ -1491,7 +1491,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { tcx, impls: FxHashMap::default(), }; - tcx.hir.krate().visit_all_item_likes(&mut visitor); + tcx.hir().krate().visit_all_item_likes(&mut visitor); let mut all_impls: Vec<_> = visitor.impls.into_iter().collect(); @@ -1505,7 +1505,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { .map(|(trait_def_id, mut impls)| { // Bring everything into deterministic order for hashing impls.sort_by_cached_key(|&def_index| { - tcx.hir.definitions().def_path_hash(def_index) + tcx.hir().definitions().def_path_hash(def_index) }); TraitImpls { @@ -1617,7 +1617,7 @@ struct EncodeVisitor<'a, 'b: 'a, 'tcx: 'b> { impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.index.tcx.hir) + NestedVisitorMap::OnlyBodies(&self.index.tcx.hir()) } fn visit_expr(&mut self, ex: &'tcx hir::Expr) { intravisit::walk_expr(self, ex); @@ -1625,7 +1625,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> { } fn visit_item(&mut self, item: &'tcx hir::Item) { intravisit::walk_item(self, item); - let def_id = self.index.tcx.hir.local_def_id(item.id); + let def_id = self.index.tcx.hir().local_def_id(item.id); match item.node { hir::ItemKind::ExternCrate(_) | hir::ItemKind::Use(..) => (), // ignore these @@ -1635,7 +1635,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> { } fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem) { intravisit::walk_foreign_item(self, ni); - let def_id = self.index.tcx.hir.local_def_id(ni.id); + let def_id = self.index.tcx.hir().local_def_id(ni.id); self.index.record(def_id, IsolatedEncoder::encode_info_for_foreign_item, (def_id, ni)); @@ -1647,7 +1647,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> { intravisit::walk_variant(self, v, g, id); if let Some(ref discr) = v.node.disr_expr { - let def_id = self.index.tcx.hir.local_def_id(discr.id); + let def_id = self.index.tcx.hir().local_def_id(discr.id); self.index.record(def_id, IsolatedEncoder::encode_info_for_anon_const, def_id); } } @@ -1660,7 +1660,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> { self.index.encode_info_for_ty(ty); } fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef) { - let def_id = self.index.tcx.hir.local_def_id(macro_def.id); + let def_id = self.index.tcx.hir().local_def_id(macro_def.id); self.index.record(def_id, IsolatedEncoder::encode_info_for_macro_def, macro_def); } } @@ -1682,7 +1682,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { match param.kind { hir::GenericParamKind::Lifetime { .. } => {} hir::GenericParamKind::Type { ref default, .. } => { - let def_id = self.tcx.hir.local_def_id(param.id); + let def_id = self.tcx.hir().local_def_id(param.id); let has_default = Untracked(default.is_some()); let encode_info = IsolatedEncoder::encode_info_for_ty_param; self.record(def_id, encode_info, (def_id, has_default)); @@ -1694,7 +1694,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { fn encode_info_for_ty(&mut self, ty: &hir::Ty) { match ty.node { hir::TyKind::Array(_, ref length) => { - let def_id = self.tcx.hir.local_def_id(length.id); + let def_id = self.tcx.hir().local_def_id(length.id); self.record(def_id, IsolatedEncoder::encode_info_for_anon_const, def_id); } _ => {} @@ -1704,7 +1704,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { fn encode_info_for_expr(&mut self, expr: &hir::Expr) { match expr.node { hir::ExprKind::Closure(..) => { - let def_id = self.tcx.hir.local_def_id(expr.id); + let def_id = self.tcx.hir().local_def_id(expr.id); self.record(def_id, IsolatedEncoder::encode_info_for_closure, def_id); } _ => {} @@ -1716,7 +1716,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { /// so it's easier to do that here then to wait until we would encounter /// normally in the visitor walk. fn encode_addl_info_for_item(&mut self, item: &hir::Item) { - let def_id = self.tcx.hir.local_def_id(item.id); + let def_id = self.tcx.hir().local_def_id(item.id); match item.node { hir::ItemKind::Static(..) | hir::ItemKind::Const(..) | @@ -1746,7 +1746,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { // If the struct has a constructor, encode it. if !struct_def.is_struct() { - let ctor_def_id = self.tcx.hir.local_def_id(struct_def.id()); + let ctor_def_id = self.tcx.hir().local_def_id(struct_def.id()); self.record(ctor_def_id, IsolatedEncoder::encode_struct_ctor, (def_id, ctor_def_id)); @@ -1781,7 +1781,7 @@ struct ImplVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'a, 'tcx> { fn visit_item(&mut self, item: &hir::Item) { if let hir::ItemKind::Impl(..) = item.node { - let impl_id = self.tcx.hir.local_def_id(item.id); + let impl_id = self.tcx.hir().local_def_id(item.id); if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_id) { self.impls .entry(trait_ref.def_id) diff --git a/src/librustc_metadata/foreign_modules.rs b/src/librustc_metadata/foreign_modules.rs index e96d56fb388..5b2002f2a96 100644 --- a/src/librustc_metadata/foreign_modules.rs +++ b/src/librustc_metadata/foreign_modules.rs @@ -18,7 +18,7 @@ pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Vec { tcx, modules: Vec::new(), }; - tcx.hir.krate().visit_all_item_likes(&mut collector); + tcx.hir().krate().visit_all_item_likes(&mut collector); return collector.modules } @@ -35,11 +35,11 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for Collector<'a, 'tcx> { }; let foreign_items = fm.items.iter() - .map(|it| self.tcx.hir.local_def_id(it.id)) + .map(|it| self.tcx.hir().local_def_id(it.id)) .collect(); self.modules.push(ForeignModule { foreign_items, - def_id: self.tcx.hir.local_def_id(it.id), + def_id: self.tcx.hir().local_def_id(it.id), }); } diff --git a/src/librustc_metadata/index_builder.rs b/src/librustc_metadata/index_builder.rs index fd2c2237c32..aea3ac1be81 100644 --- a/src/librustc_metadata/index_builder.rs +++ b/src/librustc_metadata/index_builder.rs @@ -90,7 +90,7 @@ impl<'a, 'b, 'tcx> DerefMut for IndexBuilder<'a, 'b, 'tcx> { impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { pub fn new(ecx: &'a mut EncodeContext<'b, 'tcx>) -> Self { IndexBuilder { - items: Index::new(ecx.tcx.hir.definitions().def_index_counts_lo_hi()), + items: Index::new(ecx.tcx.hir().definitions().def_index_counts_lo_hi()), ecx, } } @@ -195,7 +195,7 @@ macro_rules! read_hir { ($t:ty) => { impl<'tcx> DepGraphRead for &'tcx $t { fn read(&self, tcx: TyCtxt) { - tcx.hir.read(self.id); + tcx.hir().read(self.id); } } } @@ -229,6 +229,6 @@ pub struct FromId(pub ast::NodeId, pub T); impl DepGraphRead for FromId { fn read(&self, tcx: TyCtxt) { - tcx.hir.read(self.0); + tcx.hir().read(self.0); } } diff --git a/src/librustc_metadata/link_args.rs b/src/librustc_metadata/link_args.rs index 008e1e363ff..decd85c507e 100644 --- a/src/librustc_metadata/link_args.rs +++ b/src/librustc_metadata/link_args.rs @@ -17,9 +17,9 @@ pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Vec { let mut collector = Collector { args: Vec::new(), }; - tcx.hir.krate().visit_all_item_likes(&mut collector); + tcx.hir().krate().visit_all_item_likes(&mut collector); - for attr in tcx.hir.krate().attrs.iter() { + for attr in tcx.hir().krate().attrs.iter() { if attr.path == "link_args" { if let Some(linkarg) = attr.value_str() { collector.add_link_args(&linkarg.as_str()); diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index d4e51693d7e..f01ed9e3cee 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -661,7 +661,7 @@ impl<'a> Context<'a> { // Ok so at this point we've determined that `(lib, kind)` above is // a candidate crate to load, and that `slot` is either none (this // is the first crate of its kind) or if some the previous path has - // the exact same hash (e.g. it's the exact same crate). + // the exact same hash (e.g., it's the exact same crate). // // In principle these two candidate crates are exactly the same so // we can choose either of them to link. As a stupidly gross hack, @@ -678,7 +678,7 @@ impl<'a> Context<'a> { // candidates are all canonicalized, so we canonicalize the sysroot // as well. if let Some((ref prev, _)) = ret { - let sysroot = self.sess.sysroot(); + let sysroot = &self.sess.sysroot; let sysroot = sysroot.canonicalize() .unwrap_or_else(|_| sysroot.to_path_buf()); if prev.starts_with(&sysroot) { diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs index 392644c793d..6f85418b297 100644 --- a/src/librustc_metadata/native_libs.rs +++ b/src/librustc_metadata/native_libs.rs @@ -25,7 +25,7 @@ pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Vec { tcx, libs: Vec::new(), }; - tcx.hir.krate().visit_all_item_likes(&mut collector); + tcx.hir().krate().visit_all_item_likes(&mut collector); collector.process_command_line(); return collector.libs } @@ -65,7 +65,7 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for Collector<'a, 'tcx> { name: None, kind: cstore::NativeUnknown, cfg: None, - foreign_module: Some(self.tcx.hir.local_def_id(it.id)), + foreign_module: Some(self.tcx.hir().local_def_id(it.id)), wasm_import_module: None, }; let mut kind_specified = false; diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index e91d15b78c0..1ae3f0a12bd 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -40,7 +40,7 @@ pub fn rustc_version() -> String { } /// Metadata encoding version. -/// NB: increment this if you change the format of metadata such that +/// N.B., increment this if you change the format of metadata such that /// the rustc version can't be found to compare with `rustc_version()`. pub const METADATA_VERSION: u8 = 4; @@ -52,7 +52,7 @@ pub const METADATA_VERSION: u8 = 4; /// This header is followed by the position of the `CrateRoot`, /// which is encoded as a 32-bit big-endian unsigned integer, /// and further followed by the rustc version string. -pub const METADATA_HEADER: &'static [u8; 12] = +pub const METADATA_HEADER: &[u8; 12] = &[0, 0, 0, 0, b'r', b'u', b's', b't', 0, 0, 0, METADATA_VERSION]; /// A value of type T referred to by its absolute position diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml index 2da0ede9d15..5044e351962 100644 --- a/src/librustc_mir/Cargo.toml +++ b/src/librustc_mir/Cargo.toml @@ -25,4 +25,4 @@ syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } byteorder = { version = "1.1", features = ["i128"] } rustc_apfloat = { path = "../librustc_apfloat" } -smallvec = { version = "0.6.5", features = ["union"] } +smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs index fd7dc7fc4bd..947c32df0f6 100644 --- a/src/librustc_mir/borrow_check/borrow_set.rs +++ b/src/librustc_mir/borrow_check/borrow_set.rs @@ -16,7 +16,7 @@ use rustc::mir::traversal; use rustc::mir::visit::{ PlaceContext, Visitor, NonUseContext, MutatingUseContext, NonMutatingUseContext }; -use rustc::mir::{self, Location, Mir, Place, Local}; +use rustc::mir::{self, Location, Mir, Local}; use rustc::ty::{RegionVid, TyCtxt}; use rustc::util::nodemap::{FxHashMap, FxHashSet}; use rustc_data_structures::indexed_vec::IndexVec; @@ -41,10 +41,6 @@ crate struct BorrowSet<'tcx> { /// only need to store one borrow index crate activation_map: FxHashMap>, - /// Every borrow has a region; this maps each such regions back to - /// its borrow-indexes. - crate region_map: FxHashMap>, - /// Map from local to all the borrows on that local crate local_map: FxHashMap>, @@ -149,7 +145,6 @@ impl<'tcx> BorrowSet<'tcx> { idx_vec: IndexVec::new(), location_map: Default::default(), activation_map: Default::default(), - region_map: Default::default(), local_map: Default::default(), pending_activations: Default::default(), locals_state_at_exit: @@ -164,7 +159,6 @@ impl<'tcx> BorrowSet<'tcx> { borrows: visitor.idx_vec, location_map: visitor.location_map, activation_map: visitor.activation_map, - region_map: visitor.region_map, local_map: visitor.local_map, locals_state_at_exit: visitor.locals_state_at_exit, } @@ -184,7 +178,6 @@ struct GatherBorrows<'a, 'gcx: 'tcx, 'tcx: 'a> { idx_vec: IndexVec>, location_map: FxHashMap, activation_map: FxHashMap>, - region_map: FxHashMap>, local_map: FxHashMap>, /// When we encounter a 2-phase borrow statement, it will always @@ -229,7 +222,6 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> { self.insert_as_pending_if_two_phase(location, &assigned_place, kind, idx); - self.region_map.entry(region).or_default().insert(idx); if let Some(local) = borrowed_place.root_local() { self.local_map.entry(local).or_default().insert(idx); } @@ -238,68 +230,68 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> { self.super_assign(block, assigned_place, rvalue, location) } - fn visit_place( + fn visit_local( &mut self, - place: &mir::Place<'tcx>, + temp: &Local, context: PlaceContext<'tcx>, location: Location, ) { - self.super_place(place, context, location); + if !context.is_use() { + return; + } - // We found a use of some temporary TEMP... - if let Place::Local(temp) = place { - // ... check whether we (earlier) saw a 2-phase borrow like - // - // TMP = &mut place - if let Some(&borrow_index) = self.pending_activations.get(temp) { - let borrow_data = &mut self.idx_vec[borrow_index]; + // We found a use of some temporary TMP + // check whether we (earlier) saw a 2-phase borrow like + // + // TMP = &mut place + if let Some(&borrow_index) = self.pending_activations.get(temp) { + let borrow_data = &mut self.idx_vec[borrow_index]; - // Watch out: the use of TMP in the borrow itself - // doesn't count as an activation. =) - if borrow_data.reserve_location == location && - context == PlaceContext::MutatingUse(MutatingUseContext::Store) - { - return; - } - - if let TwoPhaseActivation::ActivatedAt(other_location) = - borrow_data.activation_location { - span_bug!( - self.mir.source_info(location).span, - "found two uses for 2-phase borrow temporary {:?}: \ - {:?} and {:?}", - temp, - location, - other_location, - ); - } - - // Otherwise, this is the unique later use - // that we expect. - borrow_data.activation_location = match context { - // The use of TMP in a shared borrow does not - // count as an actual activation. - PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow(..)) | - PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow(..)) => - TwoPhaseActivation::NotActivated, - _ => { - // Double check: This borrow is indeed a two-phase borrow (that is, - // we are 'transitioning' from `NotActivated` to `ActivatedAt`) and - // we've not found any other activations (checked above). - assert_eq!( - borrow_data.activation_location, - TwoPhaseActivation::NotActivated, - "never found an activation for this borrow!", - ); - - self.activation_map - .entry(location) - .or_default() - .push(borrow_index); - TwoPhaseActivation::ActivatedAt(location) - } - }; + // Watch out: the use of TMP in the borrow itself + // doesn't count as an activation. =) + if borrow_data.reserve_location == location && + context == PlaceContext::MutatingUse(MutatingUseContext::Store) + { + return; } + + if let TwoPhaseActivation::ActivatedAt(other_location) = + borrow_data.activation_location { + span_bug!( + self.mir.source_info(location).span, + "found two uses for 2-phase borrow temporary {:?}: \ + {:?} and {:?}", + temp, + location, + other_location, + ); + } + + // Otherwise, this is the unique later use + // that we expect. + borrow_data.activation_location = match context { + // The use of TMP in a shared borrow does not + // count as an actual activation. + PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow(..)) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow(..)) => + TwoPhaseActivation::NotActivated, + _ => { + // Double check: This borrow is indeed a two-phase borrow (that is, + // we are 'transitioning' from `NotActivated` to `ActivatedAt`) and + // we've not found any other activations (checked above). + assert_eq!( + borrow_data.activation_location, + TwoPhaseActivation::NotActivated, + "never found an activation for this borrow!", + ); + + self.activation_map + .entry(location) + .or_default() + .push(borrow_index); + TwoPhaseActivation::ActivatedAt(location) + } + }; } } diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 4ccd26bee8b..598c2f810be 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -195,8 +195,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let needs_note = match ty.sty { ty::Closure(id, _) => { let tables = self.infcx.tcx.typeck_tables_of(id); - let node_id = self.infcx.tcx.hir.as_local_node_id(id).unwrap(); - let hir_id = self.infcx.tcx.hir.node_to_hir_id(node_id); + let node_id = self.infcx.tcx.hir().as_local_node_id(id).unwrap(); + let hir_id = self.infcx.tcx.hir().node_to_hir_id(node_id); tables.closure_kind_origins().get(hir_id).is_none() } @@ -344,6 +344,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let first_borrow_desc; + let explanation = self.explain_why_borrow_contains_point(context, issued_borrow, None); + let second_borrow_desc = if explanation.is_explained() { + "second " + } else { + "" + }; + // FIXME: supply non-"" `opt_via` when appropriate let mut err = match ( gen_borrow_kind, @@ -454,6 +461,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { issued_span, "", None, + second_borrow_desc, Origin::Mir, ) } @@ -469,6 +477,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { issued_span, "", None, + second_borrow_desc, Origin::Mir, ) } @@ -513,7 +522,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ); } - self.explain_why_borrow_contains_point(context, issued_borrow, None) + explanation .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, first_borrow_desc); err.buffer(&mut self.errors_buffer); @@ -711,13 +720,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { format!("`{}` would have to be valid for `{}`...", name, region_name), ); - if let Some(fn_node_id) = self.infcx.tcx.hir.as_local_node_id(self.mir_def_id) { + if let Some(fn_node_id) = self.infcx.tcx.hir().as_local_node_id(self.mir_def_id) { err.span_label( drop_span, format!( "...but `{}` will be dropped here, when the function `{}` returns", name, - self.infcx.tcx.hir.name(fn_node_id), + self.infcx.tcx.hir().name(fn_node_id), ), ); @@ -1055,7 +1064,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let escapes_from = if tcx.is_closure(self.mir_def_id) { let tables = tcx.typeck_tables_of(self.mir_def_id); - let mir_hir_id = tcx.hir.def_index_to_hir_id(self.mir_def_id.index); + let mir_hir_id = tcx.hir().def_index_to_hir_id(self.mir_def_id.index); match tables.node_id_to_type(mir_hir_id).sty { ty::Closure(..) => "closure", ty::Generator(..) => "generator", @@ -1240,7 +1249,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { /// (part of) a non-`mut` local that occurs potentially after that /// local has already been initialized. `place` is the path being /// assigned; `err_place` is a place providing a reason why - /// `place` is not mutable (e.g. the non-`mut` local `x` in an + /// `place` is not mutable (e.g., the non-`mut` local `x` in an /// assignment to `x.f`). pub(super) fn report_illegal_reassignment( &mut self, @@ -1403,11 +1412,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ); if let ty::TyKind::Closure(did, _substs) = self.mir.local_decls[closure].ty.sty { - let node_id = match self.infcx.tcx.hir.as_local_node_id(did) { + let node_id = match self.infcx.tcx.hir().as_local_node_id(did) { Some(node_id) => node_id, _ => return, }; - let hir_id = self.infcx.tcx.hir.node_to_hir_id(node_id); + let hir_id = self.infcx.tcx.hir().node_to_hir_id(node_id); if let Some(( span, name @@ -1645,12 +1654,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // the local code in the current crate, so this returns an `Option` in case // the closure comes from another crate. But in that case we wouldn't // be borrowck'ing it, so we can just unwrap: - let node_id = self.infcx.tcx.hir.as_local_node_id(def_id).unwrap(); + let node_id = self.infcx.tcx.hir().as_local_node_id(def_id).unwrap(); let freevar = self.infcx .tcx .with_freevars(node_id, |fv| fv[field.index()]); - self.infcx.tcx.hir.name(freevar.var_id()).to_string() + self.infcx.tcx.hir().name(freevar.var_id()).to_string() } _ => { // Might need a revision when the fields in trait RFC is implemented @@ -1971,8 +1980,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ) -> Option { debug!("annotate_fn_sig: did={:?} sig={:?}", did, sig); let is_closure = self.infcx.tcx.is_closure(did); - let fn_node_id = self.infcx.tcx.hir.as_local_node_id(did)?; - let fn_decl = self.infcx.tcx.hir.fn_decl(fn_node_id)?; + let fn_node_id = self.infcx.tcx.hir().as_local_node_id(did)?; + let fn_decl = self.infcx.tcx.hir().fn_decl(fn_node_id)?; // We need to work out which arguments to highlight. We do this by looking // at the return type, where there are three cases: @@ -2414,8 +2423,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { "closure_span: def_id={:?} target_place={:?} places={:?}", def_id, target_place, places ); - let node_id = self.infcx.tcx.hir.as_local_node_id(def_id)?; - let expr = &self.infcx.tcx.hir.expect_expr(node_id).node; + let node_id = self.infcx.tcx.hir().as_local_node_id(def_id)?; + let expr = &self.infcx.tcx.hir().expect_expr(node_id).node; debug!("closure_span: node_id={:?} expr={:?}", node_id, expr); if let hir::ExprKind::Closure( .., args_span, _ diff --git a/src/librustc_mir/borrow_check/flows.rs b/src/librustc_mir/borrow_check/flows.rs index 16bb1ef78dc..8a58cb05680 100644 --- a/src/librustc_mir/borrow_check/flows.rs +++ b/src/librustc_mir/borrow_check/flows.rs @@ -33,9 +33,9 @@ use std::rc::Rc; // (forced to be `pub` due to its use as an associated type below.) crate struct Flows<'b, 'gcx: 'tcx, 'tcx: 'b> { - borrows: FlowAtLocation>, - pub uninits: FlowAtLocation>, - pub ever_inits: FlowAtLocation>, + borrows: FlowAtLocation<'tcx, Borrows<'b, 'gcx, 'tcx>>, + pub uninits: FlowAtLocation<'tcx, MaybeUninitializedPlaces<'b, 'gcx, 'tcx>>, + pub ever_inits: FlowAtLocation<'tcx, EverInitializedPlaces<'b, 'gcx, 'tcx>>, /// Polonius Output pub polonius_output: Option>>, @@ -43,9 +43,9 @@ crate struct Flows<'b, 'gcx: 'tcx, 'tcx: 'b> { impl<'b, 'gcx, 'tcx> Flows<'b, 'gcx, 'tcx> { crate fn new( - borrows: FlowAtLocation>, - uninits: FlowAtLocation>, - ever_inits: FlowAtLocation>, + borrows: FlowAtLocation<'tcx, Borrows<'b, 'gcx, 'tcx>>, + uninits: FlowAtLocation<'tcx, MaybeUninitializedPlaces<'b, 'gcx, 'tcx>>, + ever_inits: FlowAtLocation<'tcx, EverInitializedPlaces<'b, 'gcx, 'tcx>>, polonius_output: Option>>, ) -> Self { Flows { diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 76ba6ae5de6..f49e8d89c5a 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -63,7 +63,7 @@ mod move_errors; mod mutability_errors; mod path_utils; crate mod place_ext; -mod places_conflict; +crate mod places_conflict; mod prefixes; mod used_muts; @@ -137,7 +137,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( let attributes = tcx.get_attrs(def_id); let param_env = tcx.param_env(def_id); let id = tcx - .hir + .hir() .as_local_node_id(def_id) .expect("do_mir_borrowck: non-local DefId"); @@ -173,7 +173,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]), )); - let locals_are_invalidated_at_exit = match tcx.hir.body_owner_kind(id) { + let locals_are_invalidated_at_exit = match tcx.hir().body_owner_kind(id) { hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => false, hir::BodyOwnerKind::Fn => true, }; @@ -229,7 +229,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( |bd, i| DebugFormatted::new(&bd.move_data().inits[i]), )); - let movable_generator = match tcx.hir.get(id) { + let movable_generator = match tcx.hir().get(id) { Node::Expr(&hir::Expr { node: hir::ExprKind::Closure(.., Some(hir::GeneratorMovability::Static)), .. @@ -373,10 +373,14 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( for err in &mut mbcx.errors_buffer { if err.is_error() { err.level = Level::Warning; - err.warn("This error has been downgraded to a warning \ - for backwards compatibility with previous releases.\n\ - It represents potential unsoundness in your code.\n\ - This warning will become a hard error in the future."); + err.warn( + "this error has been downgraded to a warning for backwards \ + compatibility with previous releases", + ); + err.warn( + "this represents potential undefined behavior in your code and \ + this warning will become a hard error in the future", + ); } } } @@ -545,7 +549,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx self.mutate_place( ContextKind::SetDiscrim.new(location), (place, span), - Shallow(Some(ArtificialField::Discriminant)), + Shallow(None), JustWrite, flow_state, ); @@ -590,7 +594,6 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx StatementKind::Nop | StatementKind::AscribeUserType(..) | StatementKind::Retag { .. } - | StatementKind::EscapeToRaw { .. } | StatementKind::StorageLive(..) => { // `Nop`, `AscribeUserType`, `Retag`, and `StorageLive` are irrelevant // to borrow check. @@ -782,7 +785,6 @@ use self::AccessDepth::{Deep, Shallow}; #[derive(Copy, Clone, PartialEq, Eq, Debug)] enum ArtificialField { - Discriminant, ArrayLength, ShallowBorrow, } @@ -1191,14 +1193,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Rvalue::Len(ref place) | Rvalue::Discriminant(ref place) => { let af = match *rvalue { - Rvalue::Len(..) => ArtificialField::ArrayLength, - Rvalue::Discriminant(..) => ArtificialField::Discriminant, + Rvalue::Len(..) => Some(ArtificialField::ArrayLength), + Rvalue::Discriminant(..) => None, _ => unreachable!(), }; self.access_place( context, (place, span), - (Shallow(Some(af)), Read(ReadKind::Copy)), + (Shallow(af), Read(ReadKind::Copy)), LocalMutationIsAllowed::No, flow_state, ); @@ -1370,7 +1372,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { place, borrow.kind, root_place, - sd + sd, + places_conflict::PlaceConflictBias::Overlap, ) { debug!("check_for_invalidation_at_exit({:?}): INVALID", place); // FIXME: should be talking about the region lifetime instead @@ -1526,7 +1529,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // ancestors; dataflow recurs on children when parents // move (to support partial (re)inits). // - // (I.e. querying parents breaks scenario 7; but may want + // (I.e., querying parents breaks scenario 7; but may want // to do such a query based on partial-init feature-gate.) } } @@ -1562,7 +1565,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // // (Distinct from handling of scenarios 1+2+4 above because // `place` does not interfere with suffixes of its prefixes, - // e.g. `a.b.c` does not interfere with `a.b.d`) + // e.g., `a.b.c` does not interfere with `a.b.d`) // // This code covers scenario 1. @@ -1735,7 +1738,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // // This does not use check_if_path_or_subpath_is_moved, // because we want to *allow* reinitializations of fields: - // e.g. want to allow + // e.g., want to allow // // `let mut s = ...; drop(s.x); s.x=Val;` // @@ -2166,7 +2169,7 @@ enum Overlap { /// `u.a.x` and `a.b.y` are. Arbitrary, /// The places have the same type, and are either completely disjoint - /// or equal - i.e. they can't "partially" overlap as can occur with + /// or equal - i.e., they can't "partially" overlap as can occur with /// unions. This is the "base case" on which we recur for extensions /// of the place. EqualOrDisjoint, diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs index a556199b875..fb93c41ce4f 100644 --- a/src/librustc_mir/borrow_check/move_errors.rs +++ b/src/librustc_mir/borrow_check/move_errors.rs @@ -40,7 +40,7 @@ use util::borrowck_errors::{BorrowckErrors, Origin}; #[derive(Debug)] enum GroupedMoveError<'tcx> { // Place expression can't be moved from, - // e.g. match x[0] { s => (), } where x: &[String] + // e.g., match x[0] { s => (), } where x: &[String] MovesFromPlace { original_path: Place<'tcx>, span: Span, @@ -49,7 +49,7 @@ enum GroupedMoveError<'tcx> { binds_to: Vec, }, // Part of a value expression can't be moved from, - // e.g. match &String::new() { &x => (), } + // e.g., match &String::new() { &x => (), } MovesFromValue { original_path: Place<'tcx>, span: Span, @@ -319,8 +319,8 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { let upvar_hir_id = upvar_decl.var_hir_id.assert_crate_local(); let upvar_node_id = - self.infcx.tcx.hir.hir_to_node_id(upvar_hir_id); - let upvar_span = self.infcx.tcx.hir.span(upvar_node_id); + self.infcx.tcx.hir().hir_to_node_id(upvar_hir_id); + let upvar_span = self.infcx.tcx.hir().span(upvar_node_id); diag.span_label(upvar_span, "captured outer variable"); break; } @@ -426,13 +426,13 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { .span_to_snippet(pat_span) .unwrap(); if pat_snippet.starts_with('&') { - let pat_snippet = pat_snippet[1..].trim_left(); + let pat_snippet = pat_snippet[1..].trim_start(); let suggestion; let to_remove; if pat_snippet.starts_with("mut") && pat_snippet["mut".len()..].starts_with(Pattern_White_Space) { - suggestion = pat_snippet["mut".len()..].trim_left(); + suggestion = pat_snippet["mut".len()..].trim_start(); to_remove = "&mut"; } else { suggestion = pat_snippet; diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index 7afe2c67adc..ab819aafc47 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -263,7 +263,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { // Deliberately fall into this case for all implicit self types, // so that we don't fall in to the next case with them. *kind == mir::ImplicitSelfKind::MutRef - } else if Some(keywords::SelfValue.name()) == local_decl.name { + } else if Some(keywords::SelfLower.name()) == local_decl.name { // Otherwise, check if the name is the self kewyord - in which case // we have an explicit self. Do the same thing in this case and check // for a `self: &mut Self` to suggest removing the `&mut`. @@ -317,8 +317,8 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { let upvar_hir_id = self.mir.upvar_decls[upvar_index.index()] .var_hir_id .assert_crate_local(); - let upvar_node_id = self.infcx.tcx.hir.hir_to_node_id(upvar_hir_id); - if let Some(Node::Binding(pat)) = self.infcx.tcx.hir.find(upvar_node_id) { + let upvar_node_id = self.infcx.tcx.hir().hir_to_node_id(upvar_hir_id); + if let Some(Node::Binding(pat)) = self.infcx.tcx.hir().find(upvar_node_id) { if let hir::PatKind::Binding( hir::BindingAnnotation::Unannotated, _, @@ -641,8 +641,8 @@ fn annotate_struct_field( if let ty::TyKind::Adt(def, _) = ty.sty { let field = def.all_fields().nth(field.index())?; // Use the HIR types to construct the diagnostic message. - let node_id = tcx.hir.as_local_node_id(field.did)?; - let node = tcx.hir.find(node_id)?; + let node_id = tcx.hir().as_local_node_id(field.did)?; + let node = tcx.hir().find(node_id)?; // Now we're dealing with the actual struct that we're going to suggest a change to, // we can expect a field that is an immutable reference to a type. if let hir::Node::Field(field) = node { diff --git a/src/librustc_mir/borrow_check/nll/constraints/mod.rs b/src/librustc_mir/borrow_check/nll/constraints/mod.rs index a873af8333a..bfac33b34c7 100644 --- a/src/librustc_mir/borrow_check/nll/constraints/mod.rs +++ b/src/librustc_mir/borrow_check/nll/constraints/mod.rs @@ -40,7 +40,7 @@ impl ConstraintSet { /// Constructs a "normal" graph from the constraint set; the graph makes it /// easy to find the constraints affecting a particular region. /// - /// NB: This graph contains a "frozen" view of the current + /// N.B., this graph contains a "frozen" view of the current /// constraints. any new constraints added to the `ConstraintSet` /// after the graph is built will not be present in the graph. crate fn graph(&self, num_region_vars: usize) -> graph::NormalConstraintGraph { diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index bb9a29b055b..7fb3f02e0e3 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -52,6 +52,12 @@ pub(in borrow_check) enum LaterUseKind { } impl BorrowExplanation { + pub(in borrow_check) fn is_explained(&self) -> bool { + match self { + BorrowExplanation::Unexplained => false, + _ => true, + } + } pub(in borrow_check) fn add_explanation_to_diagnostic<'cx, 'gcx, 'tcx>( &self, tcx: TyCtxt<'cx, 'gcx, 'tcx>, @@ -271,13 +277,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { borrow_region_vid, region, ); - let opt_place_desc = self.describe_place(&borrow.borrowed_place); - BorrowExplanation::MustBeValidFor { - category, - from_closure, - span, - region_name, - opt_place_desc, + if let Some(region_name) = region_name { + let opt_place_desc = self.describe_place(&borrow.borrowed_place); + BorrowExplanation::MustBeValidFor { + category, + from_closure, + span, + region_name, + opt_place_desc, + } + } else { + BorrowExplanation::Unexplained } } else { BorrowExplanation::Unexplained diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs index 8af23a8813a..d2810de284a 100644 --- a/src/librustc_mir/borrow_check/nll/invalidation.rs +++ b/src/librustc_mir/borrow_check/nll/invalidation.rs @@ -99,7 +99,7 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> { self.mutate_place( ContextKind::SetDiscrim.new(location), place, - Shallow(Some(ArtificialField::Discriminant)), + Shallow(None), JustWrite, ); } @@ -135,7 +135,6 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> { StatementKind::Nop | StatementKind::AscribeUserType(..) | StatementKind::Retag { .. } | - StatementKind::EscapeToRaw { .. } | StatementKind::StorageLive(..) => { // `Nop`, `AscribeUserType`, `Retag`, and `StorageLive` are irrelevant // to borrow check. @@ -360,14 +359,14 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cx, 'tcx, 'gcx> { Rvalue::Len(ref place) | Rvalue::Discriminant(ref place) => { let af = match *rvalue { - Rvalue::Len(..) => ArtificialField::ArrayLength, - Rvalue::Discriminant(..) => ArtificialField::Discriminant, + Rvalue::Len(..) => Some(ArtificialField::ArrayLength), + Rvalue::Discriminant(..) => None, _ => unreachable!(), }; self.access_place( context, place, - (Shallow(Some(af)), Read(ReadKind::Copy)), + (Shallow(af), Read(ReadKind::Copy)), LocalMutationIsAllowed::No, ); } diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index 0c4140caee8..1e3a27c8fe5 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -85,7 +85,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>( mir: &Mir<'tcx>, location_table: &LocationTable, param_env: ty::ParamEnv<'gcx>, - flow_inits: &mut FlowAtLocation>, + flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'cx, 'gcx, 'tcx>>, move_data: &MoveData<'tcx>, borrow_set: &BorrowSet<'tcx>, errors_buffer: &mut Vec, @@ -176,7 +176,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>( // Dump facts if requested. let polonius_output = all_facts.and_then(|all_facts| { if infcx.tcx.sess.opts.debugging_opts.nll_facts { - let def_path = infcx.tcx.hir.def_path(def_id); + let def_path = infcx.tcx.hir().def_path(def_id); let dir_path = PathBuf::from("nll-facts").join(def_path.to_filename_friendly_no_crate()); all_facts.write_to_dir(dir_path, location_table).unwrap(); 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 3358e5851f9..32aaa0590d2 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 @@ -38,6 +38,7 @@ impl ConstraintDescription for ConstraintCategory { match self { ConstraintCategory::Assignment => "assignment ", ConstraintCategory::Return => "returning this value ", + ConstraintCategory::Yield => "yielding this value ", ConstraintCategory::UseAsConst => "using this value as a constant ", ConstraintCategory::UseAsStatic => "using this value as a static ", ConstraintCategory::Cast => "cast ", @@ -133,11 +134,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { let constraint_sup_scc = self.constraint_sccs.scc(constraint.sup); match categorized_path[i].0 { - ConstraintCategory::OpaqueType - | ConstraintCategory::Boring - | ConstraintCategory::BoringNoLocation - | ConstraintCategory::Internal => false, - ConstraintCategory::TypeAnnotation | ConstraintCategory::Return => true, + ConstraintCategory::OpaqueType | ConstraintCategory::Boring | + ConstraintCategory::BoringNoLocation | ConstraintCategory::Internal => false, + ConstraintCategory::TypeAnnotation | ConstraintCategory::Return | + ConstraintCategory::Yield => true, _ => constraint_sup_scc != target_scc, } }); @@ -376,9 +376,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { diag.span_label(span, message); - match self.give_region_a_name(infcx, mir, mir_def_id, outlived_fr, &mut 1) - .source - { + match self.give_region_a_name(infcx, mir, mir_def_id, outlived_fr, &mut 1).unwrap().source { RegionNameSource::NamedEarlyBoundRegion(fr_span) | RegionNameSource::NamedFreeRegion(fr_span) | RegionNameSource::SynthesizedFreeEnvRegion(fr_span, _) @@ -521,10 +519,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { ); let counter = &mut 1; - let fr_name = self.give_region_a_name(infcx, mir, mir_def_id, fr, counter); + let fr_name = self.give_region_a_name(infcx, mir, mir_def_id, fr, counter).unwrap(); fr_name.highlight_region_name(&mut diag); let outlived_fr_name = - self.give_region_a_name(infcx, mir, mir_def_id, outlived_fr, counter); + self.give_region_a_name(infcx, mir, mir_def_id, outlived_fr, counter).unwrap(); outlived_fr_name.highlight_region_name(&mut diag); let mir_def_name = if infcx.tcx.is_closure(mir_def_id) { @@ -661,7 +659,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { infcx: &InferCtxt<'_, '_, 'tcx>, borrow_region: RegionVid, outlived_region: RegionVid, - ) -> (ConstraintCategory, bool, Span, RegionName) { + ) -> (ConstraintCategory, bool, Span, Option) { let (category, from_closure, span) = self.best_blame_constraint(mir, borrow_region, |r| r == outlived_region); let outlived_fr_name = 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 a32fb0503a8..a41d27e8ff1 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 @@ -157,7 +157,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { mir_def_id: DefId, fr: RegionVid, counter: &mut usize, - ) -> RegionName { + ) -> Option { debug!("give_region_a_name(fr={:?}, counter={})", fr, counter); assert!(self.universal_regions.is_universal_region(fr)); @@ -177,8 +177,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.give_name_if_anonymous_region_appears_in_output( infcx, mir, mir_def_id, fr, counter, ) - }) - .unwrap_or_else(|| span_bug!(mir.span, "can't make a name for free region {:?}", fr)); + }); debug!("give_region_a_name: gave name {:?}", value); value @@ -226,12 +225,14 @@ impl<'tcx> RegionInferenceContext<'tcx> { }, ty::BoundRegion::BrEnv => { - let mir_node_id = tcx.hir.as_local_node_id(mir_def_id).expect("non-local mir"); + let mir_node_id = tcx.hir() + .as_local_node_id(mir_def_id) + .expect("non-local mir"); let def_ty = self.universal_regions.defining_ty; if let DefiningTy::Closure(def_id, substs) = def_ty { let args_span = if let hir::ExprKind::Closure(_, _, _, span, _) = - tcx.hir.expect_expr(mir_node_id).node + tcx.hir().expect_expr(mir_node_id).node { span } else { @@ -302,10 +303,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { name: &InternedString, ) -> 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 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 + 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)) { @@ -361,8 +362,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { argument_index: usize, counter: &mut usize, ) -> 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 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]; match argument_hir_ty.node { // This indicates a variable with no type annotation, like @@ -685,9 +686,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { let type_name = with_highlight_region_for_regionvid( fr, *counter, || infcx.extract_type_name(&return_ty)); - let mir_node_id = tcx.hir.as_local_node_id(mir_def_id).expect("non-local mir"); + let mir_node_id = tcx.hir().as_local_node_id(mir_def_id).expect("non-local mir"); - let (return_span, mir_description) = match tcx.hir.get(mir_node_id) { + let (return_span, mir_description) = match tcx.hir().get(mir_node_id) { hir::Node::Expr(hir::Expr { node: hir::ExprKind::Closure(_, _, _, span, gen_move), .. diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/var_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/var_name.rs index 73fa1b0cfb7..0c0504b7b31 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/var_name.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/var_name.rs @@ -81,11 +81,11 @@ impl<'tcx> RegionInferenceContext<'tcx> { upvar_index: usize, ) -> (Symbol, Span) { let upvar_hir_id = mir.upvar_decls[upvar_index].var_hir_id.assert_crate_local(); - let upvar_node_id = tcx.hir.hir_to_node_id(upvar_hir_id); + let upvar_node_id = tcx.hir().hir_to_node_id(upvar_hir_id); debug!("get_upvar_name_and_span_for_region: upvar_node_id={:?}", upvar_node_id); - let upvar_name = tcx.hir.name(upvar_node_id); - let upvar_span = tcx.hir.span(upvar_node_id); + let upvar_name = tcx.hir().name(upvar_node_id); + let upvar_span = tcx.hir().span(upvar_node_id); debug!("get_upvar_name_and_span_for_region: upvar_name={:?} upvar_span={:?}", upvar_name, upvar_span); @@ -95,7 +95,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// Search the argument types for one that references fr (which should be a free region). /// Returns Some(_) with the index of the input if one is found. /// - /// NB: In the case of a closure, the index is indexing into the signature as seen by the + /// N.B., in the case of a closure, the index is indexing into the signature as seen by the /// user - in particular, index 0 is not the implicit self parameter. crate fn get_argument_index_for_region( &self, 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 fbde699264b..cbd1e666284 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs @@ -119,7 +119,7 @@ struct RegionDefinition<'tcx> { external_name: Option>, } -/// NB: The variants in `Cause` are intentionally ordered. Lower +/// N.B., the variants in `Cause` are intentionally ordered. Lower /// values are preferred when it comes to error messages. Do not /// reorder willy nilly. #[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)] @@ -657,7 +657,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { .buffer(errors_buffer); } else { // FIXME. We should handle this case better. It - // indicates that we have e.g. some region variable + // indicates that we have e.g., some region variable // whose value is like `'a+'b` where `'a` and `'b` are // distinct unrelated univesal regions that are not // known to outlive one another. It'd be nice to have 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 69e2c896d33..4f5829f3406 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/values.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/values.rs @@ -48,7 +48,7 @@ impl RegionValueElements { let mut basic_blocks = IndexVec::with_capacity(num_points); for (bb, bb_data) in mir.basic_blocks().iter_enumerated() { - basic_blocks.extend((0..bb_data.statements.len() + 1).map(|_| bb)); + basic_blocks.extend((0..=bb_data.statements.len()).map(|_| bb)); } Self { @@ -313,7 +313,7 @@ impl RegionValues { self.points.insert_all_into_row(r); } - /// Add all elements in `r_from` to `r_to` (because e.g. `r_to: + /// 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.union_rows(r_from, r_to) diff --git a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs b/src/librustc_mir/borrow_check/nll/type_check/input_output.rs index 85ea39e538f..bb890e65b53 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/input_output.rs @@ -40,7 +40,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { // If the user explicitly annotated the input types, extract // those. // - // e.g. `|x: FxHashMap<_, &'static u32>| ...` + // e.g., `|x: FxHashMap<_, &'static u32>| ...` let user_provided_sig; if !self.tcx().is_closure(self.mir_def_id) { user_provided_sig = None; @@ -50,7 +50,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { None => None, Some(user_provided_poly_sig) => { // Instantiate the canonicalized variables from - // user-provided signature (e.g. the `_` in the code + // user-provided signature (e.g., the `_` in the code // above) with fresh variables. let (poly_sig, _) = self.infcx.instantiate_canonical_with_fresh_inference_vars( mir.span, diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs index 4b39d58cd96..320422c9d33 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs @@ -23,7 +23,7 @@ crate struct LocalUseMap<'me> { liveness_map: &'me NllLivenessMap, /// Head of a linked list of **definitions** of each variable -- - /// definition in this context means assignment, e.g. `x` is + /// definition in this context means assignment, e.g., `x` is /// defined in `x = y` but not `y`; that first def is the head of /// a linked list that lets you enumerate all places the variable /// is assigned. diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs index 9ccdc84db15..7b216d8e587 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs @@ -39,7 +39,7 @@ pub(super) fn generate<'gcx, 'tcx>( typeck: &mut TypeChecker<'_, 'gcx, 'tcx>, mir: &Mir<'tcx>, elements: &Rc, - flow_inits: &mut FlowAtLocation>, + flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'gcx, 'tcx>>, move_data: &MoveData<'tcx>, location_table: &LocationTable, ) { 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 bc4e0ca2351..1fbde2ae59d 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 @@ -46,7 +46,7 @@ pub(super) fn trace( typeck: &mut TypeChecker<'_, 'gcx, 'tcx>, mir: &Mir<'tcx>, elements: &Rc, - flow_inits: &mut FlowAtLocation>, + flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'gcx, 'tcx>>, move_data: &MoveData<'tcx>, liveness_map: &NllLivenessMap, location_table: &LocationTable, @@ -99,7 +99,7 @@ where /// Results of dataflow tracking which variables (and paths) have been /// initialized. - flow_inits: &'me mut FlowAtLocation>, + flow_inits: &'me mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'flow, 'gcx, 'tcx>>, /// Index indicating where each variable is assigned, used, or /// dropped. diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 5f64dfd931c..d205e4da798 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -9,6 +9,7 @@ // except according to those terms. //! This pass type-checks the MIR to ensure it is not broken. + #![allow(unreachable_code)] use borrow_check::borrow_set::BorrowSet; @@ -122,7 +123,7 @@ pub(crate) fn type_check<'gcx, 'tcx>( location_table: &LocationTable, borrow_set: &BorrowSet<'tcx>, all_facts: &mut Option, - flow_inits: &mut FlowAtLocation>, + flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'gcx, 'tcx>>, move_data: &MoveData<'tcx>, elements: &Rc, ) -> MirTypeckResults<'tcx> { @@ -1315,7 +1316,6 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { | StatementKind::StorageDead(..) | StatementKind::InlineAsm { .. } | StatementKind::Retag { .. } - | StatementKind::EscapeToRaw { .. } | StatementKind::Nop => {} } } @@ -1467,7 +1467,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { value_ty, ty, term_location.to_locations(), - ConstraintCategory::Return, + ConstraintCategory::Yield, ) { span_mirbug!( self, @@ -1545,8 +1545,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } } None => { - // FIXME(canndrew): This is_never should probably be an is_uninhabited - if !sig.output().is_never() { + if !sig.output().conservative_is_privately_uninhabited(self.tcx()) { span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig); } } diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/nll/universal_regions.rs index c54a4f96b7d..97fdb80cc78 100644 --- a/src/librustc_mir/borrow_check/nll/universal_regions.rs +++ b/src/librustc_mir/borrow_check/nll/universal_regions.rs @@ -210,8 +210,8 @@ impl<'tcx> UniversalRegions<'tcx> { param_env: ty::ParamEnv<'tcx>, ) -> Self { let tcx = infcx.tcx; - let mir_node_id = tcx.hir.as_local_node_id(mir_def_id).unwrap(); - let mir_hir_id = tcx.hir.node_to_hir_id(mir_node_id); + let mir_node_id = tcx.hir().as_local_node_id(mir_def_id).unwrap(); + let mir_hir_id = tcx.hir().node_to_hir_id(mir_node_id); UniversalRegionsBuilder { infcx, mir_def_id, @@ -485,7 +485,7 @@ impl<'cx, 'gcx, 'tcx> UniversalRegionsBuilder<'cx, 'gcx, 'tcx> { let tcx = self.infcx.tcx; let closure_base_def_id = tcx.closure_base_def_id(self.mir_def_id); - match tcx.hir.body_owner_kind(self.mir_node_id) { + match tcx.hir().body_owner_kind(self.mir_node_id) { BodyOwnerKind::Fn => { let defining_ty = if self.mir_def_id == closure_base_def_id { tcx.type_of(closure_base_def_id) @@ -780,9 +780,9 @@ fn for_each_late_bound_region_defined_on<'tcx>( owner: fn_def_id.index, local_id: *late_bound, }; - let region_node_id = tcx.hir.hir_to_node_id(hir_id); - let name = tcx.hir.name(region_node_id).as_interned_str(); - let region_def_id = tcx.hir.local_def_id(region_node_id); + let region_node_id = tcx.hir().hir_to_node_id(hir_id); + let name = tcx.hir().name(region_node_id).as_interned_str(); + let region_def_id = tcx.hir().local_def_id(region_node_id); let liberated_region = tcx.mk_region(ty::ReFree(ty::FreeRegion { scope: fn_def_id, bound_region: ty::BoundRegion::BrNamed(region_def_id, name), diff --git a/src/librustc_mir/borrow_check/path_utils.rs b/src/librustc_mir/borrow_check/path_utils.rs index 9250c04969f..5e17afc3d3c 100644 --- a/src/librustc_mir/borrow_check/path_utils.rs +++ b/src/librustc_mir/borrow_check/path_utils.rs @@ -68,6 +68,7 @@ pub(super) fn each_borrow_involving_path<'a, 'tcx, 'gcx: 'tcx, F, I, S> ( borrowed.kind, place, access, + places_conflict::PlaceConflictBias::Overlap, ) { debug!( "each_borrow_involving_path: {:?} @ {:?} vs. {:?}/{:?}", diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs index 715d6e0c0d1..7ebd69c63ab 100644 --- a/src/librustc_mir/borrow_check/places_conflict.rs +++ b/src/librustc_mir/borrow_check/places_conflict.rs @@ -17,6 +17,43 @@ use rustc::mir::{Projection, ProjectionElem}; use rustc::ty::{self, TyCtxt}; use std::cmp::max; +/// When checking if a place conflicts with another place, this enum is used to influence decisions +/// where a place might be equal or disjoint with another place, such as if `a[i] == a[j]`. +/// `PlaceConflictBias::Overlap` would bias toward assuming that `i` might equal `j` and that these +/// places overlap. `PlaceConflictBias::NoOverlap` assumes that for the purposes of the predicate +/// being run in the calling context, the conservative choice is to assume the compared indices +/// are disjoint (and therefore, do not overlap). +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +crate enum PlaceConflictBias { + Overlap, + NoOverlap, +} + +/// Helper function for checking if places conflict with a mutable borrow and deep access depth. +/// This is used to check for places conflicting outside of the borrow checking code (such as in +/// dataflow). +crate fn places_conflict<'gcx, 'tcx>( + tcx: TyCtxt<'_, 'gcx, 'tcx>, + mir: &Mir<'tcx>, + borrow_place: &Place<'tcx>, + access_place: &Place<'tcx>, + bias: PlaceConflictBias, +) -> bool { + borrow_conflicts_with_place( + tcx, + mir, + borrow_place, + BorrowKind::Mut { allow_two_phase_borrow: true }, + access_place, + AccessDepth::Deep, + bias, + ) +} + +/// Checks whether the `borrow_place` conflicts with the `access_place` given a borrow kind and +/// access depth. The `bias` parameter is used to determine how the unknowable (comparing runtime +/// array indices, for example) should be interpreted - this depends on what the caller wants in +/// order to make the conservative choice and preserve soundness. pub(super) fn borrow_conflicts_with_place<'gcx, 'tcx>( tcx: TyCtxt<'_, 'gcx, 'tcx>, mir: &Mir<'tcx>, @@ -24,10 +61,11 @@ pub(super) fn borrow_conflicts_with_place<'gcx, 'tcx>( borrow_kind: BorrowKind, access_place: &Place<'tcx>, access: AccessDepth, + bias: PlaceConflictBias, ) -> bool { debug!( - "borrow_conflicts_with_place({:?},{:?},{:?})", - borrow_place, access_place, access + "borrow_conflicts_with_place({:?}, {:?}, {:?}, {:?})", + borrow_place, access_place, access, bias, ); // This Local/Local case is handled by the more general code below, but @@ -46,7 +84,8 @@ pub(super) fn borrow_conflicts_with_place<'gcx, 'tcx>( borrow_components, borrow_kind, access_components, - access + access, + bias, ) }) }) @@ -59,6 +98,7 @@ fn place_components_conflict<'gcx, 'tcx>( borrow_kind: BorrowKind, mut access_components: PlaceComponentsIter<'_, 'tcx>, access: AccessDepth, + bias: PlaceConflictBias, ) -> bool { // The borrowck rules for proving disjointness are applied from the "root" of the // borrow forwards, iterating over "similar" projections in lockstep until @@ -121,17 +161,17 @@ fn place_components_conflict<'gcx, 'tcx>( // check whether the components being borrowed vs // accessed are disjoint (as in the second example, // but not the first). - match place_element_conflict(tcx, mir, borrow_c, access_c) { + match place_element_conflict(tcx, mir, borrow_c, access_c, bias) { Overlap::Arbitrary => { // We have encountered different fields of potentially // the same union - the borrow now partially overlaps. // // There is no *easy* way of comparing the fields // further on, because they might have different types - // (e.g. borrows of `u.a.0` and `u.b.y` where `.0` and + // (e.g., borrows of `u.a.0` and `u.b.y` where `.0` and // `.y` come from different structs). // - // We could try to do some things here - e.g. count + // We could try to do some things here - e.g., count // dereferences - but that's probably not a good // idea, at least for now, so just give up and // report a conflict. This is unsafe code anyway so @@ -165,24 +205,21 @@ fn place_components_conflict<'gcx, 'tcx>( let base_ty = base.ty(mir, tcx).to_ty(tcx); match (elem, &base_ty.sty, access) { - (_, _, Shallow(Some(ArtificialField::Discriminant))) - | (_, _, Shallow(Some(ArtificialField::ArrayLength))) + (_, _, Shallow(Some(ArtificialField::ArrayLength))) | (_, _, Shallow(Some(ArtificialField::ShallowBorrow))) => { - // The discriminant and array length are like - // additional fields on the type; they do not - // overlap any existing data there. Furthermore, - // they cannot actually be a prefix of any - // borrowed place (at least in MIR as it is - // currently.) + // The array length is like additional fields on the + // type; it does not overlap any existing data there. + // Furthermore, if cannot actually be a prefix of any + // borrowed place (at least in MIR as it is currently.) // - // e.g. a (mutable) borrow of `a[5]` while we read the + // e.g., a (mutable) borrow of `a[5]` while we read the // array length of `a`. debug!("borrow_conflicts_with_place: implicit field"); return false; } (ProjectionElem::Deref, _, Shallow(None)) => { - // e.g. a borrow of `*x.y` while we shallowly access `x.y` or some + // e.g., a borrow of `*x.y` while we shallowly access `x.y` or some // prefix thereof - the shallow access can't touch anything behind // the pointer. debug!("borrow_conflicts_with_place: shallow access behind ptr"); @@ -193,7 +230,7 @@ fn place_components_conflict<'gcx, 'tcx>( bug!("Tracking borrow behind shared reference."); } (ProjectionElem::Deref, ty::Ref(_, _, hir::MutMutable), AccessDepth::Drop) => { - // Values behind a mutatble reference are not access either by Dropping a + // Values behind a mutable reference are not access either by dropping a // value, or by StorageDead debug!("borrow_conflicts_with_place: drop access behind ptr"); return false; @@ -216,7 +253,7 @@ fn place_components_conflict<'gcx, 'tcx>( | (ProjectionElem::Downcast { .. }, _, _) => { // Recursive case. This can still be disjoint on a // further iteration if this a shallow access and - // there's a deref later on, e.g. a borrow + // there's a deref later on, e.g., a borrow // of `*x.y` while accessing `x`. } } @@ -251,7 +288,7 @@ fn place_components_conflict<'gcx, 'tcx>( /// the place `a` with a "next" pointer to `a.b`). Created by /// `unroll_place`. /// -/// NB: This particular impl strategy is not the most obvious. It was +/// N.B., this particular impl strategy is not the most obvious. It was /// chosen because it makes a measurable difference to NLL /// performance, as this code (`borrow_conflicts_with_place`) is somewhat hot. struct PlaceComponents<'p, 'tcx: 'p> { @@ -277,7 +314,7 @@ impl<'p, 'tcx> PlaceComponents<'p, 'tcx> { /// Iterator over components; see `PlaceComponents::iter` for more /// information. /// -/// NB: This is not a *true* Rust iterator -- the code above just +/// N.B., this is not a *true* Rust iterator -- the code above just /// manually invokes `next`. This is because we (sometimes) want to /// keep executing even after `None` has been returned. struct PlaceComponentsIter<'p, 'tcx: 'p> { @@ -331,6 +368,7 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>( mir: &Mir<'tcx>, elem1: &Place<'tcx>, elem2: &Place<'tcx>, + bias: PlaceConflictBias, ) -> Overlap { match (elem1, elem2) { (Place::Local(l1), Place::Local(l2)) => { @@ -384,13 +422,13 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>( (Place::Projection(pi1), Place::Projection(pi2)) => { match (&pi1.elem, &pi2.elem) { (ProjectionElem::Deref, ProjectionElem::Deref) => { - // derefs (e.g. `*x` vs. `*x`) - recur. + // derefs (e.g., `*x` vs. `*x`) - recur. debug!("place_element_conflict: DISJOINT-OR-EQ-DEREF"); Overlap::EqualOrDisjoint } (ProjectionElem::Field(f1, _), ProjectionElem::Field(f2, _)) => { if f1 == f2 { - // same field (e.g. `a.y` vs. `a.y`) - recur. + // same field (e.g., `a.y` vs. `a.y`) - recur. debug!("place_element_conflict: DISJOINT-OR-EQ-FIELD"); Overlap::EqualOrDisjoint } else { @@ -448,10 +486,20 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>( | (ProjectionElem::ConstantIndex { .. }, ProjectionElem::Index(..)) | (ProjectionElem::Subslice { .. }, ProjectionElem::Index(..)) => { // Array indexes (`a[0]` vs. `a[i]`). These can either be disjoint - // (if the indexes differ) or equal (if they are the same), so this - // is the recursive case that gives "equal *or* disjoint" its meaning. - debug!("place_element_conflict: DISJOINT-OR-EQ-ARRAY-INDEX"); - Overlap::EqualOrDisjoint + // (if the indexes differ) or equal (if they are the same). + match bias { + PlaceConflictBias::Overlap => { + // If we are biased towards overlapping, then this is the recursive + // case that gives "equal *or* disjoint" its meaning. + debug!("place_element_conflict: DISJOINT-OR-EQ-ARRAY-INDEX"); + Overlap::EqualOrDisjoint + } + PlaceConflictBias::NoOverlap => { + // If we are biased towards no overlapping, then this is disjoint. + debug!("place_element_conflict: DISJOINT-ARRAY-INDEX"); + Overlap::Disjoint + } + } } (ProjectionElem::ConstantIndex { offset: o1, min_length: _, from_end: false }, ProjectionElem::ConstantIndex { offset: o2, min_length: _, from_end: false }) diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs index f73e08eb135..b759e0416e5 100644 --- a/src/librustc_mir/borrow_check/prefixes.rs +++ b/src/librustc_mir/borrow_check/prefixes.rs @@ -87,14 +87,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { impl<'cx, 'gcx, 'tcx> Iterator for Prefixes<'cx, 'gcx, 'tcx> { type Item = &'cx Place<'tcx>; fn next(&mut self) -> Option { - let mut cursor = match self.next { - None => return None, - Some(place) => place, - }; + let mut cursor = self.next?; // Post-processing `place`: Enqueue any remaining // work. Also, `place` may not be a prefix itself, but - // may hold one further down (e.g. we never return + // may hold one further down (e.g., we never return // downcasts here, but may return a base of a downcast). 'cursor: loop { diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs index 2ef71617b7c..4df8d66e2fb 100644 --- a/src/librustc_mir/build/block.rs +++ b/src/librustc_mir/build/block.rs @@ -117,7 +117,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { }; this.block_context.push(BlockFrame::Statement { ignores_expr_result }); - // Enter the remainder scope, i.e. the bindings' destruction scope. + // Enter the remainder scope, i.e., the bindings' destruction scope. this.push_scope((remainder_scope, source_info)); let_scope_stack.push(remainder_scope); diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 18ce7ae4907..a476165462a 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! See docs in build/expr/mod.rs +//! See docs in `build/expr/mod.rs`. use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::Idx; diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 8eb46a04839..146bf538306 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -275,8 +275,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { exit_block.unit() } ExprKind::Call { ty, fun, args, from_hir_call } => { - // FIXME(canndrew): This is_never should probably be an is_uninhabited - let diverges = expr.ty.is_never(); let intrinsic = match ty.sty { ty::FnDef(def_id, _) => { let f = ty.fn_sig(this.hir.tcx()); @@ -332,7 +330,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { func: fun, args, cleanup: Some(cleanup), - destination: if diverges { + // FIXME(varkor): replace this with an uninhabitedness-based check. + // This requires getting access to the current module to call + // `tcx.is_ty_uninhabited_from`, which is currently tricky to do. + destination: if expr.ty.is_never() { None } else { Some((destination.clone(), success)) @@ -414,15 +415,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // must be handled above or else we get an // infinite loop in the builder; see - // e.g. `ExprKind::VarRef` above + // e.g., `ExprKind::VarRef` above Category::Place => false, _ => true, }); let rvalue = unpack!(block = this.as_local_rvalue(block, expr)); - this.cfg - .push_assign(block, source_info, destination, rvalue); + this.cfg.push_assign(block, source_info, destination, rvalue); block.unit() } }; diff --git a/src/librustc_mir/build/expr/stmt.rs b/src/librustc_mir/build/expr/stmt.rs index 45235b31539..0e9f81bbe95 100644 --- a/src/librustc_mir/build/expr/stmt.rs +++ b/src/librustc_mir/build/expr/stmt.rs @@ -16,7 +16,7 @@ use rustc::mir::*; impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// Builds a block of MIR statements to evaluate the HAIR `expr`. /// If the original expression was an AST statement, - /// (e.g. `some().code(&here());`) then `opt_stmt_span` is the + /// (e.g., `some().code(&here());`) then `opt_stmt_span` is the /// span of that statement (including its semicolon, if any). /// Diagnostics use this span (which may be larger than that of /// `expr`) to identify when statement temporaries are dropped. diff --git a/src/librustc_mir/build/into.rs b/src/librustc_mir/build/into.rs index 9c8d0b2aeb9..3e57c4acb42 100644 --- a/src/librustc_mir/build/into.rs +++ b/src/librustc_mir/build/into.rs @@ -11,7 +11,7 @@ //! In general, there are a number of things for which it's convenient //! to just call `builder.into` and have it emit its result into a //! given location. This is basically for expressions or things that can be -//! wrapped up as expressions (e.g. blocks). To make this ergonomic, we use this +//! wrapped up as expressions (e.g., blocks). To make this ergonomic, we use this //! latter `EvalInto` trait. use build::{BlockAnd, Builder}; diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 342aaf9039d..4d61bf8dae6 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -19,7 +19,6 @@ use build::{BlockAnd, BlockAndExtension, Builder}; use build::{GuardFrame, GuardFrameLocal, LocalsForNode}; use hair::*; use hair::pattern::PatternTypeProjections; -use rustc::hir; use rustc::mir::*; use rustc::ty::{self, Ty}; use rustc::ty::layout::VariantIdx; @@ -100,8 +99,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { .collect(); // create binding start block for link them by false edges - let candidate_count = arms.iter().fold(0, |ac, c| ac + c.patterns.len()); - let pre_binding_blocks: Vec<_> = (0..candidate_count + 1) + let candidate_count = arms.iter().map(|c| c.patterns.len()).sum::(); + let pre_binding_blocks: Vec<_> = (0..=candidate_count) .map(|_| self.cfg.start_new_block()) .collect(); @@ -111,7 +110,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // pattern, which means there may be more than one candidate // *per arm*. These candidates are kept sorted such that the // highest priority candidate comes first in the list. - // (i.e. same order as in source) + // (i.e., same order as in source) let candidates: Vec<_> = arms.iter() .enumerate() @@ -337,7 +336,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { pub fn place_into_pattern( &mut self, - mut block: BasicBlock, + block: BasicBlock, irrefutable_pat: Pattern<'tcx>, initializer: &Place<'tcx>, set_match_place: bool, @@ -359,7 +358,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // Simplify the candidate. Since the pattern is irrefutable, this should // always convert all match-pairs into bindings. - unpack!(block = self.simplify_candidate(block, &mut candidate)); + self.simplify_candidate(&mut candidate); if !candidate.match_pairs.is_empty() { span_bug!( @@ -470,7 +469,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ); let place = Place::Local(local_id); let var_ty = self.local_decls[local_id].ty; - let hir_id = self.hir.tcx().hir.node_to_hir_id(var); + let hir_id = self.hir.tcx().hir().node_to_hir_id(var); let region_scope = self.hir.region_scope_tree.var_scope(hir_id.local_id); self.schedule_drop(span, region_scope, &place, var_ty, DropKind::Storage); place @@ -479,7 +478,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { pub fn schedule_drop_for_binding(&mut self, var: NodeId, span: Span, for_guard: ForGuard) { let local_id = self.var_local_id(var, for_guard); let var_ty = self.local_decls[local_id].ty; - let hir_id = self.hir.tcx().hir.node_to_hir_id(var); + let hir_id = self.hir.tcx().hir().node_to_hir_id(var); let region_scope = self.hir.region_scope_tree.var_scope(hir_id.local_id); self.schedule_drop( span, @@ -681,12 +680,7 @@ enum TestKind<'tcx> { }, // test whether the value falls within an inclusive or exclusive range - Range { - lo: &'tcx ty::Const<'tcx>, - hi: &'tcx ty::Const<'tcx>, - ty: Ty<'tcx>, - end: hir::RangeEnd, - }, + Range(PatternRange<'tcx>), // test length of the slice is equal to len Len { @@ -745,7 +739,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // complete, all the match pairs which remain require some // form of test, whether it be a switch or pattern comparison. for candidate in &mut candidates { - unpack!(block = self.simplify_candidate(block, candidate)); + self.simplify_candidate(candidate); } // The candidates are sorted by priority. Check to see @@ -1035,7 +1029,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { test, match_pair ); let target_blocks = self.perform_test(block, &match_pair.place, &test); - let mut target_candidates: Vec<_> = (0..target_blocks.len()).map(|_| vec![]).collect(); + let mut target_candidates = vec![vec![]; target_blocks.len()]; // Sort the candidates into the appropriate vector in // `target_candidates`. Note that at some point we may @@ -1384,7 +1378,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // Tricky business: For `ref id` and `ref mut id` // patterns, we want `id` within the guard to // correspond to a temp of type `& &T` or `& &mut - // T` (i.e. a "borrow of a borrow") that is + // T` (i.e., a "borrow of a borrow") that is // implicitly dereferenced. // // To borrow a borrow, we need that inner borrow diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs index cfea357334f..0ce64283870 100644 --- a/src/librustc_mir/build/matches/simplify.rs +++ b/src/librustc_mir/build/matches/simplify.rs @@ -22,33 +22,35 @@ //! sort of test: for example, testing which variant an enum is, or //! testing a value against a constant. -use build::{BlockAnd, BlockAndExtension, Builder}; +use build::Builder; use build::matches::{Ascription, Binding, MatchPair, Candidate}; use hair::*; -use rustc::mir::*; +use rustc::ty; +use rustc::ty::layout::{Integer, IntegerExt, Size}; +use syntax::attr::{SignedInt, UnsignedInt}; +use rustc::hir::RangeEnd; use std::mem; impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { pub fn simplify_candidate<'pat>(&mut self, - block: BasicBlock, - candidate: &mut Candidate<'pat, 'tcx>) - -> BlockAnd<()> { + candidate: &mut Candidate<'pat, 'tcx>) { // repeatedly simplify match pairs until fixed point is reached loop { let match_pairs = mem::replace(&mut candidate.match_pairs, vec![]); - let mut progress = match_pairs.len(); // count how many were simplified + let mut changed = false; for match_pair in match_pairs { match self.simplify_match_pair(match_pair, candidate) { - Ok(()) => {} + Ok(()) => { + changed = true; + } Err(match_pair) => { candidate.match_pairs.push(match_pair); - progress -= 1; // this one was not simplified } } } - if progress == 0 { - return block.unit(); // if we were not able to simplify any, done. + if !changed { + return; // if we were not able to simplify any, done. } } } @@ -62,6 +64,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { match_pair: MatchPair<'pat, 'tcx>, candidate: &mut Candidate<'pat, 'tcx>) -> Result<(), MatchPair<'pat, 'tcx>> { + let tcx = self.hir.tcx(); match *match_pair.pattern.kind { PatternKind::AscribeUserType { ref subpattern, ref user_ty, user_ty_span } => { candidate.ascriptions.push(Ascription { @@ -104,7 +107,34 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { Err(match_pair) } - PatternKind::Range { .. } => { + PatternKind::Range(PatternRange { lo, hi, ty, end }) => { + let range = match ty.sty { + ty::Char => { + Some(('\u{0000}' as u128, '\u{10FFFF}' as u128, Size::from_bits(32))) + } + ty::Int(ity) => { + // FIXME(49937): refactor these bit manipulations into interpret. + let size = Integer::from_attr(&tcx, SignedInt(ity)).size(); + let min = 1u128 << (size.bits() - 1); + let max = (1u128 << (size.bits() - 1)) - 1; + Some((min, max, size)) + } + ty::Uint(uty) => { + // FIXME(49937): refactor these bit manipulations into interpret. + let size = Integer::from_attr(&tcx, UnsignedInt(uty)).size(); + let max = !0u128 >> (128 - size.bits()); + Some((0, max, size)) + } + _ => None, + }; + if let Some((min, max, sz)) = range { + if let (Some(lo), Some(hi)) = (lo.val.try_to_bits(sz), hi.val.try_to_bits(sz)) { + if lo <= min && (hi > max || hi == max && end == RangeEnd::Included) { + // Irrefutable pattern match. + return Ok(()); + } + } + } Err(match_pair) } diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index 5d9cb014f58..c8dec6d0b97 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -18,6 +18,7 @@ use build::Builder; use build::matches::{Candidate, MatchPair, Test, TestKind}; use hair::*; +use hair::pattern::compare_const_vals; use rustc_data_structures::bit_set::BitSet; use rustc_data_structures::fx::FxHashMap; use rustc::ty::{self, Ty}; @@ -71,16 +72,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } } - PatternKind::Range { lo, hi, ty, end } => { - assert!(ty == match_pair.pattern.ty); + PatternKind::Range(range) => { + assert!(range.ty == match_pair.pattern.ty); Test { span: match_pair.pattern.span, - kind: TestKind::Range { - lo, - hi, - ty, - end, - }, + kind: TestKind::Range(range), } } @@ -136,7 +132,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { PatternKind::Variant { .. } => { panic!("you should have called add_variants_to_switch instead!"); } - PatternKind::Range { .. } | + PatternKind::Range(range) => { + // Check that none of the switch values are in the range. + self.values_not_contained_in_range(range, indices) + .unwrap_or(false) + } PatternKind::Slice { .. } | PatternKind::Array { .. } | PatternKind::Wild | @@ -200,20 +200,18 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { for (idx, discr) in adt_def.discriminants(tcx) { target_blocks.push(if variants.contains(idx) { values.push(discr.val); - targets.push(self.cfg.start_new_block()); - *targets.last().unwrap() + let block = self.cfg.start_new_block(); + targets.push(block); + block } else { - if otherwise_block.is_none() { - otherwise_block = Some(self.cfg.start_new_block()); - } - otherwise_block.unwrap() + *otherwise_block + .get_or_insert_with(|| self.cfg.start_new_block()) }); } - if let Some(otherwise_block) = otherwise_block { - targets.push(otherwise_block); - } else { - targets.push(self.unreachable_block()); - } + targets.push( + otherwise_block + .unwrap_or_else(|| self.unreachable_block()), + ); debug!("num_enum_variants: {}, tested variants: {:?}, variants: {:?}", num_enum_variants, values, variants); let discr_ty = adt_def.repr.discr_type().to_ty(tcx); @@ -378,7 +376,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } } - TestKind::Range { ref lo, ref hi, ty, ref end } => { + TestKind::Range(PatternRange { ref lo, ref hi, ty, ref end }) => { // Test `val` by computing `lo <= val && val <= hi`, using primitive comparisons. let lo = self.literal_operand(test.span, ty.clone(), lo.clone()); let hi = self.literal_operand(test.span, ty.clone(), hi.clone()); @@ -490,8 +488,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // away.) let tested_match_pair = candidate.match_pairs.iter() .enumerate() - .filter(|&(_, mp)| mp.place == *test_place) - .next(); + .find(|&(_, mp)| mp.place == *test_place); let (match_pair_index, match_pair) = match tested_match_pair { Some(pair) => pair, None => { @@ -532,6 +529,24 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { resulting_candidates[index].push(new_candidate); true } + + (&TestKind::SwitchInt { switch_ty: _, ref options, ref indices }, + &PatternKind::Range(range)) => { + let not_contained = self + .values_not_contained_in_range(range, indices) + .unwrap_or(false); + + if not_contained { + // No switch values are contained in the pattern range, + // so the pattern can be matched only if this test fails. + let otherwise = options.len(); + resulting_candidates[otherwise].push(candidate.clone()); + true + } else { + false + } + } + (&TestKind::SwitchInt { .. }, _) => false, @@ -610,8 +625,63 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } } + (&TestKind::Range(test), + &PatternKind::Range(pat)) => { + if test == pat { + resulting_candidates[0] + .push(self.candidate_without_match_pair( + match_pair_index, + candidate, + )); + return true; + } + + let no_overlap = (|| { + use std::cmp::Ordering::*; + use rustc::hir::RangeEnd::*; + + let param_env = ty::ParamEnv::empty().and(test.ty); + let tcx = self.hir.tcx(); + + let lo = compare_const_vals(tcx, test.lo, pat.hi, param_env)?; + let hi = compare_const_vals(tcx, test.hi, pat.lo, param_env)?; + + match (test.end, pat.end, lo, hi) { + // pat < test + (_, _, Greater, _) | + (_, Excluded, Equal, _) | + // pat > test + (_, _, _, Less) | + (Excluded, _, _, Equal) => Some(true), + _ => Some(false), + } + })(); + + if no_overlap == Some(true) { + // Testing range does not overlap with pattern range, + // so the pattern can be matched only if this test fails. + resulting_candidates[1].push(candidate.clone()); + true + } else { + false + } + } + + (&TestKind::Range(range), &PatternKind::Constant { ref value }) => { + if self.const_range_contains(range, value) == Some(false) { + // `value` is not contained in the testing range, + // so `value` can be matched only if this test fails. + resulting_candidates[1].push(candidate.clone()); + true + } else { + false + } + } + + (&TestKind::Range { .. }, _) => false, + + (&TestKind::Eq { .. }, _) | - (&TestKind::Range { .. }, _) | (&TestKind::Len { .. }, _) => { // These are all binary tests. // @@ -722,6 +792,40 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { "simplifyable pattern found: {:?}", match_pair.pattern) } + + fn const_range_contains( + &self, + range: PatternRange<'tcx>, + value: &'tcx ty::Const<'tcx>, + ) -> Option { + use std::cmp::Ordering::*; + + let param_env = ty::ParamEnv::empty().and(range.ty); + let tcx = self.hir.tcx(); + + let a = compare_const_vals(tcx, range.lo, value, param_env)?; + let b = compare_const_vals(tcx, value, range.hi, param_env)?; + + match (b, range.end) { + (Less, _) | + (Equal, RangeEnd::Included) if a != Greater => Some(true), + _ => Some(false), + } + } + + fn values_not_contained_in_range( + &self, + range: PatternRange<'tcx>, + indices: &FxHashMap<&'tcx ty::Const<'tcx>, usize>, + ) -> Option { + for val in indices.keys() { + if self.const_range_contains(range, val)? { + return Some(false); + } + } + + Some(true) + } } fn is_switch_ty<'tcx>(ty: Ty<'tcx>) -> bool { diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir/build/misc.rs index 9405f43c056..3ac7bd3fc68 100644 --- a/src/librustc_mir/build/misc.rs +++ b/src/librustc_mir/build/misc.rs @@ -22,7 +22,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// Add a new temporary value of type `ty` storing the result of /// evaluating `expr`. /// - /// NB: **No cleanup is scheduled for this temporary.** You should + /// N.B., **No cleanup is scheduled for this temporary.** You should /// call `schedule_drop` once the temporary is initialized. pub fn temp(&mut self, ty: Ty<'tcx>, span: Span) -> Place<'tcx> { let temp = self.local_decls.push(LocalDecl::new_temp(ty, span)); diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index d95a74be776..d6af125debf 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -39,10 +39,10 @@ use super::lints; /// Construct the MIR for a given def-id. pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'tcx> { - let id = tcx.hir.as_local_node_id(def_id).unwrap(); + let id = tcx.hir().as_local_node_id(def_id).unwrap(); // Figure out what primary body this item has. - let (body_id, return_ty_span) = match tcx.hir.get(id) { + let (body_id, return_ty_span) = match tcx.hir().get(id) { Node::Variant(variant) => return create_constructor_shim(tcx, id, &variant.node.data), Node::StructCtor(ctor) => @@ -76,10 +76,10 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t (*body_id, ty.span) } Node::AnonConst(hir::AnonConst { body, id, .. }) => { - (*body, tcx.hir.span(*id)) + (*body, tcx.hir().span(*id)) } - _ => span_bug!(tcx.hir.span(id), "can't build MIR for {:?}", def_id), + _ => span_bug!(tcx.hir().span(id), "can't build MIR for {:?}", def_id), }; tcx.infer_ctxt().enter(|infcx| { @@ -89,10 +89,11 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t } else if let hir::BodyOwnerKind::Fn = cx.body_owner_kind { // fetch the fully liberated fn signature (that is, all bound // types/lifetimes replaced) - let fn_hir_id = tcx.hir.node_to_hir_id(id); + let fn_hir_id = tcx.hir().node_to_hir_id(id); let fn_sig = cx.tables().liberated_fn_sigs()[fn_hir_id].clone(); + let fn_def_id = tcx.hir().local_def_id(id); - let ty = tcx.type_of(tcx.hir.local_def_id(id)); + let ty = tcx.type_of(fn_def_id); let mut abi = fn_sig.abi; let implicit_argument = match ty.sty { ty::Closure(..) => { @@ -108,24 +109,23 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t _ => None, }; - // FIXME: safety in closures let safety = match fn_sig.unsafety { hir::Unsafety::Normal => Safety::Safe, hir::Unsafety::Unsafe => Safety::FnUnsafe, }; - let body = tcx.hir.body(body_id); + let body = tcx.hir().body(body_id); let explicit_arguments = body.arguments .iter() .enumerate() .map(|(index, arg)| { - let owner_id = tcx.hir.body_owner(body_id); + let owner_id = tcx.hir().body_owner(body_id); let opt_ty_info; let self_arg; - if let Some(ref fn_decl) = tcx.hir.fn_decl(owner_id) { + if let Some(ref fn_decl) = tcx.hir().fn_decl(owner_id) { let ty_hir_id = fn_decl.inputs[index].hir_id; - let ty_span = tcx.hir.span(tcx.hir.hir_to_node_id(ty_hir_id)); + let ty_span = tcx.hir().span(tcx.hir().hir_to_node_id(ty_hir_id)); opt_ty_info = Some(ty_span); self_arg = if index == 0 && fn_decl.implicit_self.has_implicit_self() { match fn_decl.implicit_self { @@ -152,7 +152,7 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t ty::Generator(gen_def_id, gen_substs, ..) => gen_substs.sig(gen_def_id, tcx), _ => - span_bug!(tcx.hir.span(id), "generator w/o generator type: {:?}", ty), + span_bug!(tcx.hir().span(id), "generator w/o generator type: {:?}", ty), }; (Some(gen_sig.yield_ty), gen_sig.return_ty) } else { @@ -239,7 +239,7 @@ fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, v: &'tcx hir::VariantData) -> Mir<'tcx> { - let span = tcx.hir.span(ctor_id); + let span = tcx.hir().span(ctor_id); if let hir::VariantData::Tuple(ref fields, ctor_id) = *v { tcx.infer_ctxt().enter(|infcx| { let mut mir = shim::build_adt_ctor(&infcx, ctor_id, fields, span); @@ -256,7 +256,7 @@ fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }; mir_util::dump_mir(tcx, None, "mir_map", &0, - MirSource::item(tcx.hir.local_def_id(ctor_id)), + MirSource::item(tcx.hir().local_def_id(ctor_id)), &mir, |_, _| Ok(()) ); mir @@ -273,7 +273,7 @@ fn liberated_closure_env_ty<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, closure_expr_id: ast::NodeId, body_id: hir::BodyId) -> Ty<'tcx> { - let closure_expr_hir_id = tcx.hir.node_to_hir_id(closure_expr_id); + let closure_expr_hir_id = tcx.hir().node_to_hir_id(closure_expr_id); let closure_ty = tcx.body_tables(body_id).node_id_to_type(closure_expr_hir_id); let (closure_def_id, closure_substs) = match closure_ty.sty { @@ -621,12 +621,7 @@ fn should_abort_on_panic<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, // unwind anyway. Don't stop them. let attrs = &tcx.get_attrs(fn_def_id); match attr::find_unwind_attr(Some(tcx.sess.diagnostic()), attrs) { - None => { - // FIXME(rust-lang/rust#48251) -- Had to disable - // abort-on-panic for backwards compatibility reasons. - false - } - + None => true, Some(UnwindAttr::Allowed) => false, Some(UnwindAttr::Aborts) => true, } @@ -655,14 +650,14 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, let arguments: Vec<_> = arguments.collect(); let tcx = hir.tcx(); - let span = tcx.hir.span(fn_id); + let span = tcx.hir().span(fn_id); // Gather the upvars of a closure, if any. let upvar_decls: Vec<_> = tcx.with_freevars(fn_id, |freevars| { freevars.iter().map(|fv| { let var_id = fv.var_id(); - let var_hir_id = tcx.hir.node_to_hir_id(var_id); - let closure_expr_id = tcx.hir.local_def_id(fn_id); + let var_hir_id = tcx.hir().node_to_hir_id(var_id); + let closure_expr_id = tcx.hir().local_def_id(fn_id); let capture = hir.tables().upvar_capture(ty::UpvarId { var_path: ty::UpvarPath {hir_id: var_hir_id}, closure_expr_id: LocalDefId::from_def_id(closure_expr_id), @@ -677,7 +672,7 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, by_ref, mutability: Mutability::Not, }; - if let Some(Node::Binding(pat)) = tcx.hir.find(var_id) { + if let Some(Node::Binding(pat)) = tcx.hir().find(var_id) { if let hir::PatKind::Binding(_, _, ident, _) = pat.node { decl.debug_name = ident.name; @@ -704,7 +699,7 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, return_ty_span, upvar_decls); - let fn_def_id = tcx.hir.local_def_id(fn_id); + let fn_def_id = tcx.hir().local_def_id(fn_id); let call_site_scope = region::Scope { id: body.value.hir_id.local_id, data: region::ScopeData::CallSite @@ -747,7 +742,7 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, // RustCall pseudo-ABI untuples the last argument. spread_arg = Some(Local::new(arguments.len())); } - let closure_expr_id = tcx.hir.local_def_id(fn_id); + let closure_expr_id = tcx.hir().local_def_id(fn_id); info!("fn_id {:?} has attrs {:?}", closure_expr_id, tcx.get_attrs(closure_expr_id)); @@ -762,10 +757,10 @@ fn construct_const<'a, 'gcx, 'tcx>( ty_span: Span, ) -> Mir<'tcx> { let tcx = hir.tcx(); - let ast_expr = &tcx.hir.body(body_id).value; + let ast_expr = &tcx.hir().body(body_id).value; let ty = hir.tables().expr_ty_adjusted(ast_expr); - let owner_id = tcx.hir.body_owner(body_id); - let span = tcx.hir.span(owner_id); + let owner_id = tcx.hir().body_owner(body_id); + let span = tcx.hir().span(owner_id); let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty, ty_span,vec![]); let mut block = START_BLOCK; @@ -791,8 +786,8 @@ fn construct_const<'a, 'gcx, 'tcx>( fn construct_error<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>, body_id: hir::BodyId) -> Mir<'tcx> { - let owner_id = hir.tcx().hir.body_owner(body_id); - let span = hir.tcx().hir.span(owner_id); + let owner_id = hir.tcx().hir().body_owner(body_id); + let span = hir.tcx().hir().span(owner_id); let ty = hir.tcx().types.err; let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty, span, vec![]); let source_info = builder.source_info(span); @@ -854,15 +849,17 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } } - Mir::new(self.cfg.basic_blocks, - self.source_scopes, - ClearCrossCrate::Set(self.source_scope_local_data), - IndexVec::new(), - yield_ty, - self.local_decls, - self.arg_count, - self.upvar_decls, - self.fn_span + Mir::new( + self.cfg.basic_blocks, + self.source_scopes, + ClearCrossCrate::Set(self.source_scope_local_data), + IndexVec::new(), + yield_ty, + self.local_decls, + self.arg_count, + self.upvar_decls, + self.fn_span, + self.hir.control_flow_destroyed(), ) } diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 2a11f24095b..8c948766314 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -152,7 +152,7 @@ struct DropData<'tcx> { pub(crate) struct CachedBlock { /// The cached block for the cleanups-on-diverge path. This block /// contains code to run the current drop and all the preceding - /// drops (i.e. those having lower index in Drop’s Scope drop + /// drops (i.e., those having lower index in Drop’s Scope drop /// array) unwind: Option, @@ -182,7 +182,7 @@ pub struct BreakableScope<'tcx> { /// Block to branch into when the loop or block terminates (either by being `break`-en out /// from, or by having its condition to become false) pub break_block: BasicBlock, - /// The destination of the loop/block expression itself (i.e. where to put the result of a + /// The destination of the loop/block expression itself (i.e., where to put the result of a /// `break` expression) pub break_destination: Place<'tcx>, } @@ -322,11 +322,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let same_lint_scopes = tcx.dep_graph.with_ignore(|| { let sets = tcx.lint_levels(LOCAL_CRATE); let parent_hir_id = - tcx.hir.definitions().node_to_hir_id( + tcx.hir().definitions().node_to_hir_id( self.source_scope_local_data[source_scope].lint_root ); let current_hir_id = - tcx.hir.definitions().node_to_hir_id(node_id); + tcx.hir().definitions().node_to_hir_id(node_id); sets.lint_level_set(parent_hir_id) == sets.lint_level_set(current_hir_id) }); @@ -737,7 +737,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // // Note that this code iterates scopes from the inner-most to the outer-most, // invalidating caches of each scope visited. This way bare minimum of the - // caches gets invalidated. i.e. if a new drop is added into the middle scope, the + // caches gets invalidated. i.e., if a new drop is added into the middle scope, the // cache of outer scpoe stays intact. scope.invalidate_cache(!needs_drop, this_scope); if this_scope { diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 291b5c170ef..4c183d59a63 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -187,7 +187,7 @@ fn eval_body_using_ecx<'mir, 'tcx>( } let layout = ecx.layout_of(mir.return_ty().subst(tcx, cid.instance.substs))?; assert!(!layout.is_unsized()); - let ret = ecx.allocate(layout, MemoryKind::Stack)?; + let ret = ecx.allocate(layout, MemoryKind::Stack); let name = ty::tls::with(|tcx| tcx.item_path_str(cid.instance.def_id())); let prom = cid.promoted.map_or(String::new(), |p| format!("::promoted[{:?}]", p)); @@ -490,8 +490,8 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx> _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, ptr: Pointer, _kind: MemoryKind, - ) -> EvalResult<'tcx, Pointer> { - Ok(ptr) + ) -> Pointer { + ptr } #[inline(always)] @@ -664,7 +664,7 @@ pub fn const_eval_raw_provider<'a, 'tcx>( let cid = key.value; let def_id = cid.instance.def.def_id(); - if let Some(id) = tcx.hir.as_local_node_id(def_id) { + if let Some(id) = tcx.hir().as_local_node_id(def_id) { let tables = tcx.typeck_tables_of(def_id); // Do match-check before building MIR @@ -672,7 +672,7 @@ pub fn const_eval_raw_provider<'a, 'tcx>( return Err(ErrorHandled::Reported) } - if let hir::BodyOwnerKind::Const = tcx.hir.body_owner_kind(id) { + if let hir::BodyOwnerKind::Const = tcx.hir().body_owner_kind(id) { tcx.mir_const_qualif(def_id); } @@ -692,12 +692,16 @@ pub fn const_eval_raw_provider<'a, 'tcx>( let err = error_to_const_error(&ecx, error); // errors in statics are always emitted as fatal errors if tcx.is_static(def_id).is_some() { - let err = err.report_as_error(ecx.tcx, "could not evaluate static initializer"); - // check that a static never produces `TooGeneric` + let reported_err = err.report_as_error(ecx.tcx, + "could not evaluate static initializer"); + // Ensure that if the above error was either `TooGeneric` or `Reported` + // an error must be reported. if tcx.sess.err_count() == 0 { - span_bug!(ecx.tcx.span, "static eval failure didn't emit an error: {:#?}", err); + tcx.sess.delay_span_bug(err.span, + &format!("static eval failure did not emit an error: {:#?}", + reported_err)); } - err + reported_err } else if def_id.is_local() { // constant defined in this crate, we can figure out a lint level! match tcx.describe_def(def_id) { @@ -708,7 +712,7 @@ pub fn const_eval_raw_provider<'a, 'tcx>( // because any code that existed before validation could not have failed validation // thus preventing such a hard error from being a backwards compatibility hazard Some(Def::Const(_)) | Some(Def::AssociatedConst(_)) => { - let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); + let node_id = tcx.hir().as_local_node_id(def_id).unwrap(); err.report_as_lint( tcx.at(tcx.def_span(def_id)), "any use of this value will cause an error", @@ -728,7 +732,7 @@ pub fn const_eval_raw_provider<'a, 'tcx>( err.report_as_lint( tcx.at(span), "reaching this expression at runtime will panic or abort", - tcx.hir.as_local_node_id(def_id).unwrap(), + tcx.hir().as_local_node_id(def_id).unwrap(), ) } // anything else (array lengths, enum initializers, constant patterns) are reported diff --git a/src/librustc_mir/dataflow/at_location.rs b/src/librustc_mir/dataflow/at_location.rs index d815bfedc37..69f6fbb6c80 100644 --- a/src/librustc_mir/dataflow/at_location.rs +++ b/src/librustc_mir/dataflow/at_location.rs @@ -67,22 +67,22 @@ pub trait FlowsAtLocation { /// effects at any point in the control-flow graph by starting with /// the state at the start of the basic block (`reset_to_entry_of`) /// and then replaying the effects of statements and terminators -/// (e.g. via `reconstruct_statement_effect` and +/// (e.g., via `reconstruct_statement_effect` and /// `reconstruct_terminator_effect`; don't forget to call /// `apply_local_effect`). -pub struct FlowAtLocation +pub struct FlowAtLocation<'tcx, BD> where - BD: BitDenotation, + BD: BitDenotation<'tcx>, { - base_results: DataflowResults, + base_results: DataflowResults<'tcx, BD>, curr_state: BitSet, stmt_gen: HybridBitSet, stmt_kill: HybridBitSet, } -impl FlowAtLocation +impl<'tcx, BD> FlowAtLocation<'tcx, BD> where - BD: BitDenotation, + BD: BitDenotation<'tcx>, { /// Iterate over each bit set in the current state. pub fn each_state_bit(&self, f: F) @@ -102,7 +102,7 @@ where self.stmt_gen.iter().for_each(f) } - pub fn new(results: DataflowResults) -> Self { + pub fn new(results: DataflowResults<'tcx, BD>) -> Self { let bits_per_block = results.sets().bits_per_block(); let curr_state = BitSet::new_empty(bits_per_block); let stmt_gen = HybridBitSet::new_empty(bits_per_block); @@ -143,8 +143,8 @@ where } } -impl FlowsAtLocation for FlowAtLocation - where BD: BitDenotation +impl<'tcx, BD> FlowsAtLocation for FlowAtLocation<'tcx, BD> + where BD: BitDenotation<'tcx> { fn reset_to_entry_of(&mut self, bb: BasicBlock) { self.curr_state.overwrite(self.base_results.sets().on_entry_set_for(bb.index())); @@ -213,9 +213,9 @@ impl FlowsAtLocation for FlowAtLocation } -impl<'tcx, T> FlowAtLocation +impl<'tcx, T> FlowAtLocation<'tcx, T> where - T: HasMoveData<'tcx> + BitDenotation, + T: HasMoveData<'tcx> + BitDenotation<'tcx, Idx = MovePathIndex>, { pub fn has_any_child_of(&self, mpi: T::Idx) -> Option { // We process `mpi` before the loop below, for two reasons: diff --git a/src/librustc_mir/dataflow/graphviz.rs b/src/librustc_mir/dataflow/graphviz.rs index 6896c91352f..45d59b5fb9d 100644 --- a/src/librustc_mir/dataflow/graphviz.rs +++ b/src/librustc_mir/dataflow/graphviz.rs @@ -25,19 +25,19 @@ use super::DataflowBuilder; use super::DebugFormatted; pub trait MirWithFlowState<'tcx> { - type BD: BitDenotation; + type BD: BitDenotation<'tcx>; fn node_id(&self) -> NodeId; fn mir(&self) -> &Mir<'tcx>; - fn flow_state(&self) -> &DataflowState; + fn flow_state(&self) -> &DataflowState<'tcx, Self::BD>; } impl<'a, 'tcx, BD> MirWithFlowState<'tcx> for DataflowBuilder<'a, 'tcx, BD> - where BD: BitDenotation + where BD: BitDenotation<'tcx> { type BD = BD; fn node_id(&self) -> NodeId { self.node_id } fn mir(&self) -> &Mir<'tcx> { self.flow_state.mir() } - fn flow_state(&self) -> &DataflowState { &self.flow_state.flow_state } + fn flow_state(&self) -> &DataflowState<'tcx, Self::BD> { &self.flow_state.flow_state } } struct Graph<'a, 'tcx, MWF:'a, P> where @@ -53,8 +53,8 @@ pub(crate) fn print_borrowck_graph_to<'a, 'tcx, BD, P>( path: &Path, render_idx: P) -> io::Result<()> - where BD: BitDenotation, - P: Fn(&BD, BD::Idx) -> DebugFormatted + where BD: BitDenotation<'tcx>, + P: Fn(&BD, BD::Idx) -> DebugFormatted, { let g = Graph { mbcx, phantom: PhantomData, render_idx }; let mut v = Vec::new(); @@ -76,7 +76,7 @@ fn outgoing(mir: &Mir, bb: BasicBlock) -> Vec { impl<'a, 'tcx, MWF, P> dot::Labeller<'a> for Graph<'a, 'tcx, MWF, P> where MWF: MirWithFlowState<'tcx>, - P: Fn(&MWF::BD, ::Idx) -> DebugFormatted, + P: Fn(&MWF::BD, >::Idx) -> DebugFormatted, { type Node = Node; type Edge = Edge; @@ -128,7 +128,7 @@ impl<'a, 'tcx, MWF, P> dot::Labeller<'a> for Graph<'a, 'tcx, MWF, P> impl<'a, 'tcx, MWF, P> Graph<'a, 'tcx, MWF, P> where MWF: MirWithFlowState<'tcx>, - P: Fn(&MWF::BD, ::Idx) -> DebugFormatted, + P: Fn(&MWF::BD, >::Idx) -> DebugFormatted, { /// Generate the node label fn node_label_internal(&self, @@ -137,8 +137,8 @@ where MWF: MirWithFlowState<'tcx>, block: BasicBlock, mir: &Mir) -> io::Result<()> { // Header rows - const HDRS: [&'static str; 4] = ["ENTRY", "MIR", "BLOCK GENS", "BLOCK KILLS"]; - const HDR_FMT: &'static str = "bgcolor=\"grey\""; + const HDRS: [&str; 4] = ["ENTRY", "MIR", "BLOCK GENS", "BLOCK KILLS"]; + const HDR_FMT: &str = "bgcolor=\"grey\""; write!(w, "")?; diff --git a/src/librustc_mir/dataflow/impls/borrowed_locals.rs b/src/librustc_mir/dataflow/impls/borrowed_locals.rs index 1e279d8dd97..374f7071ffa 100644 --- a/src/librustc_mir/dataflow/impls/borrowed_locals.rs +++ b/src/librustc_mir/dataflow/impls/borrowed_locals.rs @@ -36,7 +36,7 @@ impl<'a, 'tcx: 'a> HaveBeenBorrowedLocals<'a, 'tcx> { } } -impl<'a, 'tcx> BitDenotation for HaveBeenBorrowedLocals<'a, 'tcx> { +impl<'a, 'tcx> BitDenotation<'tcx> for HaveBeenBorrowedLocals<'a, 'tcx> { type Idx = Local; fn name() -> &'static str { "has_been_borrowed_locals" } fn bits_per_block(&self) -> usize { @@ -71,11 +71,13 @@ impl<'a, 'tcx> BitDenotation for HaveBeenBorrowedLocals<'a, 'tcx> { }.visit_terminator(loc.block, self.mir[loc.block].terminator(), loc); } - fn propagate_call_return(&self, - _in_out: &mut BitSet, - _call_bb: mir::BasicBlock, - _dest_bb: mir::BasicBlock, - _dest_place: &mir::Place) { + fn propagate_call_return( + &self, + _in_out: &mut BitSet, + _call_bb: mir::BasicBlock, + _dest_bb: mir::BasicBlock, + _dest_place: &mir::Place<'tcx>, + ) { // Nothing to do when a call returns successfully } } diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index 27bc28ac81d..078e2fd4980 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -11,7 +11,6 @@ use borrow_check::borrow_set::{BorrowSet, BorrowData}; use borrow_check::place_ext::PlaceExt; -use rustc; use rustc::mir::{self, Location, Place, Mir}; use rustc::ty::TyCtxt; use rustc::ty::RegionVid; @@ -24,6 +23,7 @@ use dataflow::{BitDenotation, BlockSets, InitialFlow}; pub use dataflow::indexes::BorrowIndex; use borrow_check::nll::region_infer::RegionInferenceContext; use borrow_check::nll::ToRegionVid; +use borrow_check::places_conflict; use std::rc::Rc; @@ -191,17 +191,55 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { } } - fn kill_borrows_on_local(&self, - sets: &mut BlockSets, - local: &rustc::mir::Local) - { - if let Some(borrow_indexes) = self.borrow_set.local_map.get(local) { - sets.kill_all(borrow_indexes); + /// Kill any borrows that conflict with `place`. + fn kill_borrows_on_place( + &self, + sets: &mut BlockSets, + place: &Place<'tcx> + ) { + debug!("kill_borrows_on_place: place={:?}", place); + // Handle the `Place::Local(..)` case first and exit early. + if let Place::Local(local) = place { + if let Some(borrow_indices) = self.borrow_set.local_map.get(&local) { + debug!("kill_borrows_on_place: borrow_indices={:?}", borrow_indices); + sets.kill_all(borrow_indices); + return; + } + } + + // Otherwise, look at all borrows that are live and if they conflict with the assignment + // into our place then we can kill them. + let mut borrows = sets.on_entry.clone(); + let _ = borrows.union(sets.gen_set); + for borrow_index in borrows.iter() { + let borrow_data = &self.borrows()[borrow_index]; + debug!( + "kill_borrows_on_place: borrow_index={:?} borrow_data={:?}", + borrow_index, borrow_data, + ); + + // By passing `PlaceConflictBias::NoOverlap`, we conservatively assume that any given + // pair of array indices are unequal, so that when `places_conflict` returns true, we + // will be assured that two places being compared definitely denotes the same sets of + // locations. + if places_conflict::places_conflict( + self.tcx, + self.mir, + place, + &borrow_data.borrowed_place, + places_conflict::PlaceConflictBias::NoOverlap, + ) { + debug!( + "kill_borrows_on_place: (kill) borrow_index={:?} borrow_data={:?}", + borrow_index, borrow_data, + ); + sets.kill(borrow_index); + } } } } -impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> BitDenotation<'tcx> for Borrows<'a, 'gcx, 'tcx> { type Idx = BorrowIndex; fn name() -> &'static str { "borrows" } fn bits_per_block(&self) -> usize { @@ -222,7 +260,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { } fn statement_effect(&self, sets: &mut BlockSets, location: Location) { - debug!("Borrows::statement_effect sets: {:?} location: {:?}", sets, location); + debug!("Borrows::statement_effect: sets={:?} location={:?}", sets, location); let block = &self.mir.basic_blocks().get(location.block).unwrap_or_else(|| { panic!("could not find block at location {:?}", location); @@ -231,22 +269,14 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { panic!("could not find statement at location {:?}"); }); + debug!("Borrows::statement_effect: stmt={:?}", stmt); match stmt.kind { mir::StatementKind::Assign(ref lhs, ref rhs) => { // Make sure there are no remaining borrows for variables // that are assigned over. - if let Place::Local(ref local) = *lhs { - // FIXME: Handle the case in which we're assigning over - // a projection (`foo.bar`). - self.kill_borrows_on_local(sets, local); - } + self.kill_borrows_on_place(sets, lhs); - // NOTE: if/when the Assign case is revised to inspect - // the assigned_place here, make sure to also - // re-consider the current implementations of the - // propagate_call_return method. - - if let mir::Rvalue::Ref(region, _, ref place) = **rhs { + if let mir::Rvalue::Ref(_, _, ref place) = **rhs { if place.ignore_borrow( self.tcx, self.mir, @@ -258,13 +288,6 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { panic!("could not find BorrowIndex for location {:?}", location); }); - assert!(self.borrow_set.region_map - .get(®ion.to_region_vid()) - .unwrap_or_else(|| { - panic!("could not find BorrowIndexs for RegionVid {:?}", region); - }) - .contains(&index) - ); sets.gen(*index); // Issue #46746: Two-phase borrows handles @@ -274,7 +297,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { Place::Local(..) | Place::Static(..) => {} // okay Place::Projection(..) => { // ... can assign into projections, - // e.g. `box (&mut _)`. Current + // e.g., `box (&mut _)`. Current // conservative solution: force // immediate activation here. sets.gen(*index); @@ -286,19 +309,13 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { mir::StatementKind::StorageDead(local) => { // Make sure there are no remaining borrows for locals that // are gone out of scope. - self.kill_borrows_on_local(sets, &local) + self.kill_borrows_on_place(sets, &Place::Local(local)); } mir::StatementKind::InlineAsm { ref outputs, ref asm, .. } => { for (output, kind) in outputs.iter().zip(&asm.outputs) { if !kind.is_indirect && !kind.is_rw { - // Make sure there are no remaining borrows for direct - // output variables. - if let Place::Local(ref local) = *output { - // FIXME: Handle the case in which we're assigning over - // a projection (`foo.bar`). - self.kill_borrows_on_local(sets, local); - } + self.kill_borrows_on_place(sets, output); } } } @@ -307,7 +324,6 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { mir::StatementKind::SetDiscriminant { .. } | mir::StatementKind::StorageLive(..) | mir::StatementKind::Retag { .. } | - mir::StatementKind::EscapeToRaw { .. } | mir::StatementKind::AscribeUserType(..) | mir::StatementKind::Nop => {} @@ -323,16 +339,13 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { fn terminator_effect(&self, _: &mut BlockSets, _: Location) {} - fn propagate_call_return(&self, - _in_out: &mut BitSet, - _call_bb: mir::BasicBlock, - _dest_bb: mir::BasicBlock, - _dest_place: &mir::Place) { - // there are no effects on borrows from method call return... - // - // ... but if overwriting a place can affect flow state, then - // latter is not true; see NOTE on Assign case in - // statement_effect_on_borrows. + fn propagate_call_return( + &self, + _in_out: &mut BitSet, + _call_bb: mir::BasicBlock, + _dest_bb: mir::BasicBlock, + _dest_place: &mir::Place<'tcx>, + ) { } } @@ -349,4 +362,3 @@ impl<'a, 'gcx, 'tcx> InitialFlow for Borrows<'a, 'gcx, 'tcx> { false // bottom = nothing is reserved or activated yet } } - diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs index efdf9c33023..99e1eab8269 100644 --- a/src/librustc_mir/dataflow/impls/mod.rs +++ b/src/librustc_mir/dataflow/impls/mod.rs @@ -293,7 +293,7 @@ impl<'a, 'gcx, 'tcx> DefinitelyInitializedPlaces<'a, 'gcx, 'tcx> { } } -impl<'a, 'gcx, 'tcx> BitDenotation for MaybeInitializedPlaces<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> BitDenotation<'tcx> for MaybeInitializedPlaces<'a, 'gcx, 'tcx> { type Idx = MovePathIndex; fn name() -> &'static str { "maybe_init" } fn bits_per_block(&self) -> usize { @@ -331,11 +331,13 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MaybeInitializedPlaces<'a, 'gcx, 'tcx> { ) } - fn propagate_call_return(&self, - in_out: &mut BitSet, - _call_bb: mir::BasicBlock, - _dest_bb: mir::BasicBlock, - dest_place: &mir::Place) { + fn propagate_call_return( + &self, + in_out: &mut BitSet, + _call_bb: mir::BasicBlock, + _dest_bb: mir::BasicBlock, + dest_place: &mir::Place<'tcx>, + ) { // when a call returns successfully, that means we need to set // the bits for that dest_place to 1 (initialized). on_lookup_result_bits(self.tcx, self.mir, self.move_data(), @@ -344,7 +346,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MaybeInitializedPlaces<'a, 'gcx, 'tcx> { } } -impl<'a, 'gcx, 'tcx> BitDenotation for MaybeUninitializedPlaces<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> BitDenotation<'tcx> for MaybeUninitializedPlaces<'a, 'gcx, 'tcx> { type Idx = MovePathIndex; fn name() -> &'static str { "maybe_uninit" } fn bits_per_block(&self) -> usize { @@ -387,11 +389,13 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MaybeUninitializedPlaces<'a, 'gcx, 'tcx> ) } - fn propagate_call_return(&self, - in_out: &mut BitSet, - _call_bb: mir::BasicBlock, - _dest_bb: mir::BasicBlock, - dest_place: &mir::Place) { + fn propagate_call_return( + &self, + in_out: &mut BitSet, + _call_bb: mir::BasicBlock, + _dest_bb: mir::BasicBlock, + dest_place: &mir::Place<'tcx>, + ) { // when a call returns successfully, that means we need to set // the bits for that dest_place to 0 (initialized). on_lookup_result_bits(self.tcx, self.mir, self.move_data(), @@ -400,7 +404,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MaybeUninitializedPlaces<'a, 'gcx, 'tcx> } } -impl<'a, 'gcx, 'tcx> BitDenotation for DefinitelyInitializedPlaces<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> BitDenotation<'tcx> for DefinitelyInitializedPlaces<'a, 'gcx, 'tcx> { type Idx = MovePathIndex; fn name() -> &'static str { "definite_init" } fn bits_per_block(&self) -> usize { @@ -441,11 +445,13 @@ impl<'a, 'gcx, 'tcx> BitDenotation for DefinitelyInitializedPlaces<'a, 'gcx, 'tc ) } - fn propagate_call_return(&self, - in_out: &mut BitSet, - _call_bb: mir::BasicBlock, - _dest_bb: mir::BasicBlock, - dest_place: &mir::Place) { + fn propagate_call_return( + &self, + in_out: &mut BitSet, + _call_bb: mir::BasicBlock, + _dest_bb: mir::BasicBlock, + dest_place: &mir::Place<'tcx>, + ) { // when a call returns successfully, that means we need to set // the bits for that dest_place to 1 (initialized). on_lookup_result_bits(self.tcx, self.mir, self.move_data(), @@ -454,7 +460,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for DefinitelyInitializedPlaces<'a, 'gcx, 'tc } } -impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedPlaces<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> BitDenotation<'tcx> for EverInitializedPlaces<'a, 'gcx, 'tcx> { type Idx = InitIndex; fn name() -> &'static str { "ever_init" } fn bits_per_block(&self) -> usize { @@ -488,7 +494,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedPlaces<'a, 'gcx, 'tcx> { // // FIXME(#46525): We *need* to do this for StorageLive as well as // StorageDead, because lifetimes of match bindings with guards are - // weird - i.e. this code + // weird - i.e., this code // // ``` // fn main() { @@ -530,11 +536,13 @@ impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedPlaces<'a, 'gcx, 'tcx> { ); } - fn propagate_call_return(&self, - in_out: &mut BitSet, - call_bb: mir::BasicBlock, - _dest_bb: mir::BasicBlock, - _dest_place: &mir::Place) { + fn propagate_call_return( + &self, + in_out: &mut BitSet, + call_bb: mir::BasicBlock, + _dest_bb: mir::BasicBlock, + _dest_place: &mir::Place<'tcx>, + ) { let move_data = self.move_data(); let bits_per_block = self.bits_per_block(); let init_loc_map = &move_data.init_loc_map; diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs index c8faa34df8a..caf3d3f7ab6 100644 --- a/src/librustc_mir/dataflow/impls/storage_liveness.rs +++ b/src/librustc_mir/dataflow/impls/storage_liveness.rs @@ -29,7 +29,7 @@ impl<'a, 'tcx: 'a> MaybeStorageLive<'a, 'tcx> { } } -impl<'a, 'tcx> BitDenotation for MaybeStorageLive<'a, 'tcx> { +impl<'a, 'tcx> BitDenotation<'tcx> for MaybeStorageLive<'a, 'tcx> { type Idx = Local; fn name() -> &'static str { "maybe_storage_live" } fn bits_per_block(&self) -> usize { @@ -58,11 +58,13 @@ impl<'a, 'tcx> BitDenotation for MaybeStorageLive<'a, 'tcx> { // Terminators have no effect } - fn propagate_call_return(&self, - _in_out: &mut BitSet, - _call_bb: mir::BasicBlock, - _dest_bb: mir::BasicBlock, - _dest_place: &mir::Place) { + fn propagate_call_return( + &self, + _in_out: &mut BitSet, + _call_bb: mir::BasicBlock, + _dest_bb: mir::BasicBlock, + _dest_place: &mir::Place<'tcx>, + ) { // Nothing to do when a call returns successfully } } diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index c19145636e6..efdf0c1efcb 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -44,7 +44,9 @@ pub mod move_paths; pub(crate) use self::move_paths::indexes; -pub(crate) struct DataflowBuilder<'a, 'tcx: 'a, BD> where BD: BitDenotation +pub(crate) struct DataflowBuilder<'a, 'tcx: 'a, BD> +where + BD: BitDenotation<'tcx> { node_id: ast::NodeId, flow_state: DataflowAnalysis<'a, 'tcx, BD>, @@ -71,7 +73,7 @@ impl fmt::Debug for DebugFormatted { } } -pub(crate) trait Dataflow { +pub(crate) trait Dataflow<'tcx, BD: BitDenotation<'tcx>> { /// Sets up and runs the dataflow problem, using `p` to render results if /// implementation so chooses. fn dataflow

(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> DebugFormatted { @@ -87,7 +89,9 @@ pub(crate) trait Dataflow { fn propagate(&mut self); } -impl<'a, 'tcx: 'a, BD> Dataflow for DataflowBuilder<'a, 'tcx, BD> where BD: BitDenotation +impl<'a, 'tcx: 'a, BD> Dataflow<'tcx, BD> for DataflowBuilder<'a, 'tcx, BD> +where + BD: BitDenotation<'tcx> { fn dataflow

(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> DebugFormatted { self.flow_state.build_sets(); @@ -127,21 +131,21 @@ pub(crate) fn do_dataflow<'a, 'gcx, 'tcx, BD, P>(tcx: TyCtxt<'a, 'gcx, 'tcx>, dead_unwinds: &BitSet, bd: BD, p: P) - -> DataflowResults - where BD: BitDenotation + InitialFlow, + -> DataflowResults<'tcx, BD> + where BD: BitDenotation<'tcx> + InitialFlow, P: Fn(&BD, BD::Idx) -> DebugFormatted { let flow_state = DataflowAnalysis::new(mir, dead_unwinds, bd); flow_state.run(tcx, node_id, attributes, p) } -impl<'a, 'gcx: 'tcx, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> where BD: BitDenotation +impl<'a, 'gcx: 'tcx, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> where BD: BitDenotation<'tcx> { pub(crate) fn run

(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, node_id: ast::NodeId, attributes: &[ast::Attribute], - p: P) -> DataflowResults + p: P) -> DataflowResults<'tcx, BD> where P: Fn(&BD, BD::Idx) -> DebugFormatted { let name_found = |sess: &Session, attrs: &[ast::Attribute], name| -> Option { @@ -173,12 +177,12 @@ impl<'a, 'gcx: 'tcx, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> where BD: BitD } } -struct PropagationContext<'b, 'a: 'b, 'tcx: 'a, O> where O: 'b + BitDenotation +struct PropagationContext<'b, 'a: 'b, 'tcx: 'a, O> where O: 'b + BitDenotation<'tcx> { builder: &'b mut DataflowAnalysis<'a, 'tcx, O>, } -impl<'a, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> where BD: BitDenotation +impl<'a, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> where BD: BitDenotation<'tcx> { fn propagate(&mut self) { let mut temp = BitSet::new_empty(self.flow_state.sets.bits_per_block); @@ -228,7 +232,7 @@ impl<'a, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> where BD: BitDenotation } } -impl<'b, 'a: 'b, 'tcx: 'a, BD> PropagationContext<'b, 'a, 'tcx, BD> where BD: BitDenotation +impl<'b, 'a: 'b, 'tcx: 'a, BD> PropagationContext<'b, 'a, 'tcx, BD> where BD: BitDenotation<'tcx> { fn walk_cfg(&mut self, in_out: &mut BitSet) { let mut dirty_queue: WorkQueue = @@ -259,7 +263,7 @@ fn dataflow_path(context: &str, path: &str) -> PathBuf { path } -impl<'a, 'tcx: 'a, BD> DataflowBuilder<'a, 'tcx, BD> where BD: BitDenotation +impl<'a, 'tcx: 'a, BD> DataflowBuilder<'a, 'tcx, BD> where BD: BitDenotation<'tcx> { fn pre_dataflow_instrumentation

(&self, p: P) -> io::Result<()> where P: Fn(&BD, BD::Idx) -> DebugFormatted @@ -290,7 +294,7 @@ impl<'a, 'tcx: 'a, BD> DataflowBuilder<'a, 'tcx, BD> where BD: BitDenotation /// It abstracts over the FlowState and also completely hides the /// underlying flow analysis results, because it needs to handle cases /// where we are combining the results of *multiple* flow analyses -/// (e.g. borrows + inits + uninits). +/// (e.g., borrows + inits + uninits). pub(crate) trait DataflowResultsConsumer<'a, 'tcx: 'a> { type FlowState: FlowsAtLocation; @@ -347,10 +351,10 @@ pub(crate) trait DataflowResultsConsumer<'a, 'tcx: 'a> { fn mir(&self) -> &'a Mir<'tcx>; } -pub fn state_for_location<'tcx, T: BitDenotation>(loc: Location, - analysis: &T, - result: &DataflowResults, - mir: &Mir<'tcx>) +pub fn state_for_location<'tcx, T: BitDenotation<'tcx>>(loc: Location, + analysis: &T, + result: &DataflowResults<'tcx, T>, + mir: &Mir<'tcx>) -> BitSet { let mut on_entry = result.sets().on_entry_set_for(loc.block.index()).to_owned(); let mut kill_set = on_entry.to_hybrid(); @@ -381,25 +385,25 @@ pub fn state_for_location<'tcx, T: BitDenotation>(loc: Location, gen_set.to_dense() } -pub struct DataflowAnalysis<'a, 'tcx: 'a, O> where O: BitDenotation +pub struct DataflowAnalysis<'a, 'tcx: 'a, O> where O: BitDenotation<'tcx> { - flow_state: DataflowState, + flow_state: DataflowState<'tcx, O>, dead_unwinds: &'a BitSet, mir: &'a Mir<'tcx>, } -impl<'a, 'tcx: 'a, O> DataflowAnalysis<'a, 'tcx, O> where O: BitDenotation +impl<'a, 'tcx: 'a, O> DataflowAnalysis<'a, 'tcx, O> where O: BitDenotation<'tcx> { - pub fn results(self) -> DataflowResults { + pub fn results(self) -> DataflowResults<'tcx, O> { DataflowResults(self.flow_state) } pub fn mir(&self) -> &'a Mir<'tcx> { self.mir } } -pub struct DataflowResults(pub(crate) DataflowState) where O: BitDenotation; +pub struct DataflowResults<'tcx, O>(pub(crate) DataflowState<'tcx, O>) where O: BitDenotation<'tcx>; -impl DataflowResults { +impl<'tcx, O: BitDenotation<'tcx>> DataflowResults<'tcx, O> { pub fn sets(&self) -> &AllSets { &self.0.sets } @@ -411,7 +415,7 @@ impl DataflowResults { /// State of a dataflow analysis; couples a collection of bit sets /// with operator used to initialize and merge bits during analysis. -pub struct DataflowState +pub struct DataflowState<'tcx, O: BitDenotation<'tcx>> { /// All the sets for the analysis. (Factored into its /// own structure so that we can borrow it mutably @@ -422,7 +426,7 @@ pub struct DataflowState pub(crate) operator: O, } -impl DataflowState { +impl<'tcx, O: BitDenotation<'tcx>> DataflowState<'tcx, O> { pub(crate) fn interpret_set<'c, P>(&self, o: &'c O, set: &BitSet, @@ -553,7 +557,7 @@ impl AllSets { /// Parameterization for the precise form of data flow that is used. /// `InitialFlow` handles initializing the bitvectors before any /// code is inspected by the analysis. Analyses that need more nuanced -/// initialization (e.g. they need to consult the results of some other +/// initialization (e.g., they need to consult the results of some other /// dataflow analysis to set up the initial bitvectors) should not /// implement this. pub trait InitialFlow { @@ -561,7 +565,7 @@ pub trait InitialFlow { fn bottom_value() -> bool; } -pub trait BitDenotation: BitSetOperator { +pub trait BitDenotation<'tcx>: BitSetOperator { /// Specifies what index type is used to access the bitvector. type Idx: Idx; @@ -592,7 +596,7 @@ pub trait BitDenotation: BitSetOperator { /// A name describing the dataflow analysis that this /// BitDenotation is supporting. The name should be something - /// suitable for plugging in as part of a filename e.g. avoid + /// suitable for plugging in as part of a filename e.g., avoid /// space-characters or other things that tend to look bad on a /// file system, like slashes or periods. It is also better for /// the name to be reasonably short, again because it will be @@ -687,14 +691,16 @@ pub trait BitDenotation: BitSetOperator { /// be better to represent this as an additional gen- and /// kill-sets associated with each edge coming out of the basic /// block. - fn propagate_call_return(&self, - in_out: &mut BitSet, - call_bb: mir::BasicBlock, - dest_bb: mir::BasicBlock, - dest_place: &mir::Place); + fn propagate_call_return( + &self, + in_out: &mut BitSet, + call_bb: mir::BasicBlock, + dest_bb: mir::BasicBlock, + dest_place: &mir::Place<'tcx>, + ); } -impl<'a, 'tcx, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation +impl<'a, 'tcx, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation<'tcx> { pub fn new(mir: &'a Mir<'tcx>, dead_unwinds: &'a BitSet, @@ -726,8 +732,7 @@ impl<'a, 'tcx, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation } } -impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation -{ +impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation<'tcx> { /// Propagates the bits of `in_out` into all the successors of `bb`, /// using bitwise operator denoted by `self.operator`. /// @@ -739,12 +744,12 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation /// To reflect this, the `propagate_call_return` method of the /// `BitDenotation` mutates `in_out` when propagating `in_out` via /// a call terminator; such mutation is performed *last*, to - /// ensure its side-effects do not leak elsewhere (e.g. into + /// ensure its side-effects do not leak elsewhere (e.g., into /// unwind target). fn propagate_bits_into_graph_successors_of( &mut self, in_out: &mut BitSet, - (bb, bb_data): (mir::BasicBlock, &mir::BasicBlockData), + (bb, bb_data): (mir::BasicBlock, &mir::BasicBlockData<'tcx>), dirty_list: &mut WorkQueue) { match bb_data.terminator().kind { diff --git a/src/librustc_mir/dataflow/move_paths/abs_domain.rs b/src/librustc_mir/dataflow/move_paths/abs_domain.rs index 4d20857bc2e..186e5f5f5f0 100644 --- a/src/librustc_mir/dataflow/move_paths/abs_domain.rs +++ b/src/librustc_mir/dataflow/move_paths/abs_domain.rs @@ -10,7 +10,7 @@ //! The move-analysis portion of borrowck needs to work in an abstract //! domain of lifted Places. Most of the Place variants fall into a -//! one-to-one mapping between the concrete and abstract (e.g. a +//! one-to-one mapping between the concrete and abstract (e.g., a //! field-deref on a local-variable, `x.field`, has the same meaning //! in both domains). Indexed-Projections are the exception: `a[x]` //! needs to be treated as mapping to the same move path as `a[y]` as diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index 7fe27e97d3d..d201a355a2a 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -302,7 +302,6 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> { "SetDiscriminant should not exist during borrowck"); } StatementKind::Retag { .. } | - StatementKind::EscapeToRaw { .. } | StatementKind::AscribeUserType(..) | StatementKind::Nop => {} } diff --git a/src/librustc_mir/diagnostics.rs b/src/librustc_mir/diagnostics.rs index 56a9daf84f7..ec5617d7052 100644 --- a/src/librustc_mir/diagnostics.rs +++ b/src/librustc_mir/diagnostics.rs @@ -606,7 +606,7 @@ static X: i32 = 1; const C: i32 = 2; // these three are not allowed: -const CR: &'static mut i32 = &mut C; +const CR: &mut i32 = &mut C; static STATIC_REF: &'static mut i32 = &mut X; static CONST_REF: &'static mut i32 = &mut C; ``` @@ -1163,7 +1163,7 @@ You can also have this error while using a cell type: use std::cell::Cell; const A: Cell = Cell::new(1); -const B: &'static Cell = &A; +const B: &Cell = &A; // error: cannot borrow a constant which may contain interior mutability, // create a static instead @@ -1171,10 +1171,10 @@ const B: &'static Cell = &A; struct C { a: Cell } const D: C = C { a: Cell::new(1) }; -const E: &'static Cell = &D.a; // error +const E: &Cell = &D.a; // error // or: -const F: &'static C = &D; // error +const F: &C = &D; // error ``` This is because cell types do operations that are not thread-safe. Due to this, diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs index d56ddcb4944..beb035d82b1 100644 --- a/src/librustc_mir/hair/cx/block.rs +++ b/src/librustc_mir/hair/cx/block.rs @@ -55,9 +55,9 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, -> Vec> { let mut result = vec![]; for (index, stmt) in stmts.iter().enumerate() { - let hir_id = cx.tcx.hir.node_to_hir_id(stmt.node.id()); + let hir_id = cx.tcx.hir().node_to_hir_id(stmt.node.id()); let opt_dxn_ext = cx.region_scope_tree.opt_destruction_scope(hir_id.local_id); - let stmt_span = StatementSpan(cx.tcx.hir.span(stmt.node.id())); + let stmt_span = StatementSpan(cx.tcx.hir().span(stmt.node.id())); match stmt.node { hir::StmtKind::Expr(ref expr, _) | hir::StmtKind::Semi(ref expr, _) => { diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 2e9edf20c57..f93dbce97b5 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -181,7 +181,7 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, // To ensure that both implicit and explicit coercions are // handled the same way, we insert an extra layer of indirection here. - // For explicit casts (e.g. 'foo as *const T'), the source of the 'Use' + // For explicit casts (e.g., 'foo as *const T'), the source of the 'Use' // will be an ExprKind::Hair with the appropriate cast expression. Here, // we make our Use source the generated Cast from the original coercion. // @@ -372,6 +372,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, // FIXME(eddyb) use logical ops in constants when // they can handle that kind of control-flow. (hir::BinOpKind::And, hir::Constness::Const) => { + cx.control_flow_destroyed.push(( + op.span, + "`&&` operator".into(), + )); ExprKind::Binary { op: BinOp::BitAnd, lhs: lhs.to_ref(), @@ -379,6 +383,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } } (hir::BinOpKind::Or, hir::Constness::Const) => { + cx.control_flow_destroyed.push(( + op.span, + "`||` operator".into(), + )); ExprKind::Binary { op: BinOp::BitOr, lhs: lhs.to_ref(), @@ -556,7 +564,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, // Now comes the rote stuff: hir::ExprKind::Repeat(ref v, ref count) => { - let def_id = cx.tcx.hir.local_def_id(count.id); + let def_id = cx.tcx.hir().local_def_id(count.id); let substs = Substs::identity_for_item(cx.tcx.global_tcx(), def_id); let instance = ty::Instance::resolve( cx.tcx.global_tcx(), @@ -588,7 +596,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, match dest.target_id { Ok(target_id) => ExprKind::Break { label: region::Scope { - id: cx.tcx.hir.node_to_hir_id(target_id).local_id, + id: cx.tcx.hir().node_to_hir_id(target_id).local_id, data: region::ScopeData::Node }, value: value.to_ref(), @@ -600,7 +608,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, match dest.target_id { Ok(loop_id) => ExprKind::Continue { label: region::Scope { - id: cx.tcx.hir.node_to_hir_id(loop_id).local_id, + id: cx.tcx.hir().node_to_hir_id(loop_id).local_id, data: region::ScopeData::Node }, }, @@ -974,17 +982,17 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, var_id, index, closure_expr_id); - let var_hir_id = cx.tcx.hir.node_to_hir_id(var_id); + let var_hir_id = cx.tcx.hir().node_to_hir_id(var_id); let var_ty = cx.tables().node_id_to_type(var_hir_id); // FIXME free regions in closures are not right let closure_ty = cx.tables() - .node_id_to_type(cx.tcx.hir.node_to_hir_id(closure_expr_id)); + .node_id_to_type(cx.tcx.hir().node_to_hir_id(closure_expr_id)); // FIXME we're just hard-coding the idea that the // signature will be &self or &mut self and hence will // have a bound region with number 0 - let closure_def_id = cx.tcx.hir.local_def_id(closure_expr_id); + let closure_def_id = cx.tcx.hir().local_def_id(closure_expr_id); let region = ty::ReFree(ty::FreeRegion { scope: closure_def_id, bound_region: ty::BoundRegion::BrAnon(0), @@ -1176,10 +1184,10 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, freevar: &hir::Freevar, freevar_ty: Ty<'tcx>) -> ExprRef<'tcx> { - let var_hir_id = cx.tcx.hir.node_to_hir_id(freevar.var_id()); + let var_hir_id = cx.tcx.hir().node_to_hir_id(freevar.var_id()); let upvar_id = ty::UpvarId { var_path: ty::UpvarPath { hir_id: var_hir_id }, - closure_expr_id: cx.tcx.hir.local_def_id(closure_expr.id).to_local(), + closure_expr_id: cx.tcx.hir().local_def_id(closure_expr.id).to_local(), }; let upvar_capture = cx.tables().upvar_capture(upvar_id); let temp_lifetime = cx.region_scope_tree.temporary_scope(closure_expr.hir_id.local_id); @@ -1212,7 +1220,7 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } } -/// Converts a list of named fields (i.e. for struct-like struct/enum ADTs) into FieldExprRef. +/// Converts a list of named fields (i.e., for struct-like struct/enum ADTs) into FieldExprRef. fn field_refs<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, fields: &'tcx [hir::Field]) -> Vec> { diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index c414088b653..5d8732bb8ae 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -56,14 +56,17 @@ pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { /// True if this constant/function needs overflow checks. check_overflow: bool, + + /// See field with the same name on `Mir` + control_flow_destroyed: Vec<(Span, String)>, } impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, src_id: ast::NodeId) -> Cx<'a, 'gcx, 'tcx> { let tcx = infcx.tcx; - let src_def_id = tcx.hir.local_def_id(src_id); - let body_owner_kind = tcx.hir.body_owner_kind(src_id); + let src_def_id = tcx.hir().local_def_id(src_id); + let body_owner_kind = tcx.hir().body_owner_kind(src_id); let constness = match body_owner_kind { hir::BodyOwnerKind::Const | @@ -71,7 +74,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { hir::BodyOwnerKind::Fn => hir::Constness::NotConst, }; - let attrs = tcx.hir.attrs(src_id); + let attrs = tcx.hir().attrs(src_id); // Some functions always have overflow checks enabled, // however, they may not get codegen'd, depending on @@ -96,9 +99,13 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { constness, body_owner_kind, check_overflow, + control_flow_destroyed: Vec::new(), } } + pub fn control_flow_destroyed(self) -> Vec<(Span, String)> { + self.control_flow_destroyed + } } impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { @@ -157,7 +164,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { pub fn pattern_from_hir(&mut self, p: &hir::Pat) -> Pattern<'tcx> { let tcx = self.tcx.global_tcx(); - let p = match tcx.hir.get(p.id) { + let p = match tcx.hir().get(p.id) { Node::Pat(p) | Node::Binding(p) => p, node => bug!("pattern became {:?}", node) }; @@ -202,7 +209,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { } fn lint_level_of(&self, node_id: ast::NodeId) -> LintLevel { - let hir_id = self.tcx.hir.definitions().node_to_hir_id(node_id); + let hir_id = self.tcx.hir().definitions().node_to_hir_id(node_id); let has_lint_level = self.tcx.dep_graph.with_ignore(|| { self.tcx.lint_levels(LOCAL_CRATE).lint_level_set(hir_id).is_some() }); @@ -253,11 +260,11 @@ fn lint_level_for_hir_id(tcx: TyCtxt, mut id: ast::NodeId) -> ast::NodeId { tcx.dep_graph.with_ignore(|| { let sets = tcx.lint_levels(LOCAL_CRATE); loop { - let hir_id = tcx.hir.definitions().node_to_hir_id(id); + let hir_id = tcx.hir().definitions().node_to_hir_id(id); if sets.lint_level_set(hir_id).is_some() { return id } - let next = tcx.hir.get_parent_node(id); + let next = tcx.hir().get_parent_node(id); if next == id { bug!("lint traversal reached the root of the crate"); } diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index e604b118eac..b254fce4b76 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -29,7 +29,7 @@ pub mod cx; mod constant; pub mod pattern; -pub use self::pattern::{BindingMode, Pattern, PatternKind, FieldPattern}; +pub use self::pattern::{BindingMode, Pattern, PatternKind, PatternRange, FieldPattern}; pub(crate) use self::pattern::{PatternTypeProjection, PatternTypeProjections}; mod util; diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 0570cd278f3..7ec6bbfe3c1 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -29,9 +29,9 @@ /// /// If we have this predicate, then we can easily compute both exhaustiveness of an /// entire set of patterns and the individual usefulness of each one. -/// (a) the set of patterns is exhaustive iff `U(P, _)` is false (i.e. adding a wildcard +/// (a) the set of patterns is exhaustive iff `U(P, _)` is false (i.e., adding a wildcard /// match doesn't increase the number of values we're matching) -/// (b) a pattern `p_i` is not useful if `U(P[0..=(i-1), p_i)` is false (i.e. adding a +/// (b) a pattern `p_i` is not useful if `U(P[0..=(i-1), p_i)` is false (i.e., adding a /// pattern to those that have come before it doesn't increase the number of values /// we're matching). /// @@ -90,17 +90,17 @@ /// /// The algorithm for computing `U` /// ------------------------------- -/// The algorithm is inductive (on the number of columns: i.e. components of tuple patterns). +/// The algorithm is inductive (on the number of columns: i.e., components of tuple patterns). /// That means we're going to check the components from left-to-right, so the algorithm /// operates principally on the first component of the matrix and new pattern `p_{m + 1}`. /// This algorithm is realised in the `is_useful` function. /// -/// Base case. (`n = 0`, i.e. an empty tuple pattern) -/// - If `P` already contains an empty pattern (i.e. if the number of patterns `m > 0`), +/// Base case. (`n = 0`, i.e., an empty tuple pattern) +/// - If `P` already contains an empty pattern (i.e., if the number of patterns `m > 0`), /// then `U(P, p_{m + 1})` is false. /// - Otherwise, `P` must be empty, so `U(P, p_{m + 1})` is true. /// -/// Inductive step. (`n > 0`, i.e. whether there's at least one column +/// Inductive step. (`n > 0`, i.e., whether there's at least one column /// [which may then be expanded into further columns later]) /// We're going to match on the new pattern, `p_{m + 1}`. /// - If `p_{m + 1} == c(r_1, .., r_a)`, then we have a constructor pattern. @@ -113,7 +113,7 @@ /// + All the constructors of the first component of the type exist within /// all the rows (after having expanded OR-patterns). In this case: /// `U(P, p_{m + 1}) := ∨(k ϵ constructors) U(S(k, P), S(k, p_{m + 1}))` -/// I.e. the pattern `p_{m + 1}` is only useful when all the constructors are +/// I.e., the pattern `p_{m + 1}` is only useful when all the constructors are /// present *if* its later components are useful for the respective constructors /// covered by `p_{m + 1}` (usually a single constructor, but all in the case of `_`). /// + Some constructors are not present in the existing rows (after having expanded @@ -156,14 +156,14 @@ /// - When we're testing for usefulness of a pattern and the pattern's first component is a /// wildcard. /// + If all the constructors appear in the matrix, we have a slight complication. By default, -/// the behaviour (i.e. a disjunction over specialised matrices for each constructor) is +/// the behaviour (i.e., a disjunction over specialised matrices for each constructor) is /// invalid, because we want a disjunction over every *integer* in each range, not just a /// disjunction over every range. This is a bit more tricky to deal with: essentially we need /// to form equivalence classes of subranges of the constructor range for which the behaviour /// of the matrix `P` and new pattern `p_{m + 1}` are the same. This is described in more /// detail in `split_grouped_constructors`. /// + If some constructors are missing from the matrix, it turns out we don't need to do -/// anything special (because we know none of the integers are actually wildcards: i.e. we +/// anything special (because we know none of the integers are actually wildcards: i.e., we /// can't span wildcards using ranges). use self::Constructor::*; @@ -173,16 +173,16 @@ use self::WitnessPreference::*; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::Idx; -use super::{FieldPattern, Pattern, PatternKind}; +use super::{FieldPattern, Pattern, PatternKind, PatternRange}; use super::{PatternFoldable, PatternFolder, compare_const_vals}; use rustc::hir::def_id::DefId; use rustc::hir::RangeEnd; -use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; -use rustc::ty::layout::{Integer, IntegerExt, VariantIdx}; +use rustc::ty::{self, Ty, TyCtxt, TypeFoldable, Const}; +use rustc::ty::layout::{Integer, IntegerExt, VariantIdx, Size}; use rustc::mir::Field; -use rustc::mir::interpret::ConstValue; +use rustc::mir::interpret::{ConstValue, Pointer, Scalar}; use rustc::util::common::ErrorReported; use syntax::attr::{SignedInt, UnsignedInt}; @@ -190,6 +190,7 @@ use syntax_pos::{Span, DUMMY_SP}; use arena::TypedArena; +use smallvec::{SmallVec, smallvec}; use std::cmp::{self, Ordering, min, max}; use std::fmt; use std::iter::{FromIterator, IntoIterator}; @@ -199,14 +200,60 @@ use std::u128; pub fn expand_pattern<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>, pat: Pattern<'tcx>) -> &'a Pattern<'tcx> { - cx.pattern_arena.alloc(LiteralExpander.fold_pattern(&pat)) + cx.pattern_arena.alloc(LiteralExpander { tcx: cx.tcx }.fold_pattern(&pat)) } -struct LiteralExpander; -impl<'tcx> PatternFolder<'tcx> for LiteralExpander { +struct LiteralExpander<'a, 'tcx> { + tcx: TyCtxt<'a, 'tcx, 'tcx> +} + +impl<'a, 'tcx> LiteralExpander<'a, 'tcx> { + /// Derefs `val` and potentially unsizes the value if `crty` is an array and `rty` a slice. + /// + /// `crty` and `rty` can differ because you can use array constants in the presence of slice + /// patterns. So the pattern may end up being a slice, but the constant is an array. We convert + /// the array to a slice in that case. + fn fold_const_value_deref( + &mut self, + val: ConstValue<'tcx>, + // the pattern's pointee type + rty: Ty<'tcx>, + // the constant's pointee type + crty: Ty<'tcx>, + ) -> ConstValue<'tcx> { + match (val, &crty.sty, &rty.sty) { + // the easy case, deref a reference + (ConstValue::Scalar(Scalar::Ptr(p)), x, y) if x == y => ConstValue::ByRef( + p.alloc_id, + self.tcx.alloc_map.lock().unwrap_memory(p.alloc_id), + p.offset, + ), + // unsize array to slice if pattern is array but match value or other patterns are slice + (ConstValue::Scalar(Scalar::Ptr(p)), ty::Array(t, n), ty::Slice(u)) => { + assert_eq!(t, u); + ConstValue::ScalarPair( + Scalar::Ptr(p), + n.val.try_to_scalar().unwrap(), + ) + }, + // fat pointers stay the same + (ConstValue::ScalarPair(..), _, _) => val, + // FIXME(oli-obk): this is reachable for `const FOO: &&&u32 = &&&42;` being used + _ => bug!("cannot deref {:#?}, {} -> {}", val, crty, rty), + } + } +} + +impl<'a, 'tcx> PatternFolder<'tcx> for LiteralExpander<'a, 'tcx> { fn fold_pattern(&mut self, pat: &Pattern<'tcx>) -> Pattern<'tcx> { match (&pat.ty.sty, &*pat.kind) { - (&ty::Ref(_, rty, _), &PatternKind::Constant { ref value }) => { + ( + &ty::Ref(_, rty, _), + &PatternKind::Constant { value: Const { + val, + ty: ty::TyS { sty: ty::Ref(_, crty, _), .. }, + } }, + ) => { Pattern { ty: pat.ty, span: pat.span, @@ -214,7 +261,11 @@ impl<'tcx> PatternFolder<'tcx> for LiteralExpander { subpattern: Pattern { ty: rty, span: pat.span, - kind: box PatternKind::Constant { value: value.clone() }, + kind: box PatternKind::Constant { value: Const::from_const_value( + self.tcx, + self.fold_const_value_deref(*val, rty, crty), + rty, + ) }, } } } @@ -237,14 +288,16 @@ impl<'tcx> Pattern<'tcx> { } } -pub struct Matrix<'a, 'tcx: 'a>(Vec>>); +/// A 2D matrix. Nx1 matrices are very common, which is why `SmallVec[_; 2]` +/// works well for each row. +pub struct Matrix<'p, 'tcx: 'p>(Vec; 2]>>); -impl<'a, 'tcx> Matrix<'a, 'tcx> { +impl<'p, 'tcx> Matrix<'p, 'tcx> { pub fn empty() -> Self { Matrix(vec![]) } - pub fn push(&mut self, row: Vec<&'a Pattern<'tcx>>) { + pub fn push(&mut self, row: SmallVec<[&'p Pattern<'tcx>; 2]>) { self.0.push(row) } } @@ -261,7 +314,7 @@ impl<'a, 'tcx> Matrix<'a, 'tcx> { /// ++++++++++++++++++++++++++ /// + _ + [_, _, ..tail] + /// ++++++++++++++++++++++++++ -impl<'a, 'tcx> fmt::Debug for Matrix<'a, 'tcx> { +impl<'p, 'tcx> fmt::Debug for Matrix<'p, 'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "\n")?; @@ -293,8 +346,9 @@ impl<'a, 'tcx> fmt::Debug for Matrix<'a, 'tcx> { } } -impl<'a, 'tcx> FromIterator>> for Matrix<'a, 'tcx> { - fn from_iter>>>(iter: T) -> Self +impl<'p, 'tcx> FromIterator; 2]>> for Matrix<'p, 'tcx> { + fn from_iter(iter: T) -> Self + where T: IntoIterator; 2]>> { Matrix(iter.into_iter().collect()) } @@ -371,7 +425,7 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> { #[derive(Clone, Debug, PartialEq)] pub enum Constructor<'tcx> { /// The constructor of all patterns that don't vary by constructor, - /// e.g. struct patterns and fixed-length arrays. + /// e.g., struct patterns and fixed-length arrays. Single, /// Enum variants. Variant(DefId), @@ -488,7 +542,7 @@ impl<'tcx> Witness<'tcx> { /// patterns expanded by the specialization step. /// /// When a pattern P is discovered to be useful, this function is used bottom-up - /// to reconstruct a complete witness, e.g. a pattern P' that covers a subset + /// to reconstruct a complete witness, e.g., a pattern P' that covers a subset /// of values, V, where each value in that set is not covered by any previously /// used patterns and is covered by the pattern P'. Examples: /// @@ -550,12 +604,12 @@ impl<'tcx> Witness<'tcx> { _ => { match *ctor { ConstantValue(value) => PatternKind::Constant { value }, - ConstantRange(lo, hi, ty, end) => PatternKind::Range { + ConstantRange(lo, hi, ty, end) => PatternKind::Range(PatternRange { lo: ty::Const::from_bits(cx.tcx, lo, ty::ParamEnv::empty().and(ty)), hi: ty::Const::from_bits(cx.tcx, hi, ty::ParamEnv::empty().and(ty)), ty, end, - }, + }), _ => PatternKind::Wild, } } @@ -584,7 +638,6 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, -> Vec> { debug!("all_constructors({:?})", pcx.ty); - let exhaustive_integer_patterns = cx.tcx.features().exhaustive_integer_patterns; let ctors = match pcx.ty.sty { ty::Bool => { [true, false].iter().map(|&b| { @@ -614,7 +667,7 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, .map(|v| Variant(v.did)) .collect() } - ty::Char if exhaustive_integer_patterns => { + ty::Char => { vec![ // The valid Unicode Scalar Value ranges. ConstantRange('\u{0000}' as u128, @@ -629,14 +682,14 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, ), ] } - ty::Int(ity) if exhaustive_integer_patterns => { + ty::Int(ity) => { // FIXME(49937): refactor these bit manipulations into interpret. let bits = Integer::from_attr(&cx.tcx, SignedInt(ity)).size().bits() as u128; let min = 1u128 << (bits - 1); let max = (1u128 << (bits - 1)) - 1; vec![ConstantRange(min, max, pcx.ty, RangeEnd::Included)] } - ty::Uint(uty) if exhaustive_integer_patterns => { + ty::Uint(uty) => { // FIXME(49937): refactor these bit manipulations into interpret. let bits = Integer::from_attr(&cx.tcx, UnsignedInt(uty)).size().bits() as u128; let max = !0u128 >> (128 - bits); @@ -729,15 +782,17 @@ fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>( for row in patterns { match *row.kind { PatternKind::Constant { value } => { - if let Some(ptr) = value.to_ptr() { - let is_array_ptr = value.ty - .builtin_deref(true) - .and_then(|t| t.ty.builtin_index()) - .map_or(false, |t| t == cx.tcx.types.u8); - if is_array_ptr { - let alloc = cx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id); - max_fixed_len = cmp::max(max_fixed_len, alloc.bytes.len() as u64); - } + // extract the length of an array/slice from a constant + match (value.val, &value.ty.sty) { + (_, ty::Array(_, n)) => max_fixed_len = cmp::max( + max_fixed_len, + n.unwrap_usize(cx.tcx), + ), + (ConstValue::ScalarPair(_, n), ty::Slice(_)) => max_fixed_len = cmp::max( + max_fixed_len, + n.to_usize(&cx.tcx).unwrap(), + ), + _ => {}, } } PatternKind::Slice { ref prefix, slice: None, ref suffix } => { @@ -764,7 +819,7 @@ fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>( /// straightforward. See `signed_bias` for details. /// /// `IntRange` is never used to encode an empty range or a "range" that wraps -/// around the (offset) space: i.e. `range.lo <= range.hi`. +/// around the (offset) space: i.e., `range.lo <= range.hi`. #[derive(Clone)] struct IntRange<'tcx> { pub range: RangeInclusive, @@ -775,8 +830,17 @@ impl<'tcx> IntRange<'tcx> { fn from_ctor(tcx: TyCtxt<'_, 'tcx, 'tcx>, ctor: &Constructor<'tcx>) -> Option> { + // Floating-point ranges are permitted and we don't want + // to consider them when constructing integer ranges. + fn is_integral<'tcx>(ty: Ty<'tcx>) -> bool { + match ty.sty { + ty::Char | ty::Int(_) | ty::Uint(_) => true, + _ => false, + } + } + match ctor { - ConstantRange(lo, hi, ty, end) => { + ConstantRange(lo, hi, ty, end) if is_integral(ty) => { // Perform a shift if the underlying types are signed, // which makes the interval arithmetic simpler. let bias = IntRange::signed_bias(tcx, ty); @@ -789,7 +853,7 @@ impl<'tcx> IntRange<'tcx> { Some(IntRange { range: lo..=(hi - offset), ty }) } } - ConstantValue(val) => { + ConstantValue(val) if is_integral(val.ty) => { let ty = val.ty; if let Some(val) = val.assert_bits(tcx, ty::ParamEnv::empty().and(ty)) { let bias = IntRange::signed_bias(tcx, ty); @@ -799,9 +863,7 @@ impl<'tcx> IntRange<'tcx> { None } } - Single | Variant(_) | Slice(_) => { - None - } + _ => None, } } @@ -810,7 +872,7 @@ impl<'tcx> IntRange<'tcx> { -> Option> { Self::from_ctor(tcx, &match pat.kind { box PatternKind::Constant { value } => ConstantValue(value), - box PatternKind::Range { lo, hi, ty, end } => ConstantRange( + box PatternKind::Range(PatternRange { lo, hi, ty, end }) => ConstantRange( lo.to_bits(tcx, ty::ParamEnv::empty().and(ty)).unwrap(), hi.to_bits(tcx, ty::ParamEnv::empty().and(ty)).unwrap(), ty, @@ -848,7 +910,7 @@ impl<'tcx> IntRange<'tcx> { } /// Return a collection of ranges that spans the values covered by `ranges`, subtracted - /// by the values covered by `self`: i.e. `ranges \ self` (in set notation). + /// by the values covered by `self`: i.e., `ranges \ self` (in set notation). fn subtract_from(self, tcx: TyCtxt<'_, 'tcx, 'tcx>, ranges: Vec>) @@ -933,12 +995,10 @@ fn compute_missing_ctors<'a, 'tcx: 'a>( // If a constructor appears in a `match` arm, we can // eliminate it straight away. refined_ctors = vec![] - } else if tcx.features().exhaustive_integer_patterns { - if let Some(interval) = IntRange::from_ctor(tcx, used_ctor) { - // Refine the required constructors for the type by subtracting - // the range defined by the current constructor pattern. - refined_ctors = interval.subtract_from(tcx, refined_ctors); - } + } else if let Some(interval) = IntRange::from_ctor(tcx, used_ctor) { + // Refine the required constructors for the type by subtracting + // the range defined by the current constructor pattern. + refined_ctors = interval.subtract_from(tcx, refined_ctors); } // If the constructor patterns that have been considered so far @@ -994,7 +1054,7 @@ fn compute_missing_ctors<'a, 'tcx: 'a>( /// matrix isn't exhaustive). pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, matrix: &Matrix<'p, 'tcx>, - v: &[&'p Pattern<'tcx>], + v: &[&Pattern<'tcx>], witness: WitnessPreference) -> Usefulness<'tcx> { let &Matrix(ref rows) = matrix; @@ -1094,7 +1154,8 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, // For privately empty and non-exhaustive enums, we work as if there were an "extra" // `_` constructor for the type, so we can never match over all constructors. - let is_non_exhaustive = is_privately_empty || is_declared_nonexhaustive; + let is_non_exhaustive = is_privately_empty || is_declared_nonexhaustive || + (pcx.ty.is_pointer_sized() && !cx.tcx.features().precise_pointer_size_matching); if cheap_missing_ctors == MissingCtors::Empty && !is_non_exhaustive { split_grouped_constructors(cx.tcx, all_ctors, matrix, pcx.ty).into_iter().map(|c| { @@ -1103,7 +1164,7 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, } else { let matrix = rows.iter().filter_map(|r| { if r[0].is_wildcard() { - Some(r[1..].to_vec()) + Some(SmallVec::from_slice(&r[1..])) } else { None } @@ -1117,7 +1178,7 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, // // There are 2 ways we can report a witness here. // Commonly, we can report all the "free" - // constructors as witnesses, e.g. if we have: + // constructors as witnesses, e.g., if we have: // // ``` // enum Direction { N, S, E, W } @@ -1132,7 +1193,7 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, // 1) If the user is matching against a non-exhaustive // enum, there is no point in enumerating all possible // variants, because the user can't actually match - // against them himself, e.g. in an example like: + // against them himself, e.g., in an example like: // ``` // let err: io::ErrorKind = ...; // match err { @@ -1146,7 +1207,7 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, // case). // // 2) If the user didn't actually specify a constructor - // in this arm, e.g. in + // in this arm, e.g., in // ``` // let x: (Direction, Direction, bool) = ...; // let (_, _, false) = x; @@ -1192,12 +1253,12 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, } } -/// A shorthand for the `U(S(c, P), S(c, q))` operation from the paper. I.e. `is_useful` applied +/// A shorthand for the `U(S(c, P), S(c, q))` operation from the paper. I.e., `is_useful` applied /// to the specialised version of both the pattern matrix `P` and the new pattern `q`. -fn is_useful_specialized<'p, 'a:'p, 'tcx: 'a>( +fn is_useful_specialized<'p, 'a: 'p, 'tcx: 'a>( cx: &mut MatchCheckCtxt<'a, 'tcx>, &Matrix(ref m): &Matrix<'p, 'tcx>, - v: &[&'p Pattern<'tcx>], + v: &[&Pattern<'tcx>], ctor: Constructor<'tcx>, lty: Ty<'tcx>, witness: WitnessPreference, @@ -1250,7 +1311,7 @@ fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt<'_, 'tcx>, Some(vec![Variant(adt_def.variants[variant_index].did)]) } PatternKind::Constant { value } => Some(vec![ConstantValue(value)]), - PatternKind::Range { lo, hi, ty, end } => + PatternKind::Range(PatternRange { lo, hi, ty, end }) => Some(vec![ConstantRange( lo.to_bits(cx.tcx, ty::ParamEnv::empty().and(ty)).unwrap(), hi.to_bits(cx.tcx, ty::ParamEnv::empty().and(ty)).unwrap(), @@ -1339,28 +1400,62 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>, } } -fn slice_pat_covered_by_constructor<'tcx>( +// checks whether a constant is equal to a user-written slice pattern. Only supports byte slices, +// meaning all other types will compare unequal and thus equal patterns often do not cause the +// second pattern to lint about unreachable match arms. +fn slice_pat_covered_by_const<'tcx>( tcx: TyCtxt<'_, 'tcx, '_>, _span: Span, - ctor: &Constructor, + const_val: &ty::Const<'tcx>, prefix: &[Pattern<'tcx>], slice: &Option>, suffix: &[Pattern<'tcx>] ) -> Result { - let data: &[u8] = match *ctor { - ConstantValue(const_val) => { - let val = match const_val.val { - ConstValue::Unevaluated(..) | - ConstValue::ByRef(..) => bug!("unexpected ConstValue: {:?}", const_val), - ConstValue::Scalar(val) | ConstValue::ScalarPair(val, _) => val, - }; - if let Ok(ptr) = val.to_ptr() { - tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id).bytes.as_ref() - } else { - bug!("unexpected non-ptr ConstantValue") + let data: &[u8] = match (const_val.val, &const_val.ty.sty) { + (ConstValue::ByRef(id, alloc, offset), ty::Array(t, n)) => { + if *t != tcx.types.u8 { + // FIXME(oli-obk): can't mix const patterns with slice patterns and get + // any sort of exhaustiveness/unreachable check yet + // This solely means that we don't lint about unreachable patterns, even if some + // are definitely unreachable. + return Ok(false); } - } - _ => bug!() + let ptr = Pointer::new(id, offset); + let n = n.assert_usize(tcx).unwrap(); + alloc.get_bytes(&tcx, ptr, Size::from_bytes(n)).unwrap() + }, + // a slice fat pointer to a zero length slice + (ConstValue::ScalarPair(Scalar::Bits { .. }, n), ty::Slice(t)) => { + if *t != tcx.types.u8 { + // FIXME(oli-obk): can't mix const patterns with slice patterns and get + // any sort of exhaustiveness/unreachable check yet + // This solely means that we don't lint about unreachable patterns, even if some + // are definitely unreachable. + return Ok(false); + } + assert_eq!(n.to_usize(&tcx).unwrap(), 0); + &[] + }, + // + (ConstValue::ScalarPair(Scalar::Ptr(ptr), n), ty::Slice(t)) => { + if *t != tcx.types.u8 { + // FIXME(oli-obk): can't mix const patterns with slice patterns and get + // any sort of exhaustiveness/unreachable check yet + // This solely means that we don't lint about unreachable patterns, even if some + // are definitely unreachable. + return Ok(false); + } + let n = n.to_usize(&tcx).unwrap(); + tcx.alloc_map + .lock() + .unwrap_memory(ptr.alloc_id) + .get_bytes(&tcx, ptr, Size::from_bytes(n)) + .unwrap() + }, + _ => bug!( + "slice_pat_covered_by_const: {:#?}, {:#?}, {:#?}, {:#?}", + const_val, prefix, slice, suffix, + ), }; let pat_len = prefix.len() + suffix.len(); @@ -1390,17 +1485,16 @@ fn slice_pat_covered_by_constructor<'tcx>( // Whether to evaluate a constructor using exhaustive integer matching. This is true if the // constructor is a range or constant with an integer type. fn should_treat_range_exhaustively(tcx: TyCtxt<'_, 'tcx, 'tcx>, ctor: &Constructor<'tcx>) -> bool { - if tcx.features().exhaustive_integer_patterns { - let ty = match ctor { - ConstantValue(value) => value.ty, - ConstantRange(_, _, ty, _) => ty, - _ => return false, - }; - if let ty::Char | ty::Int(_) | ty::Uint(_) = ty.sty { - return true; - } + let ty = match ctor { + ConstantValue(value) => value.ty, + ConstantRange(_, _, ty, _) => ty, + _ => return false, + }; + if let ty::Char | ty::Int(_) | ty::Uint(_) = ty.sty { + !ty.is_pointer_sized() || tcx.features().precise_pointer_size_matching + } else { + false } - false } /// For exhaustive integer matching, some constructors are grouped within other constructors @@ -1409,7 +1503,7 @@ fn should_treat_range_exhaustively(tcx: TyCtxt<'_, 'tcx, 'tcx>, ctor: &Construct /// the groups (the ranges). Thus we need to split the groups up. Splitting them up naïvely would /// mean creating a separate constructor for every single value in the range, which is clearly /// impractical. However, observe that for some ranges of integers, the specialisation will be -/// identical across all values in that range (i.e. there are equivalence classes of ranges of +/// identical across all values in that range (i.e., there are equivalence classes of ranges of /// constructors based on their `is_useful_specialized` outcome). These classes are grouped by /// the patterns that apply to them (in the matrix `P`). We can split the range whenever the /// patterns that apply to that range (specifically: the patterns that *intersect* with that range) @@ -1418,7 +1512,7 @@ fn should_treat_range_exhaustively(tcx: TyCtxt<'_, 'tcx, 'tcx>, ctor: &Construct /// the group of intersecting patterns changes (using the method described below). /// And voilà! We're testing precisely those ranges that we need to, without any exhaustive matching /// on actual integers. The nice thing about this is that the number of subranges is linear in the -/// number of rows in the matrix (i.e. the number of cases in the `match` statement), so we don't +/// number of rows in the matrix (i.e., the number of cases in the `match` statement), so we don't /// need to be worried about matching over gargantuan ranges. /// /// Essentially, given the first column of a matrix representing ranges, looking like the following: @@ -1517,7 +1611,7 @@ fn constructor_intersects_pattern<'p, 'a: 'p, 'tcx: 'a>( tcx: TyCtxt<'a, 'tcx, 'tcx>, ctor: &Constructor<'tcx>, pat: &'p Pattern<'tcx>, -) -> Option>> { +) -> Option; 2]>> { if should_treat_range_exhaustively(tcx, ctor) { match (IntRange::from_ctor(tcx, ctor), IntRange::from_pat(tcx, pat)) { (Some(ctor), Some(pat)) => { @@ -1525,7 +1619,7 @@ fn constructor_intersects_pattern<'p, 'a: 'p, 'tcx: 'a>( let (pat_lo, pat_hi) = pat.range.into_inner(); let (ctor_lo, ctor_hi) = ctor.range.into_inner(); assert!(pat_lo <= ctor_lo && ctor_hi <= pat_hi); - vec![] + smallvec![] }) } _ => None, @@ -1535,7 +1629,7 @@ fn constructor_intersects_pattern<'p, 'a: 'p, 'tcx: 'a>( // conveniently handled by `IntRange`. For these cases, the constructor may not be a range // so intersection actually devolves into being covered by the pattern. match constructor_covered_by_range(tcx, ctor, pat) { - Ok(true) => Some(vec![]), + Ok(true) => Some(smallvec![]), Ok(false) | Err(ErrorReported) => None, } } @@ -1548,7 +1642,7 @@ fn constructor_covered_by_range<'a, 'tcx>( ) -> Result { let (from, to, end, ty) = match pat.kind { box PatternKind::Constant { value } => (value, value, RangeEnd::Included, value.ty), - box PatternKind::Range { lo, hi, ty, end } => (lo, hi, end, ty), + box PatternKind::Range(PatternRange { lo, hi, end, ty }) => (lo, hi, end, ty), _ => bug!("`constructor_covered_by_range` called with {:?}", pat), }; trace!("constructor_covered_by_range {:#?}, {:#?}, {:#?}, {}", ctor, from, to, ty); @@ -1606,9 +1700,9 @@ fn constructor_covered_by_range<'a, 'tcx>( fn patterns_for_variant<'p, 'a: 'p, 'tcx: 'a>( subpatterns: &'p [FieldPattern<'tcx>], wild_patterns: &[&'p Pattern<'tcx>]) - -> Vec<&'p Pattern<'tcx>> + -> SmallVec<[&'p Pattern<'tcx>; 2]> { - let mut result = wild_patterns.to_owned(); + let mut result = SmallVec::from_slice(wild_patterns); for subpat in subpatterns { result[subpat.field.index()] = &subpat.pattern; @@ -1631,15 +1725,16 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>( r: &[&'p Pattern<'tcx>], constructor: &Constructor<'tcx>, wild_patterns: &[&'p Pattern<'tcx>], -) -> Option>> { +) -> Option; 2]>> { let pat = &r[0]; - let head: Option> = match *pat.kind { - PatternKind::AscribeUserType { ref subpattern, .. } => - specialize(cx, ::std::slice::from_ref(&subpattern), constructor, wild_patterns), + let head = match *pat.kind { + PatternKind::AscribeUserType { ref subpattern, .. } => { + specialize(cx, ::std::slice::from_ref(&subpattern), constructor, wild_patterns) + } PatternKind::Binding { .. } | PatternKind::Wild => { - Some(wild_patterns.to_owned()) + Some(SmallVec::from_slice(wild_patterns)) } PatternKind::Variant { adt_def, variant_index, ref subpatterns, .. } => { @@ -1656,7 +1751,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>( } PatternKind::Deref { ref subpattern } => { - Some(vec![subpattern]) + Some(smallvec![subpattern]) } PatternKind::Constant { value } => { @@ -1666,22 +1761,23 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>( // necessarily point to memory, they are usually just integers. The only time // they should be pointing to memory is when they are subslices of nonzero // slices - let (opt_ptr, n, ty) = match value.ty.builtin_deref(false).unwrap().ty.sty { - ty::TyKind::Array(t, n) => (value.to_ptr(), n.unwrap_usize(cx.tcx), t), - ty::TyKind::Slice(t) => { - match value.val { - ConstValue::ScalarPair(ptr, n) => ( - ptr.to_ptr().ok(), - n.to_bits(cx.tcx.data_layout.pointer_size).unwrap() as u64, - t, - ), - _ => span_bug!( - pat.span, - "slice pattern constant must be scalar pair but is {:?}", - value, - ), - } - }, + let (opt_ptr, n, ty) = match (value.val, &value.ty.sty) { + (ConstValue::ByRef(id, alloc, offset), ty::TyKind::Array(t, n)) => ( + Some(( + Pointer::new(id, offset), + alloc, + )), + n.unwrap_usize(cx.tcx), + t, + ), + (ConstValue::ScalarPair(ptr, n), ty::TyKind::Slice(t)) => ( + ptr.to_ptr().ok().map(|ptr| ( + ptr, + cx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id), + )), + n.to_bits(cx.tcx.data_layout.pointer_size).unwrap() as u64, + t, + ), _ => span_bug!( pat.span, "unexpected const-val {:?} with ctor {:?}", @@ -1692,9 +1788,8 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>( if wild_patterns.len() as u64 == n { // convert a constant slice/array pattern to a list of patterns. match (n, opt_ptr) { - (0, _) => Some(Vec::new()), - (_, Some(ptr)) => { - let alloc = cx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id); + (0, _) => Some(SmallVec::new()), + (_, Some((ptr, alloc))) => { let layout = cx.tcx.layout_of(cx.param_env.and(ty)).ok()?; (0..n).map(|i| { let ptr = ptr.offset(layout.size * i, &cx.tcx).ok()?; @@ -1757,11 +1852,9 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>( None } } - ConstantValue(..) => { - match slice_pat_covered_by_constructor( - cx.tcx, pat.span, constructor, prefix, slice, suffix - ) { - Ok(true) => Some(vec![]), + ConstantValue(cv) => { + match slice_pat_covered_by_const(cx.tcx, pat.span, cv, prefix, slice, suffix) { + Ok(true) => Some(smallvec![]), Ok(false) => None, Err(ErrorReported) => None } diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index db6d9b6a427..a251b723d61 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -31,6 +31,7 @@ use rustc::hir::def_id::DefId; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::{self, Pat, PatKind}; +use smallvec::smallvec; use std::slice; use syntax::ast; @@ -41,18 +42,18 @@ struct OuterVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx> } impl<'a, 'tcx> Visitor<'tcx> for OuterVisitor<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir) + NestedVisitorMap::OnlyBodies(&self.tcx.hir()) } fn visit_body(&mut self, body: &'tcx hir::Body) { intravisit::walk_body(self, body); - let def_id = self.tcx.hir.body_owner_def_id(body.id()); + let def_id = self.tcx.hir().body_owner_def_id(body.id()); let _ = self.tcx.check_match(def_id); } } pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - tcx.hir.krate().visit_all_item_likes(&mut OuterVisitor { tcx }.as_deep_visitor()); + tcx.hir().krate().visit_all_item_likes(&mut OuterVisitor { tcx }.as_deep_visitor()); tcx.sess.abort_if_errors(); } @@ -60,8 +61,8 @@ pub(crate) fn check_match<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, ) -> Result<(), ErrorReported> { - let body_id = if let Some(id) = tcx.hir.as_local_node_id(def_id) { - tcx.hir.body_owned_by(id) + let body_id = if let Some(id) = tcx.hir().as_local_node_id(def_id) { + tcx.hir().body_owned_by(id) } else { return Ok(()); }; @@ -73,7 +74,7 @@ pub(crate) fn check_match<'a, 'tcx>( region_scope_tree: &tcx.region_scope_tree(def_id), param_env: tcx.param_env(def_id), identity_substs: Substs::identity_for_item(tcx, def_id), - }.visit_body(tcx.hir.body(body_id)); + }.visit_body(tcx.hir().body(body_id)); }) } @@ -188,11 +189,11 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { // Third, perform some lints. for pat in &arm.pats { - check_for_bindings_named_the_same_as_variants(self, pat); + check_for_bindings_named_same_as_variants(self, pat); } } - let module = self.tcx.hir.get_module_parent(scrut.id); + let module = self.tcx.hir().get_module_parent(scrut.id); MatchCheckCtxt::create_and_enter(self.tcx, self.param_env, module, |ref mut cx| { let mut have_errors = false; @@ -224,12 +225,16 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { // Then, if the match has no arms, check whether the scrutinee // is uninhabited. let pat_ty = self.tables.node_id_to_type(scrut.hir_id); - let module = self.tcx.hir.get_module_parent(scrut.id); + let module = self.tcx.hir().get_module_parent(scrut.id); if inlined_arms.is_empty() { let scrutinee_is_uninhabited = if self.tcx.features().exhaustive_patterns { self.tcx.is_ty_uninhabited_from(module, pat_ty) } else { - self.conservative_is_uninhabited(pat_ty) + match pat_ty.sty { + ty::Never => true, + ty::Adt(def, _) => def.variants.is_empty(), + _ => false + } }; if !scrutinee_is_uninhabited { // We know the type is inhabited, so this must be wrong @@ -250,31 +255,22 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { .iter() .filter(|&&(_, guard)| guard.is_none()) .flat_map(|arm| &arm.0) - .map(|pat| vec![pat.0]) + .map(|pat| smallvec![pat.0]) .collect(); let scrut_ty = self.tables.node_id_to_type(scrut.hir_id); check_exhaustive(cx, scrut_ty, scrut.span, &matrix); }) } - fn conservative_is_uninhabited(&self, scrutinee_ty: Ty<'tcx>) -> bool { - // "rustc-1.0-style" uncontentious uninhabitableness check - match scrutinee_ty.sty { - ty::Never => true, - ty::Adt(def, _) => def.variants.is_empty(), - _ => false - } - } - fn check_irrefutable(&self, pat: &'tcx Pat, origin: &str) { - let module = self.tcx.hir.get_module_parent(pat.id); + let module = self.tcx.hir().get_module_parent(pat.id); MatchCheckCtxt::create_and_enter(self.tcx, self.param_env, module, |ref mut cx| { let mut patcx = PatternContext::new(self.tcx, self.param_env.and(self.identity_substs), self.tables); let pattern = patcx.lower_pattern(pat); let pattern_ty = pattern.ty; - let pats: Matrix = vec![vec![ + let pats: Matrix = vec![smallvec![ expand_pattern(cx, pattern) ]].into_iter().collect(); @@ -309,7 +305,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { } } -fn check_for_bindings_named_the_same_as_variants(cx: &MatchVisitor, pat: &Pat) { +fn check_for_bindings_named_same_as_variants(cx: &MatchVisitor, pat: &Pat) { pat.walk(|p| { if let PatKind::Binding(_, _, ident, None) = p.node { if let Some(&bm) = cx.tables.pat_binding_modes().get(p.hir_id) { @@ -367,7 +363,7 @@ fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>, let mut printed_if_let_err = false; for (arm_index, &(ref pats, guard)) in arms.iter().enumerate() { for &(pat, hir_pat) in pats { - let v = vec![pat]; + let v = smallvec![pat]; match is_useful(cx, &seen, &v, LeaveOutWitness) { NotUseful => { @@ -462,10 +458,10 @@ fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>, } } -fn check_exhaustive<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>, +fn check_exhaustive<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, scrut_ty: Ty<'tcx>, sp: Span, - matrix: &Matrix<'a, 'tcx>) { + matrix: &Matrix<'p, 'tcx>) { let wild_pattern = Pattern { ty: scrut_ty, span: DUMMY_SP, diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 61d8297fec9..f78a70f6a25 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -24,7 +24,7 @@ use hair::constant::*; use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability}; use rustc::mir::{ProjectionElem, UserTypeAnnotation, UserTypeProjection, UserTypeProjections}; use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend}; -use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty}; +use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, Lift}; use rustc::ty::subst::{Substs, Kind}; use rustc::ty::layout::VariantIdx; use rustc::hir::{self, PatKind, RangeEnd}; @@ -219,16 +219,11 @@ pub enum PatternKind<'tcx> { value: &'tcx ty::Const<'tcx>, }, - Range { - lo: &'tcx ty::Const<'tcx>, - hi: &'tcx ty::Const<'tcx>, - ty: Ty<'tcx>, - end: RangeEnd, - }, + Range(PatternRange<'tcx>), /// matches against a slice, checking the length and extracting elements. /// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty. - /// e.g. `&[ref xs..]`. + /// e.g., `&[ref xs..]`. Slice { prefix: Vec>, slice: Option>, @@ -243,6 +238,14 @@ pub enum PatternKind<'tcx> { }, } +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct PatternRange<'tcx> { + pub lo: &'tcx ty::Const<'tcx>, + pub hi: &'tcx ty::Const<'tcx>, + pub ty: Ty<'tcx>, + pub end: RangeEnd, +} + impl<'tcx> fmt::Display for Pattern<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self.kind { @@ -354,7 +357,7 @@ impl<'tcx> fmt::Display for Pattern<'tcx> { PatternKind::Constant { value } => { fmt_const_val(f, value) } - PatternKind::Range { lo, hi, ty: _, end } => { + PatternKind::Range(PatternRange { lo, hi, ty: _, end }) => { fmt_const_val(f, lo)?; match end { RangeEnd::Included => write!(f, "..=")?, @@ -483,7 +486,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { ); match (end, cmp) { (RangeEnd::Excluded, Some(Ordering::Less)) => - PatternKind::Range { lo, hi, ty, end }, + PatternKind::Range(PatternRange { lo, hi, ty, end }), (RangeEnd::Excluded, _) => { span_err!( self.tcx.sess, @@ -497,7 +500,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { PatternKind::Constant { value: lo } } (RangeEnd::Included, Some(Ordering::Less)) => { - PatternKind::Range { lo, hi, ty, end } + PatternKind::Range(PatternRange { lo, hi, ty, end }) } (RangeEnd::Included, _) => { let mut err = struct_span_err!( @@ -954,7 +957,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { }; let kind = match cv.ty.sty { ty::Float(_) => { - let id = self.tcx.hir.hir_to_node_id(id); + let id = self.tcx.hir().hir_to_node_id(id); self.tcx.lint_node( ::rustc::lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN, id, @@ -1177,17 +1180,17 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> { } => PatternKind::Constant { value: value.fold_with(folder) }, - PatternKind::Range { + PatternKind::Range(PatternRange { lo, hi, ty, end, - } => PatternKind::Range { + }) => PatternKind::Range(PatternRange { lo: lo.fold_with(folder), hi: hi.fold_with(folder), ty: ty.fold_with(folder), end, - }, + }), PatternKind::Slice { ref prefix, ref slice, @@ -1210,8 +1213,8 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> { } } -pub fn compare_const_vals<'a, 'tcx>( - tcx: TyCtxt<'a, 'tcx, 'tcx>, +pub fn compare_const_vals<'a, 'gcx, 'tcx>( + tcx: TyCtxt<'a, 'gcx, 'tcx>, a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>, ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, @@ -1233,6 +1236,9 @@ pub fn compare_const_vals<'a, 'tcx>( return fallback(); } + let tcx = tcx.global_tcx(); + let (a, b, ty) = (a, b, ty).lift_to_tcx(tcx).unwrap(); + // FIXME: This should use assert_bits(ty) instead of use_bits // but triggers possibly bugs due to mismatching of arrays and slices if let (Some(a), Some(b)) = (a.to_bits(tcx, ty), b.to_bits(tcx, ty)) { @@ -1259,34 +1265,32 @@ pub fn compare_const_vals<'a, 'tcx>( } } - if let ty::Ref(_, rty, _) = ty.value.sty { - if let ty::Str = rty.sty { - match (a.val, b.val) { - ( - ConstValue::ScalarPair( - Scalar::Ptr(ptr_a), - len_a, - ), - ConstValue::ScalarPair( - Scalar::Ptr(ptr_b), - len_b, - ), - ) if ptr_a.offset.bytes() == 0 && ptr_b.offset.bytes() == 0 => { - if let Ok(len_a) = len_a.to_bits(tcx.data_layout.pointer_size) { - if let Ok(len_b) = len_b.to_bits(tcx.data_layout.pointer_size) { - if len_a == len_b { - let map = tcx.alloc_map.lock(); - let alloc_a = map.unwrap_memory(ptr_a.alloc_id); - let alloc_b = map.unwrap_memory(ptr_b.alloc_id); - if alloc_a.bytes.len() as u128 == len_a { - return from_bool(alloc_a == alloc_b); - } + if let ty::Str = ty.value.sty { + match (a.val, b.val) { + ( + ConstValue::ScalarPair( + Scalar::Ptr(ptr_a), + len_a, + ), + ConstValue::ScalarPair( + Scalar::Ptr(ptr_b), + len_b, + ), + ) if ptr_a.offset.bytes() == 0 && ptr_b.offset.bytes() == 0 => { + if let Ok(len_a) = len_a.to_bits(tcx.data_layout.pointer_size) { + if let Ok(len_b) = len_b.to_bits(tcx.data_layout.pointer_size) { + if len_a == len_b { + let map = tcx.alloc_map.lock(); + let alloc_a = map.unwrap_memory(ptr_a.alloc_id); + let alloc_b = map.unwrap_memory(ptr_b.alloc_id); + if alloc_a.bytes.len() as u128 == len_a { + return from_bool(alloc_a == alloc_b); } } } } - _ => (), } + _ => (), } } diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index 7d636b77ced..118539fc58e 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -44,22 +44,16 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> } Misc => { - let src_layout = src.layout; let src = self.read_immediate(src)?; - // There are no casts to references - assert!(!dest.layout.ty.is_region_ptr()); - // Hence we make all casts erase the tag - let src = src.erase_tag().with_default_tag(); - - if self.type_is_fat_ptr(src_layout.ty) { - match (src, self.type_is_fat_ptr(dest.layout.ty)) { + if self.type_is_fat_ptr(src.layout.ty) { + match (*src, self.type_is_fat_ptr(dest.layout.ty)) { // pointers to extern types (Immediate::Scalar(_),_) | // slices and trait objects to other slices/trait objects (Immediate::ScalarPair(..), true) => { // No change to immediate - self.write_immediate(src, dest)?; + self.write_immediate(*src, dest)?; } // slices and trait objects to thin pointers (dropping the metadata) (Immediate::ScalarPair(data, _), false) => { @@ -67,11 +61,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> } } } else { - match src_layout.variants { + match src.layout.variants { layout::Variants::Single { index } => { - if let Some(def) = src_layout.ty.ty_adt_def() { + if let Some(def) = src.layout.ty.ty_adt_def() { // Cast from a univariant enum - assert!(src_layout.is_zst()); + assert!(src.layout.is_zst()); let discr_val = def .discriminant_for_variant(*self.tcx, index) .val; @@ -84,7 +78,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> layout::Variants::NicheFilling { .. } => {}, } - let dest_val = self.cast_scalar(src.to_scalar()?, src_layout, dest.layout)?; + let dest_val = self.cast_scalar(src.to_scalar()?, src.layout, dest.layout)?; self.write_scalar(dest_val, dest)?; } } diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index d36d530fe78..8ae0345e07a 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -422,7 +422,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc return_to_block: StackPopCleanup, ) -> EvalResult<'tcx> { if self.stack.len() > 1 { // FIXME should be "> 0", printing topmost frame crashes rustc... - debug!("PAUSING({}) {}", self.cur_frame(), self.frame().instance); + info!("PAUSING({}) {}", self.cur_frame(), self.frame().instance); } ::log_settings::settings().indentation += 1; @@ -491,7 +491,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc } if self.stack.len() > 1 { // FIXME no check should be needed, but some instances ICE - debug!("ENTERING({}) {}", self.cur_frame(), self.frame().instance); + info!("ENTERING({}) {}", self.cur_frame(), self.frame().instance); } if self.stack.len() > self.tcx.sess.const_eval_stack_frame_limit { @@ -503,7 +503,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc pub(super) fn pop_stack_frame(&mut self) -> EvalResult<'tcx> { if self.stack.len() > 1 { // FIXME no check should be needed, but some instances ICE - debug!("LEAVING({}) {}", self.cur_frame(), self.frame().instance); + info!("LEAVING({}) {}", self.cur_frame(), self.frame().instance); } ::log_settings::settings().indentation -= 1; let frame = self.stack.pop().expect( @@ -557,7 +557,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc } if self.stack.len() > 1 { // FIXME should be "> 0", printing topmost frame crashes rustc... - debug!("CONTINUING({}) {}", self.cur_frame(), self.frame().instance); + info!("CONTINUING({}) {}", self.cur_frame(), self.frame().instance); } Ok(()) diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index bbee6e0b49a..cbe2e25b4fc 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -103,7 +103,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> if bits == 0 { return err!(Intrinsic(format!("{} called on 0", intrinsic_name))); } - numeric_intrinsic(intrinsic_name.trim_right_matches("_nonzero"), bits, kind)? + numeric_intrinsic(intrinsic_name.trim_end_matches("_nonzero"), bits, kind)? } else { numeric_intrinsic(intrinsic_name, bits, kind)? }; diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index d7a3a27bbe8..144d79f236c 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -81,7 +81,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { type FrameExtra; /// Extra data stored in memory. A reference to this is available when `AllocExtra` - /// gets initialized, so you can e.g. have an `Rc` here if there is global state you + /// gets initialized, so you can e.g., have an `Rc` here if there is global state you /// need access to in the `AllocExtra` hooks. type MemoryExtra: Default; @@ -185,7 +185,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, ptr: Pointer, kind: MemoryKind, - ) -> EvalResult<'tcx, Pointer>; + ) -> Pointer; /// Executed when evaluating the `*` operator: Following a reference. /// This has the chance to adjust the tag. It should not change anything else! @@ -203,21 +203,12 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { #[inline] fn retag( _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, - _fn_entry: bool, + _kind: mir::RetagKind, _place: PlaceTy<'tcx, Self::PointerTag>, ) -> EvalResult<'tcx> { Ok(()) } - /// Execute an escape-to-raw operation - #[inline] - fn escape_to_raw( - _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, - _ptr: OpTy<'tcx, Self::PointerTag>, - ) -> EvalResult<'tcx> { - Ok(()) - } - /// Called immediately before a new stack frame got pushed fn stack_push( ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 97d7e1586b8..f1c7b2be6fb 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -29,7 +29,7 @@ use syntax::ast::Mutability; use super::{ Pointer, AllocId, Allocation, GlobalId, AllocationExtra, - EvalResult, Scalar, EvalErrorKind, AllocType, PointerArithmetic, + EvalResult, Scalar, EvalErrorKind, AllocKind, PointerArithmetic, Machine, AllocMap, MayLeak, ErrorHandled, InboundsCheck, }; @@ -55,7 +55,7 @@ impl MayLeak for MemoryKind { } // `Memory` has to depend on the `Machine` because some of its operations -// (e.g. `get`) call a `Machine` hook. +// (e.g., `get`) call a `Machine` hook. pub struct Memory<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> { /// Allocations local to this instance of the miri engine. The kind /// helps ensure that the same mechanism is used for allocation and @@ -131,10 +131,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { &mut self, alloc: Allocation, kind: MemoryKind, - ) -> EvalResult<'tcx, AllocId> { + ) -> AllocId { let id = self.tcx.alloc_map.lock().reserve(); self.alloc_map.insert(id, (kind, alloc)); - Ok(id) + id } pub fn allocate( @@ -142,9 +142,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { size: Size, align: Align, kind: MemoryKind, - ) -> EvalResult<'tcx, Pointer> { + ) -> Pointer { let extra = AllocationExtra::memory_allocated(size, &self.extra); - Ok(Pointer::from(self.allocate_with(Allocation::undef(size, align, extra), kind)?)) + Pointer::from(self.allocate_with(Allocation::undef(size, align, extra), kind)) } pub fn reallocate( @@ -162,7 +162,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { // For simplicities' sake, we implement reallocate as "alloc, copy, dealloc". // This happens so rarely, the perf advantage is outweighed by the maintenance cost. - let new_ptr = self.allocate(new_size, new_align, kind)?; + let new_ptr = self.allocate(new_size, new_align, kind); self.copy( ptr.into(), old_align, @@ -204,12 +204,12 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { None => { // Deallocating static memory -- always an error return match self.tcx.alloc_map.lock().get(ptr.alloc_id) { - Some(AllocType::Function(..)) => err!(DeallocatedWrongMemoryKind( + Some(AllocKind::Function(..)) => err!(DeallocatedWrongMemoryKind( "function".to_string(), format!("{:?}", kind), )), - Some(AllocType::Static(..)) | - Some(AllocType::Memory(..)) => err!(DeallocatedWrongMemoryKind( + Some(AllocKind::Static(..)) | + Some(AllocKind::Memory(..)) => err!(DeallocatedWrongMemoryKind( "static".to_string(), format!("{:?}", kind), )), @@ -326,15 +326,15 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { ) -> EvalResult<'tcx, Cow<'tcx, Allocation>> { let alloc = tcx.alloc_map.lock().get(id); let def_id = match alloc { - Some(AllocType::Memory(mem)) => { + Some(AllocKind::Memory(mem)) => { // We got tcx memory. Let the machine figure out whether and how to // turn that into memory with the right pointer tag. return Ok(M::adjust_static_allocation(mem, memory_extra)) } - Some(AllocType::Function(..)) => { + Some(AllocKind::Function(..)) => { return err!(DerefFunctionPointer) } - Some(AllocType::Static(did)) => { + Some(AllocKind::Static(did)) => { did } None => @@ -435,8 +435,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { } // Could also be a fn ptr or extern static match self.tcx.alloc_map.lock().get(id) { - Some(AllocType::Function(..)) => (Size::ZERO, Align::from_bytes(1).unwrap()), - Some(AllocType::Static(did)) => { + Some(AllocKind::Function(..)) => (Size::ZERO, Align::from_bytes(1).unwrap()), + Some(AllocKind::Static(did)) => { // The only way `get` couldn't have worked here is if this is an extern static assert!(self.tcx.is_foreign_item(did)); // Use size and align of the type @@ -459,7 +459,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { } trace!("reading fn ptr: {}", ptr.alloc_id); match self.tcx.alloc_map.lock().get(ptr.alloc_id) { - Some(AllocType::Function(instance)) => Ok(instance), + Some(AllocKind::Function(instance)) => Ok(instance), _ => Err(EvalErrorKind::ExecuteMemory.into()), } } @@ -557,16 +557,16 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { Err(()) => { // static alloc? match self.tcx.alloc_map.lock().get(id) { - Some(AllocType::Memory(alloc)) => { + Some(AllocKind::Memory(alloc)) => { self.dump_alloc_helper( &mut allocs_seen, &mut allocs_to_print, msg, alloc, " (immutable)".to_owned() ); } - Some(AllocType::Function(func)) => { + Some(AllocKind::Function(func)) => { trace!("{} {}", msg, func); } - Some(AllocType::Static(did)) => { + Some(AllocKind::Static(did)) => { trace!("{} {:?}", msg, did); } None => { @@ -638,7 +638,7 @@ where // ensure llvm knows not to put this into immutable memory alloc.mutability = mutability; let alloc = self.tcx.intern_const_alloc(alloc); - self.tcx.alloc_map.lock().set_id_memory(alloc_id, alloc); + self.tcx.alloc_map.lock().set_alloc_id_memory(alloc_id, alloc); // recurse into inner allocations for &(_, alloc) in alloc.relocations.values() { // FIXME: Reusing the mutability here is likely incorrect. It is originally @@ -708,8 +708,13 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { relocations .iter() .map(|&(offset, reloc)| { - (offset + dest.offset - src.offset + (i * size * relocations.len() as u64), - reloc) + // compute offset for current repetition + let dest_offset = dest.offset + (i * size); + ( + // shift offsets from source allocation to destination allocation + offset + dest_offset - src.offset, + reloc, + ) }) ); } diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 83ceadada65..7143d66ad92 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -382,7 +382,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> _ => { trace!("Forcing allocation for local of type {:?}", layout.ty); Operand::Indirect( - *self.allocate(layout, MemoryKind::Stack)? + *self.allocate(layout, MemoryKind::Stack) ) } }) diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 1b47530eaec..e316b54f8ca 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -35,7 +35,7 @@ pub struct MemPlace { pub align: Align, /// Metadata for unsized places. Interpretation is up to the type. /// Must not be present for sized types, but can be missing for unsized types - /// (e.g. `extern type`). + /// (e.g., `extern type`). pub meta: Option>, } @@ -115,6 +115,16 @@ impl MemPlace { } } + #[inline] + pub fn with_tag(self, new_tag: Tag) -> Self + { + MemPlace { + ptr: self.ptr.with_tag(new_tag), + align: self.align, + meta: self.meta, + } + } + #[inline(always)] pub fn from_scalar_ptr(ptr: Scalar, align: Align) -> Self { MemPlace { @@ -187,6 +197,16 @@ impl<'tcx, Tag> MPlaceTy<'tcx, Tag> { } } + #[inline] + pub fn with_tag(self, new_tag: Tag) -> Self + { + MPlaceTy { + mplace: self.mplace.with_tag(new_tag), + layout: self.layout, + } + } + + #[inline] pub fn offset( self, offset: Size, @@ -216,7 +236,7 @@ impl<'tcx, Tag> MPlaceTy<'tcx, Tag> { } } else { // Go through the layout. There are lots of types that support a length, - // e.g. SIMD types. + // e.g., SIMD types. match self.layout.fields { layout::FieldPlacement::Array { count, .. } => Ok(count), _ => bug!("len not supported on sized type {:?}", self.layout.ty), @@ -888,10 +908,10 @@ where // a fake pointer? Are we even called for ZST? // We need the layout of the local. We can NOT use the layout we got, - // that might e.g. be an inner field of a struct with `Scalar` layout, + // that might e.g., be an inner field of a struct with `Scalar` layout, // that has different alignment than the outer field. let local_layout = self.layout_of_local(&self.stack[frame], local)?; - let ptr = self.allocate(local_layout, MemoryKind::Stack)?; + let ptr = self.allocate(local_layout, MemoryKind::Stack); // We don't have to validate as we can assume the local // was already valid for its type. self.write_immediate_to_mplace_no_validate(value, ptr)?; @@ -913,15 +933,15 @@ where &mut self, layout: TyLayout<'tcx>, kind: MemoryKind, - ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { + ) -> MPlaceTy<'tcx, M::PointerTag> { if layout.is_unsized() { assert!(self.tcx.features().unsized_locals, "cannot alloc memory for unsized type"); // FIXME: What should we do here? We should definitely also tag! - Ok(MPlaceTy::dangling(layout, self)) + MPlaceTy::dangling(layout, self) } else { - let ptr = self.memory.allocate(layout.size, layout.align.abi, kind)?; - let ptr = M::tag_new_allocation(self, ptr, kind)?; - Ok(MPlaceTy::from_aligned_ptr(ptr, layout)) + let ptr = self.memory.allocate(layout.size, layout.align.abi, kind); + let ptr = M::tag_new_allocation(self, ptr, kind); + MPlaceTy::from_aligned_ptr(ptr, layout) } } diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index 8814118f65b..308abdbbb90 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -18,7 +18,7 @@ use rustc::mir::interpret::{EvalResult, Scalar, PointerArithmetic}; use super::{EvalContext, Machine}; -/// Classify whether an operator is "left-homogeneous", i.e. the LHS has the +/// Classify whether an operator is "left-homogeneous", i.e., the LHS has the /// same type as the result. #[inline] fn binop_left_homogeneous(op: mir::BinOp) -> bool { @@ -31,7 +31,7 @@ fn binop_left_homogeneous(op: mir::BinOp) -> bool { false, } } -/// Classify whether an operator is "right-homogeneous", i.e. the RHS has the +/// Classify whether an operator is "right-homogeneous", i.e., the RHS has the /// same type as the LHS. #[inline] fn binop_right_homogeneous(op: mir::BinOp) -> bool { @@ -81,11 +81,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> } fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> EvalResult<'tcx> { - debug!("{:?}", stmt); + info!("{:?}", stmt); use rustc::mir::StatementKind::*; - // Some statements (e.g. box) push new stack frames. + // Some statements (e.g., box) push new stack frames. // We have to record the stack frame number *before* executing the statement. let frame_idx = self.cur_frame(); self.tcx.span = stmt.source_info.span; @@ -119,13 +119,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> FakeRead(..) => {} // Stacked Borrows. - Retag { fn_entry, ref place } => { + Retag(kind, ref place) => { let dest = self.eval_place(place)?; - M::retag(self, fn_entry, dest)?; - } - EscapeToRaw(ref op) => { - let op = self.eval_operand(op, None)?; - M::escape_to_raw(self, op)?; + M::retag(self, kind, dest)?; } // Statements we do not track. @@ -293,7 +289,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> } fn terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> EvalResult<'tcx> { - debug!("{:?}", terminator.kind); + info!("{:?}", terminator.kind); self.tcx.span = terminator.source_info.span; self.memory.tcx.span = terminator.source_info.span; @@ -303,7 +299,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> if !self.stack.is_empty() { // This should change *something* debug_assert!(self.cur_frame() != old_stack || self.frame().block != old_bb); - debug!("// {:?}", self.frame().block); + info!("// {:?}", self.frame().block); } Ok(()) } diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index 300f3d639b5..4a672f195d2 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -252,7 +252,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> return err!(FunctionAbiMismatch(caller_abi, Abi::RustIntrinsic)); } // The intrinsic itself cannot diverge, so if we got here without a return - // place... (can happen e.g. for transmute returning `!`) + // place... (can happen e.g., for transmute returning `!`) let dest = match dest { Some(dest) => dest, None => return err!(Unreachable) diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs index bda585b8eda..22936a9b0a0 100644 --- a/src/librustc_mir/interpret/traits.rs +++ b/src/librustc_mir/interpret/traits.rs @@ -54,7 +54,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> ptr_size * (3 + methods.len() as u64), ptr_align, MemoryKind::Vtable, - )?.with_default_tag(); + ).with_default_tag(); let tcx = &*self.tcx; let drop = ::monomorphize::resolve_drop_in_place(*tcx, ty); diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index d98d05bc01b..c7bfea82a2d 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -17,7 +17,7 @@ use rustc::ty::layout::{self, Size, Align, TyLayout, LayoutOf, VariantIdx}; use rustc::ty; use rustc_data_structures::fx::FxHashSet; use rustc::mir::interpret::{ - Scalar, AllocType, EvalResult, EvalErrorKind, + Scalar, AllocKind, EvalResult, EvalErrorKind, }; use super::{ @@ -388,7 +388,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> "integer pointer in non-ZST reference", self.path); // Skip validation entirely for some external statics let alloc_kind = self.ecx.tcx.alloc_map.lock().get(ptr.alloc_id); - if let Some(AllocType::Static(did)) = alloc_kind { + if let Some(AllocKind::Static(did)) = alloc_kind { // `extern static` cannot be validated as they have no body. // FIXME: Statics from other crates are also skipped. // They might be checked at a different type, but for now we @@ -408,7 +408,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> // Check if we have encountered this pointer+layout combination // before. Proceed recursively even for integer pointers, no // reason to skip them! They are (recursively) valid for some ZST, - // but not for others (e.g. `!` is a ZST). + // but not for others (e.g., `!` is a ZST). let op = place.into(); if ref_tracking.seen.insert(op) { trace!("Recursing below ptr {:#?}", *op); @@ -548,7 +548,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> // NOTE: Keep this in sync with the handling of integer and float // types above, in `visit_primitive`. // In run-time mode, we accept pointers in here. This is actually more - // permissive than a per-element check would be, e.g. we accept + // permissive than a per-element check would be, e.g., we accept // an &[u8] that contains a pointer even though bytewise checking would // reject it. However, that's good: We don't inherently want // to reject those pointers, we just do not have the machinery to diff --git a/src/librustc_mir/interpret/visitor.rs b/src/librustc_mir/interpret/visitor.rs index 81e56f3115d..4773f5627d7 100644 --- a/src/librustc_mir/interpret/visitor.rs +++ b/src/librustc_mir/interpret/visitor.rs @@ -272,7 +272,7 @@ macro_rules! make_value_visitor { // is very relevant for `NonNull` and similar structs: We need to visit them // at their scalar layout *before* descending into their fields. // FIXME: We could avoid some redundant checks here. For newtypes wrapping - // scalars, we do the same check on every "level" (e.g. first we check + // scalars, we do the same check on every "level" (e.g., first we check // MyNewtype and then the scalar in there). match v.layout().abi { layout::Abi::Uninhabited => { diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 1a35f4da20b..983488da003 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -37,7 +37,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![feature(if_while_or_patterns)] #![feature(try_from)] #![feature(reverse_bits)] -#![feature(underscore_imports)] +#![cfg_attr(stage0, feature(underscore_imports))] #![recursion_limit="256"] diff --git a/src/librustc_mir/lints.rs b/src/librustc_mir/lints.rs index 4c7938504c1..775431e5cbd 100644 --- a/src/librustc_mir/lints.rs +++ b/src/librustc_mir/lints.rs @@ -20,9 +20,9 @@ use rustc::ty::subst::Substs; pub fn check(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &Mir<'tcx>, def_id: DefId) { - let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); + let node_id = tcx.hir().as_local_node_id(def_id).unwrap(); - if let Some(fn_like_node) = FnLikeNode::from_node(tcx.hir.get(node_id)) { + if let Some(fn_like_node) = FnLikeNode::from_node(tcx.hir().get(node_id)) { check_fn_for_unconditional_recursion(tcx, fn_like_node.kind(), mir, def_id); } } @@ -39,11 +39,11 @@ fn check_fn_for_unconditional_recursion(tcx: TyCtxt<'a, 'tcx, 'tcx>, //FIXME(#54444) rewrite this lint to use the dataflow framework // Walk through this function (say `f`) looking to see if - // every possible path references itself, i.e. the function is + // every possible path references itself, i.e., the function is // called recursively unconditionally. This is done by trying // to find a path from the entry node to the exit node that // *doesn't* call `f` by traversing from the entry while - // pretending that calls of `f` are sinks (i.e. ignoring any + // pretending that calls of `f` are sinks (i.e., ignoring any // exit edges from them). // // NB. this has an edge case with non-returning statements, @@ -62,7 +62,7 @@ fn check_fn_for_unconditional_recursion(tcx: TyCtxt<'a, 'tcx, 'tcx>, // considers this to be an error for two reasons, (a) it is // easier to implement, and (b) it seems rare to actually want // to have behaviour like the above, rather than - // e.g. accidentally recursing after an assert. + // e.g., accidentally recursing after an assert. let basic_blocks = mir.basic_blocks(); let mut reachable_without_self_call_queue = vec![mir::START_BLOCK]; @@ -135,12 +135,12 @@ fn check_fn_for_unconditional_recursion(tcx: TyCtxt<'a, 'tcx, 'tcx>, } // Check the number of self calls because a function that - // doesn't return (e.g. calls a `-> !` function or `loop { /* + // doesn't return (e.g., calls a `-> !` function or `loop { /* // no break */ }`) shouldn't be linted unless it actually // recurs. if !reached_exit_without_self_call && !self_call_locations.is_empty() { - let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); - let sp = tcx.sess.source_map().def_span(tcx.hir.span(node_id)); + let node_id = tcx.hir().as_local_node_id(def_id).unwrap(); + let sp = tcx.sess.source_map().def_span(tcx.hir().span(node_id)); let mut db = tcx.struct_span_lint_node(UNCONDITIONAL_RECURSION, node_id, sp, diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 7531f62fdab..a6239a8115a 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -197,7 +197,7 @@ use rustc::session::config; use rustc::mir::{self, Location, Promoted}; use rustc::mir::visit::Visitor as MirVisitor; use rustc::mir::mono::MonoItem; -use rustc::mir::interpret::{Scalar, GlobalId, AllocType, ErrorHandled}; +use rustc::mir::interpret::{Scalar, GlobalId, AllocKind, ErrorHandled}; use monomorphize::{self, Instance}; use rustc::util::nodemap::{FxHashSet, FxHashMap, DefIdMap}; @@ -332,7 +332,7 @@ fn collect_roots<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, { let entry_fn = tcx.sess.entry_fn.borrow().map(|(node_id, _, _)| { - tcx.hir.local_def_id(node_id) + tcx.hir().local_def_id(node_id) }); debug!("collect_roots: entry_fn = {:?}", entry_fn); @@ -344,7 +344,7 @@ fn collect_roots<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, output: &mut roots, }; - tcx.hir.krate().visit_all_item_likes(&mut visitor); + tcx.hir().krate().visit_all_item_likes(&mut visitor); visitor.push_extra_entry_roots(); } @@ -462,8 +462,8 @@ fn check_recursion_limit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if recursion_depth > *tcx.sess.recursion_limit.get() { let error = format!("reached the recursion limit while instantiating `{}`", instance); - if let Some(node_id) = tcx.hir.as_local_node_id(def_id) { - tcx.sess.span_fatal(tcx.hir.span(node_id), &error); + if let Some(node_id) = tcx.hir().as_local_node_id(def_id) { + tcx.sess.span_fatal(tcx.hir().span(node_id), &error); } else { tcx.sess.fatal(&error); } @@ -494,8 +494,8 @@ fn check_type_length_limit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let instance_name = instance.to_string(); let msg = format!("reached the type-length limit while instantiating `{:.64}...`", instance_name); - let mut diag = if let Some(node_id) = tcx.hir.as_local_node_id(instance.def_id()) { - tcx.sess.struct_span_fatal(tcx.hir.span(node_id), &msg) + let mut diag = if let Some(node_id) = tcx.hir().as_local_node_id(instance.def_id()) { + tcx.sess.struct_span_fatal(tcx.hir().span(node_id), &msg) } else { tcx.sess.struct_fatal(&msg) }; @@ -821,7 +821,7 @@ fn should_monomorphize_locally<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: /// Again, we want this `find_vtable_types_for_unsizing()` to provide the pair /// `(SomeStruct, SomeTrait)`. /// -/// Finally, there is also the case of custom unsizing coercions, e.g. for +/// Finally, there is also the case of custom unsizing coercions, e.g., for /// smart pointers such as `Rc` and `Arc`. fn find_vtable_types_for_unsizing<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, source_ty: Ty<'tcx>, @@ -961,7 +961,7 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> { hir::ItemKind::Union(_, ref generics) => { if generics.params.is_empty() { if self.mode == MonoItemCollectionMode::Eager { - let def_id = self.tcx.hir.local_def_id(item.id); + let def_id = self.tcx.hir().local_def_id(item.id); debug!("RootCollector: ADT drop-glue for {}", def_id_to_string(self.tcx, def_id)); @@ -973,11 +973,11 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> { hir::ItemKind::GlobalAsm(..) => { debug!("RootCollector: ItemKind::GlobalAsm({})", def_id_to_string(self.tcx, - self.tcx.hir.local_def_id(item.id))); + self.tcx.hir().local_def_id(item.id))); self.output.push(MonoItem::GlobalAsm(item.id)); } hir::ItemKind::Static(..) => { - let def_id = self.tcx.hir.local_def_id(item.id); + let def_id = self.tcx.hir().local_def_id(item.id); debug!("RootCollector: ItemKind::Static({})", def_id_to_string(self.tcx, def_id)); self.output.push(MonoItem::Static(def_id)); @@ -987,7 +987,7 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> { // actually used somewhere. Just declaring them is insufficient. // but even just declaring them must collect the items they refer to - let def_id = self.tcx.hir.local_def_id(item.id); + let def_id = self.tcx.hir().local_def_id(item.id); let instance = Instance::mono(self.tcx, def_id); let cid = GlobalId { @@ -1001,7 +1001,7 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> { } } hir::ItemKind::Fn(..) => { - let def_id = self.tcx.hir.local_def_id(item.id); + let def_id = self.tcx.hir().local_def_id(item.id); self.push_if_root(def_id); } } @@ -1015,7 +1015,7 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> { fn visit_impl_item(&mut self, ii: &'v hir::ImplItem) { match ii.node { hir::ImplItemKind::Method(hir::MethodSig { .. }, _) => { - let def_id = self.tcx.hir.local_def_id(ii.id); + let def_id = self.tcx.hir().local_def_id(ii.id); self.push_if_root(def_id); } _ => { /* Nothing to do here */ } @@ -1108,7 +1108,7 @@ fn create_mono_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } - let impl_def_id = tcx.hir.local_def_id(item.id); + let impl_def_id = tcx.hir().local_def_id(item.id); debug!("create_mono_items_for_default_impls(item={})", def_id_to_string(tcx, impl_def_id)); @@ -1161,22 +1161,22 @@ fn collect_miri<'a, 'tcx>( alloc_id: AllocId, output: &mut Vec>, ) { - let alloc_type = tcx.alloc_map.lock().get(alloc_id); - match alloc_type { - Some(AllocType::Static(did)) => { + let alloc_kind = tcx.alloc_map.lock().get(alloc_id); + match alloc_kind { + Some(AllocKind::Static(did)) => { let instance = Instance::mono(tcx, did); if should_monomorphize_locally(tcx, &instance) { trace!("collecting static {:?}", did); output.push(MonoItem::Static(did)); } } - Some(AllocType::Memory(alloc)) => { + Some(AllocKind::Memory(alloc)) => { trace!("collecting {:?} with {:#?}", alloc_id, alloc); for &((), inner) in alloc.relocations.values() { collect_miri(tcx, inner, output); } }, - Some(AllocType::Function(fn_instance)) => { + Some(AllocKind::Function(fn_instance)) => { if should_monomorphize_locally(tcx, &fn_instance) { trace!("collecting {:?} with {:#?}", alloc_id, fn_instance); output.push(create_fn_mono_item(fn_instance)); diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs index 24de92e79f0..2bc6e93c8c1 100644 --- a/src/librustc_mir/monomorphize/item.rs +++ b/src/librustc_mir/monomorphize/item.rs @@ -68,7 +68,7 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug { tcx.symbol_name(Instance::mono(tcx, def_id)) } MonoItem::GlobalAsm(node_id) => { - let def_id = tcx.hir.local_def_id(node_id); + let def_id = tcx.hir().local_def_id(node_id); ty::SymbolName { name: Symbol::intern(&format!("global_asm_{:?}", def_id)).as_interned_str() } @@ -86,7 +86,7 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug { match *self.as_mono_item() { MonoItem::Fn(ref instance) => { let entry_def_id = - tcx.sess.entry_fn.borrow().map(|(id, _, _)| tcx.hir.local_def_id(id)); + tcx.sess.entry_fn.borrow().map(|(id, _, _)| tcx.hir().local_def_id(id)); // If this function isn't inlined or otherwise has explicit // linkage, then we'll be creating a globally shared version. if self.explicit_linkage(tcx).is_some() || @@ -199,15 +199,15 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug { fn local_span(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option { match *self.as_mono_item() { MonoItem::Fn(Instance { def, .. }) => { - tcx.hir.as_local_node_id(def.def_id()) + tcx.hir().as_local_node_id(def.def_id()) } MonoItem::Static(def_id) => { - tcx.hir.as_local_node_id(def_id) + tcx.hir().as_local_node_id(def_id) } MonoItem::GlobalAsm(node_id) => { Some(node_id) } - }.map(|node_id| tcx.hir.span(node_id)) + }.map(|node_id| tcx.hir().span(node_id)) } } diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index 3a6ee6da422..00974d4a5b2 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -51,7 +51,7 @@ //! //! - There are two codegen units for every source-level module: //! - One for "stable", that is non-generic, code -//! - One for more "volatile" code, i.e. monomorphized instances of functions +//! - One for more "volatile" code, i.e., monomorphized instances of functions //! defined in that module //! //! In order to see why this heuristic makes sense, let's take a look at when a @@ -184,7 +184,7 @@ pub trait CodegenUnitExt<'tcx> { // the codegen tests and can even make item order // unstable. InstanceDef::Item(def_id) => { - tcx.hir.as_local_node_id(def_id) + tcx.hir().as_local_node_id(def_id) } InstanceDef::VtableShim(..) | InstanceDef::Intrinsic(..) | @@ -198,7 +198,7 @@ pub trait CodegenUnitExt<'tcx> { } } MonoItem::Static(def_id) => { - tcx.hir.as_local_node_id(def_id) + tcx.hir().as_local_node_id(def_id) } MonoItem::GlobalAsm(node_id) => { Some(node_id) @@ -415,7 +415,7 @@ fn mono_item_visibility( }; } MonoItem::GlobalAsm(node_id) => { - let def_id = tcx.hir.local_def_id(*node_id); + let def_id = tcx.hir().local_def_id(*node_id); return if tcx.is_reachable_non_generic(def_id) { *can_be_internalized = false; default_visibility(tcx, def_id, false) @@ -585,7 +585,7 @@ fn merge_codegen_units<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, // smallest into each other) we're sure to start off with a deterministic // order (sorted by name). This'll mean that if two cgus have the same size // the stable sort below will keep everything nice and deterministic. - codegen_units.sort_by_key(|cgu| cgu.name().clone()); + codegen_units.sort_by_key(|cgu| *cgu.name()); // Merge the two smallest codegen units until the target size is reached. while codegen_units.len() > target_cgu_count { @@ -799,7 +799,7 @@ fn characteristic_def_id_of_mono_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, Some(def_id) } MonoItem::Static(def_id) => Some(def_id), - MonoItem::GlobalAsm(node_id) => Some(tcx.hir.local_def_id(node_id)), + MonoItem::GlobalAsm(node_id) => Some(tcx.hir().local_def_id(node_id)), } } @@ -985,7 +985,7 @@ fn collect_and_partition_mono_items<'a, 'tcx>( output.push_str(" @@"); let mut empty = Vec::new(); let cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty); - cgus.as_mut_slice().sort_by_cached_key(|&(ref name, _)| name.clone()); + cgus.sort_by_key(|(name, _)| *name); cgus.dedup(); for &(ref cgu_name, (linkage, _)) in cgus.iter() { output.push_str(" "); diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 04079319a78..3802b019127 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -219,23 +219,19 @@ fn build_drop_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, local_decls_for_sig(&sig, span), sig.inputs().len(), vec![], - span + span, + vec![], ); if let Some(..) = ty { // The first argument (index 0), but add 1 for the return value. let dropee_ptr = Place::Local(Local::new(1+0)); if tcx.sess.opts.debugging_opts.mir_emit_retag { - // Function arguments should be retagged + // Function arguments should be retagged, and we make this one raw. mir.basic_blocks_mut()[START_BLOCK].statements.insert(0, Statement { source_info, - kind: StatementKind::Retag { fn_entry: true, place: dropee_ptr.clone() }, + kind: StatementKind::Retag(RetagKind::Raw, dropee_ptr.clone()), }); - // We use raw ptr operations, better prepare the alias tracking for that - mir.basic_blocks_mut()[START_BLOCK].statements.insert(1, Statement { - source_info, - kind: StatementKind::EscapeToRaw(Operand::Copy(dropee_ptr.clone())), - }) } let patch = { let param_env = tcx.param_env(def_id).with_reveal_all(); @@ -392,7 +388,8 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> { self.local_decls, self.sig.inputs().len(), vec![], - self.span + self.span, + vec![], ) } @@ -840,7 +837,8 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, local_decls, sig.inputs().len(), vec![], - span + span, + vec![], ); if let Abi::RustCall = sig.abi { mir.spread_arg = Some(Local::new(sig.inputs().len())); @@ -856,7 +854,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>, { let tcx = infcx.tcx; let gcx = tcx.global_tcx(); - let def_id = tcx.hir.local_def_id(ctor_id); + let def_id = tcx.hir().local_def_id(ctor_id); let param_env = gcx.param_env(def_id); // Normalize the sig. @@ -917,6 +915,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>, local_decls, sig.inputs().len(), vec![], - span + span, + vec![], ) } diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs index be7e34e2dcb..69c0a68ae70 100644 --- a/src/librustc_mir/transform/add_retag.rs +++ b/src/librustc_mir/transform/add_retag.rs @@ -118,7 +118,7 @@ impl MirPass for AddRetag { basic_blocks[START_BLOCK].statements.splice(0..0, places.into_iter().map(|place| Statement { source_info, - kind: StatementKind::Retag { fn_entry: true, place }, + kind: StatementKind::Retag(RetagKind::FnEntry, place), }) ); } @@ -154,7 +154,7 @@ impl MirPass for AddRetag { for (source_info, dest_place, dest_block) in returns { basic_blocks[dest_block].statements.insert(0, Statement { source_info, - kind: StatementKind::Retag { fn_entry: false, place: dest_place }, + kind: StatementKind::Retag(RetagKind::Default, dest_place), }); } @@ -164,9 +164,9 @@ impl MirPass for AddRetag { // We want to insert statements as we iterate. To this end, we // iterate backwards using indices. for i in (0..block_data.statements.len()).rev() { - match block_data.statements[i].kind { - // If we are casting *from* a reference, we may have to escape-to-raw. - StatementKind::Assign(_, box Rvalue::Cast( + let (retag_kind, place) = match block_data.statements[i].kind { + // If we are casting *from* a reference, we may have to retag-as-raw. + StatementKind::Assign(ref place, box Rvalue::Cast( CastKind::Misc, ref src, dest_ty, @@ -175,33 +175,35 @@ impl MirPass for AddRetag { if src_ty.is_region_ptr() { // The only `Misc` casts on references are those creating raw pointers. assert!(dest_ty.is_unsafe_ptr()); - // Insert escape-to-raw before the cast. We are not concerned - // with stability here: Our EscapeToRaw will not change the value - // that the cast will then use. - // `src` might be a "move", but we rely on this not actually moving - // but just doing a memcpy. It is crucial that we do EscapeToRaw - // on the src because we need it with its original type. - let source_info = block_data.statements[i].source_info; - block_data.statements.insert(i, Statement { - source_info, - kind: StatementKind::EscapeToRaw(src.clone()), - }); + (RetagKind::Raw, place) + } else { + // Some other cast, no retag + continue } } // Assignments of reference or ptr type are the ones where we may have // to update tags. This includes `x = &[mut] ...` and hence // we also retag after taking a reference! - StatementKind::Assign(ref place, _) if needs_retag(place) => { - // Insert a retag after the assignment. - let source_info = block_data.statements[i].source_info; - block_data.statements.insert(i+1, Statement { - source_info, - kind: StatementKind::Retag { fn_entry: false, place: place.clone() }, - }); + StatementKind::Assign(ref place, box ref rvalue) if needs_retag(place) => { + let kind = match rvalue { + Rvalue::Ref(_, borrow_kind, _) + if borrow_kind.allows_two_phase_borrow() + => + RetagKind::TwoPhase, + _ => + RetagKind::Default, + }; + (kind, place) } // Do nothing for the rest - _ => {}, + _ => continue, }; + // Insert a retag after the statement. + let source_info = block_data.statements[i].source_info; + block_data.statements.insert(i+1, Statement { + source_info, + kind: StatementKind::Retag(retag_kind, place.clone()), + }); } } } diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 3404772f825..f6b7f817aad 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -23,6 +23,9 @@ use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext}; use syntax::ast; use syntax::symbol::Symbol; +use syntax::feature_gate::{emit_feature_err, GateIssue}; + +use std::ops::Bound; use util; @@ -34,6 +37,7 @@ pub struct UnsafetyChecker<'a, 'tcx: 'a> { source_info: SourceInfo, tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, + /// mark an `unsafe` block as used, so we don't lint it used_unsafe: FxHashSet, inherited_blocks: Vec<(ast::NodeId, bool)>, } @@ -93,7 +97,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { if let hir::Unsafety::Unsafe = sig.unsafety() { self.require_unsafe("call to unsafe function", "consult the function's documentation for information on how to avoid \ - undefined behavior") + undefined behavior", UnsafetyViolationKind::GatedConstFnCall) } } } @@ -113,7 +117,6 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { StatementKind::StorageLive(..) | StatementKind::StorageDead(..) | StatementKind::Retag { .. } | - StatementKind::EscapeToRaw { .. } | StatementKind::AscribeUserType(..) | StatementKind::Nop => { // safe (at least as emitted during MIR construction) @@ -121,7 +124,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { StatementKind::InlineAsm { .. } => { self.require_unsafe("use of inline assembly", - "inline assembly is entirely unchecked and can cause undefined behavior") + "inline assembly is entirely unchecked and can cause undefined behavior", + UnsafetyViolationKind::General) }, } self.super_statement(block, statement, location); @@ -134,8 +138,18 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { if let &Rvalue::Aggregate(box ref aggregate, _) = rvalue { match aggregate { &AggregateKind::Array(..) | - &AggregateKind::Tuple | - &AggregateKind::Adt(..) => {} + &AggregateKind::Tuple => {} + &AggregateKind::Adt(ref def, ..) => { + match self.tcx.layout_scalar_valid_range(def.did) { + (Bound::Unbounded, Bound::Unbounded) => {}, + _ => self.require_unsafe( + "initializing type with `rustc_layout_scalar_valid_range` attr", + "initializing a layout restricted type's field with a value outside \ + the valid range is undefined behavior", + UnsafetyViolationKind::GeneralAndConstFn, + ), + } + } &AggregateKind::Closure(def_id, _) | &AggregateKind::Generator(def_id, _, _) => { let UnsafetyCheckResult { @@ -152,28 +166,43 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { place: &Place<'tcx>, context: PlaceContext<'tcx>, location: Location) { - if context.is_borrow() { - if util::is_disaligned(self.tcx, self.mir, self.param_env, place) { - let source_info = self.source_info; - let lint_root = - self.source_scope_local_data[source_info.scope].lint_root; - self.register_violations(&[UnsafetyViolation { - source_info, - description: Symbol::intern("borrow of packed field").as_interned_str(), - details: - Symbol::intern("fields of packed structs might be misaligned: \ - dereferencing a misaligned pointer or even just creating a \ - misaligned reference is undefined behavior") - .as_interned_str(), - kind: UnsafetyViolationKind::BorrowPacked(lint_root) - }], &[]); - } - } - match place { &Place::Projection(box Projection { ref base, ref elem }) => { + if context.is_borrow() { + if util::is_disaligned(self.tcx, self.mir, self.param_env, place) { + let source_info = self.source_info; + let lint_root = + self.source_scope_local_data[source_info.scope].lint_root; + self.register_violations(&[UnsafetyViolation { + source_info, + description: Symbol::intern("borrow of packed field").as_interned_str(), + details: + Symbol::intern("fields of packed structs might be misaligned: \ + dereferencing a misaligned pointer or even just \ + creating a misaligned reference is undefined \ + behavior") + .as_interned_str(), + kind: UnsafetyViolationKind::BorrowPacked(lint_root) + }], &[]); + } + } + let is_borrow_of_interior_mut = context.is_borrow() && !base + .ty(self.mir, self.tcx) + .to_ty(self.tcx) + .is_freeze(self.tcx, self.param_env, self.source_info.span); + // prevent + // * `&mut x.field` + // * `x.field = y;` + // * `&x.field` if `field`'s type has interior mutability + // because either of these would allow modifying the layout constrained field and + // insert values that violate the layout constraints. + if context.is_mutating_use() || is_borrow_of_interior_mut { + self.check_mut_borrowing_layout_constrained_field( + place, context.is_mutating_use(), + ); + } let old_source_info = self.source_info; if let &Place::Local(local) = base { if self.mir.local_decls[local].internal { @@ -189,7 +218,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { self.require_unsafe("dereference of raw pointer", "raw pointers may be NULL, dangling or unaligned; they can violate \ aliasing rules and cause data races: all of these are undefined \ - behavior") + behavior", UnsafetyViolationKind::General) } ty::Adt(adt, _) => { if adt.is_union() { @@ -212,14 +241,15 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { "assignment to non-`Copy` union field", "the previous content of the field will be dropped, which \ causes undefined behavior if the field was not properly \ - initialized") + initialized", UnsafetyViolationKind::General) } else { // write to non-move union, safe } } else { self.require_unsafe("access to union field", "the field may not be properly initialized: using \ - uninitialized data will cause undefined behavior") + uninitialized data will cause undefined behavior", + UnsafetyViolationKind::General) } } } @@ -237,7 +267,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { if self.tcx.is_static(def_id) == Some(hir::Mutability::MutMutable) { self.require_unsafe("use of mutable static", "mutable statics can be mutated by multiple threads: aliasing violations \ - or data races will cause undefined behavior"); + or data races will cause undefined behavior", + UnsafetyViolationKind::General); } else if self.tcx.is_foreign_item(def_id) { let source_info = self.source_info; let lint_root = @@ -260,45 +291,92 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { } impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { - fn require_unsafe(&mut self, - description: &'static str, - details: &'static str) - { + fn require_unsafe( + &mut self, + description: &'static str, + details: &'static str, + kind: UnsafetyViolationKind, + ) { let source_info = self.source_info; self.register_violations(&[UnsafetyViolation { source_info, description: Symbol::intern(description).as_interned_str(), details: Symbol::intern(details).as_interned_str(), - kind: UnsafetyViolationKind::General, + kind, }], &[]); } fn register_violations(&mut self, violations: &[UnsafetyViolation], unsafe_blocks: &[(ast::NodeId, bool)]) { - if self.min_const_fn { - for violation in violations { - let mut violation = violation.clone(); - violation.kind = UnsafetyViolationKind::MinConstFn; - if !self.violations.contains(&violation) { - self.violations.push(violation) - } - } - } - let within_unsafe = match self.source_scope_local_data[self.source_info.scope].safety { + let safety = self.source_scope_local_data[self.source_info.scope].safety; + let within_unsafe = match safety { + // `unsafe` blocks are required in safe code Safety::Safe => { for violation in violations { - if !self.violations.contains(violation) { - self.violations.push(violation.clone()) + let mut violation = violation.clone(); + match violation.kind { + UnsafetyViolationKind::GeneralAndConstFn | + UnsafetyViolationKind::General => {}, + UnsafetyViolationKind::BorrowPacked(_) | + UnsafetyViolationKind::ExternStatic(_) => if self.min_const_fn { + // const fns don't need to be backwards compatible and can + // emit these violations as a hard error instead of a backwards + // compat lint + violation.kind = UnsafetyViolationKind::General; + }, + UnsafetyViolationKind::GatedConstFnCall => { + // safe code can't call unsafe const fns, this `UnsafetyViolationKind` + // is only relevant for `Safety::ExplicitUnsafe` in `unsafe const fn`s + violation.kind = UnsafetyViolationKind::General; + } + } + if !self.violations.contains(&violation) { + self.violations.push(violation) } } false } + // `unsafe` function bodies allow unsafe without additional unsafe blocks Safety::BuiltinUnsafe | Safety::FnUnsafe => true, Safety::ExplicitUnsafe(node_id) => { + // mark unsafe block as used if there are any unsafe operations inside if !violations.is_empty() { self.used_unsafe.insert(node_id); } + // only some unsafety is allowed in const fn + if self.min_const_fn { + let min_const_unsafe_fn = self.tcx.features().min_const_unsafe_fn; + for violation in violations { + match violation.kind { + UnsafetyViolationKind::GatedConstFnCall if min_const_unsafe_fn => { + // these function calls to unsafe functions are allowed + // if `#![feature(min_const_unsafe_fn)]` is active + }, + UnsafetyViolationKind::GatedConstFnCall => { + // without the feature gate, we report errors + if !self.violations.contains(&violation) { + self.violations.push(violation.clone()) + } + } + // these unsafe things are stable in const fn + UnsafetyViolationKind::GeneralAndConstFn => {}, + // these things are forbidden in const fns + UnsafetyViolationKind::General | + UnsafetyViolationKind::BorrowPacked(_) | + UnsafetyViolationKind::ExternStatic(_) => { + let mut violation = violation.clone(); + // const fns don't need to be backwards compatible and can + // emit these violations as a hard error instead of a backwards + // compat lint + violation.kind = UnsafetyViolationKind::General; + if !self.violations.contains(&violation) { + self.violations.push(violation) + } + }, + } + } + } true } }; @@ -306,6 +384,53 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { (node_id, is_used && !within_unsafe) })); } + fn check_mut_borrowing_layout_constrained_field( + &mut self, + mut place: &Place<'tcx>, + is_mut_use: bool, + ) { + while let &Place::Projection(box Projection { + ref base, ref elem + }) = place { + match *elem { + ProjectionElem::Field(..) => { + let ty = base.ty(&self.mir.local_decls, self.tcx).to_ty(self.tcx); + match ty.sty { + ty::Adt(def, _) => match self.tcx.layout_scalar_valid_range(def.did) { + (Bound::Unbounded, Bound::Unbounded) => {}, + _ => { + let (description, details) = if is_mut_use { + ( + "mutation of layout constrained field", + "mutating layout constrained fields cannot statically be \ + checked for valid values", + ) + } else { + ( + "borrow of layout constrained field with interior \ + mutability", + "references to fields of layout constrained fields \ + lose the constraints. Coupled with interior mutability, \ + the field can be changed to invalid values", + ) + }; + let source_info = self.source_info; + self.register_violations(&[UnsafetyViolation { + source_info, + description: Symbol::intern(description).as_interned_str(), + details: Symbol::intern(details).as_interned_str(), + kind: UnsafetyViolationKind::GeneralAndConstFn, + }], &[]); + } + }, + _ => {} + } + } + _ => {} + } + place = base; + } + } } pub(crate) fn provide(providers: &mut Providers) { @@ -343,8 +468,8 @@ fn check_unused_unsafe<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, unsafe_blocks: &'a mut Vec<(ast::NodeId, bool)>) { let body_id = - tcx.hir.as_local_node_id(def_id).and_then(|node_id| { - tcx.hir.maybe_body_owned_by(node_id) + tcx.hir().as_local_node_id(def_id).and_then(|node_id| { + tcx.hir().maybe_body_owned_by(node_id) }); let body_id = match body_id { @@ -354,7 +479,7 @@ fn check_unused_unsafe<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, return } }; - let body = tcx.hir.body(body_id); + let body = tcx.hir().body(body_id); debug!("check_unused_unsafe({:?}, body={:?}, used_unsafe={:?})", def_id, body, used_unsafe); @@ -367,7 +492,7 @@ fn unsafety_check_result<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { debug!("unsafety_violations({:?})", def_id); - // NB: this borrow is valid because all the consumers of + // N.B., this borrow is valid because all the consumers of // `mir_built` force this. let mir = &tcx.mir_built(def_id).borrow(); @@ -384,7 +509,7 @@ fn unsafety_check_result<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) let param_env = tcx.param_env(def_id); let mut checker = UnsafetyChecker::new( - tcx.is_const_fn(def_id) && tcx.is_min_const_fn(def_id), + tcx.is_min_const_fn(def_id), mir, source_scope_local_data, tcx, param_env); checker.visit_mir(mir); @@ -396,7 +521,7 @@ fn unsafety_check_result<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) } fn unsafe_derive_on_repr_packed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { - let lint_node_id = match tcx.hir.as_local_node_id(def_id) { + let lint_node_id = match tcx.hir().as_local_node_id(def_id) { Some(node_id) => node_id, None => bug!("checking unsafety for non-local def id {:?}", def_id) }; @@ -420,14 +545,14 @@ fn unsafe_derive_on_repr_packed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: D fn is_enclosed(tcx: TyCtxt, used_unsafe: &FxHashSet, id: ast::NodeId) -> Option<(String, ast::NodeId)> { - let parent_id = tcx.hir.get_parent_node(id); + let parent_id = tcx.hir().get_parent_node(id); if parent_id != id { if used_unsafe.contains(&parent_id) { Some(("block".to_string(), parent_id)) } else if let Some(Node::Item(&hir::Item { node: hir::ItemKind::Fn(_, header, _, _), .. - })) = tcx.hir.find(parent_id) { + })) = tcx.hir().find(parent_id) { match header.unsafety { hir::Unsafety::Unsafe => Some(("fn".to_string(), parent_id)), hir::Unsafety::Normal => None, @@ -441,12 +566,12 @@ fn is_enclosed(tcx: TyCtxt, } fn report_unused_unsafe(tcx: TyCtxt, used_unsafe: &FxHashSet, id: ast::NodeId) { - let span = tcx.sess.source_map().def_span(tcx.hir.span(id)); + let span = tcx.sess.source_map().def_span(tcx.hir().span(id)); let msg = "unnecessary `unsafe` block"; let mut db = tcx.struct_span_lint_node(UNUSED_UNSAFE, id, span, msg); db.span_label(span, msg); if let Some((kind, id)) = is_enclosed(tcx, used_unsafe, id) { - db.span_label(tcx.sess.source_map().def_span(tcx.hir.span(id)), + db.span_label(tcx.sess.source_map().def_span(tcx.hir().span(id)), format!("because it's nested under this `unsafe` {}", kind)); } db.emit(); @@ -486,6 +611,7 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { } in violations.iter() { // Report an error. match kind { + UnsafetyViolationKind::GeneralAndConstFn | UnsafetyViolationKind::General => { struct_span_err!( tcx.sess, source_info.span, E0133, @@ -494,14 +620,15 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { .note(&details.as_str()[..]) .emit(); } - UnsafetyViolationKind::MinConstFn => { - tcx.sess.struct_span_err( + UnsafetyViolationKind::GatedConstFnCall => { + emit_feature_err( + &tcx.sess.parse_sess, + "min_const_unsafe_fn", source_info.span, - &format!("{} is unsafe and unsafe operations \ - are not allowed in const fn", description)) - .span_label(source_info.span, &description.as_str()[..]) - .note(&details.as_str()[..]) - .emit(); + GateIssue::Language, + "calls to `const unsafe fn` in const fns are unstable", + ); + } UnsafetyViolationKind::ExternStatic(lint_node_id) => { tcx.lint_node_note(SAFE_EXTERN_STATICS, diff --git a/src/librustc_mir/transform/cleanup_post_borrowck.rs b/src/librustc_mir/transform/cleanup_post_borrowck.rs index c0edd3926d3..6d7fc404edb 100644 --- a/src/librustc_mir/transform/cleanup_post_borrowck.rs +++ b/src/librustc_mir/transform/cleanup_post_borrowck.rs @@ -10,17 +10,25 @@ //! This module provides two passes: //! -//! - [CleanAscribeUserType], that replaces all -//! [StatementKind::AscribeUserType] statements with [StatementKind::Nop]. -//! - [CleanFakeReadsAndBorrows], that replaces all [FakeRead] statements and -//! borrows that are read by [FakeReadCause::ForMatchGuard] fake reads with -//! [StatementKind::Nop]. +//! - [`CleanAscribeUserType`], that replaces all [`AscribeUserType`] +//! statements with [`Nop`]. +//! - [`CleanFakeReadsAndBorrows`], that replaces all [`FakeRead`] statements +//! and borrows that are read by [`ForMatchGuard`] fake reads with [`Nop`]. //! -//! The [CleanFakeReadsAndBorrows] "pass" is actually implemented as two +//! The `CleanFakeReadsAndBorrows` "pass" is actually implemented as two //! traversals (aka visits) of the input MIR. The first traversal, -//! [DeleteAndRecordFakeReads], deletes the fake reads and finds the temporaries -//! read by [ForMatchGuard] reads, and [DeleteFakeBorrows] deletes the -//! initialization of those temporaries. +//! [`DeleteAndRecordFakeReads`], deletes the fake reads and finds the +//! temporaries read by [`ForMatchGuard`] reads, and [`DeleteFakeBorrows`] +//! deletes the initialization of those temporaries. +//! +//! [`CleanAscribeUserType`]: cleanup_post_borrowck::CleanAscribeUserType +//! [`CleanFakeReadsAndBorrows`]: cleanup_post_borrowck::CleanFakeReadsAndBorrows +//! [`DeleteAndRecordFakeReads`]: cleanup_post_borrowck::DeleteAndRecordFakeReads +//! [`DeleteFakeBorrows`]: cleanup_post_borrowck::DeleteFakeBorrows +//! [`AscribeUserType`]: rustc::mir::StatementKind::AscribeUserType +//! [`Nop`]: rustc::mir::StatementKind::Nop +//! [`FakeRead`]: rustc::mir::StatementKind::FakeRead +//! [`ForMatchGuard`]: rustc::mir::FakeReadCause::ForMatchGuard use rustc_data_structures::fx::FxHashSet; diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index f21efaa048b..cfa899eb5a6 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -47,10 +47,10 @@ impl MirPass for ConstProp { } use rustc::hir::map::blocks::FnLikeNode; - let node_id = tcx.hir.as_local_node_id(source.def_id) + let node_id = tcx.hir().as_local_node_id(source.def_id) .expect("Non-local call to local provider is_const_fn"); - let is_fn_like = FnLikeNode::from_node(tcx.hir.get(node_id)).is_some(); + let is_fn_like = FnLikeNode::from_node(tcx.hir().get(node_id)).is_some(); let is_assoc_const = match tcx.describe_def(source.def_id) { Some(Def::AssociatedConst(_)) => true, _ => false, @@ -289,7 +289,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> { })?; Some((res, span)) }, - // We could get more projections by using e.g. `operand_projection`, + // We could get more projections by using e.g., `operand_projection`, // but we do not even have the stack frame set up properly so // an `Index` projection would throw us off-track. _ => None, @@ -346,7 +346,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> { Rvalue::Cast(kind, ref operand, _) => { let (op, span) = self.eval_operand(operand, source_info)?; self.use_ecx(source_info, |this| { - let dest = this.ecx.allocate(place_layout, MemoryKind::Stack)?; + let dest = this.ecx.allocate(place_layout, MemoryKind::Stack); this.ecx.cast(op, kind, dest.into())?; Ok((dest.into(), span)) }) @@ -618,7 +618,7 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> { .span; let node_id = self .tcx - .hir + .hir() .as_local_node_id(self.source.def_id) .expect("some part of a failing const eval must be local"); use rustc::mir::interpret::EvalErrorKind::*; diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index 2b3fd552e0f..caae5c8553e 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -38,7 +38,7 @@ impl MirPass for ElaborateDrops { { debug!("elaborate_drops({:?} @ {:?})", src, mir.span); - let id = tcx.hir.as_local_node_id(src.def_id).unwrap(); + let id = tcx.hir().as_local_node_id(src.def_id).unwrap(); let param_env = tcx.param_env(src.def_id).with_reveal_all(); let move_data = match MoveData::gather_moves(mir, tcx) { Ok(move_data) => move_data, @@ -303,8 +303,8 @@ struct ElaborateDropsCtxt<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>, env: &'a MoveDataParamEnv<'tcx, 'tcx>, - flow_inits: DataflowResults>, - flow_uninits: DataflowResults>, + flow_inits: DataflowResults<'tcx, MaybeInitializedPlaces<'a, 'tcx, 'tcx>>, + flow_uninits: DataflowResults<'tcx, MaybeUninitializedPlaces<'a, 'tcx, 'tcx>>, drop_flags: FxHashMap, patch: MirPatch<'tcx>, } diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 24cc4cce747..fe19accb031 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -379,7 +379,7 @@ fn locals_live_across_suspend_points( FxHashMap>, ) { let dead_unwinds = BitSet::new_empty(mir.basic_blocks().len()); - let node_id = tcx.hir.as_local_node_id(source.def_id).unwrap(); + 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 // lifetimes. @@ -689,7 +689,7 @@ fn create_generator_drop_shim<'a, 'tcx>( // Alias tracking must know we changed the type mir.basic_blocks_mut()[START_BLOCK].statements.insert(0, Statement { source_info, - kind: StatementKind::EscapeToRaw(Operand::Copy(Place::Local(self_arg()))), + kind: StatementKind::Retag(RetagKind::Raw, Place::Local(self_arg())), }) } diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 1cce0de5152..88424d75baa 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -83,8 +83,8 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { let param_env = self.tcx.param_env(self.source.def_id); // Only do inlining into fn bodies. - let id = self.tcx.hir.as_local_node_id(self.source.def_id).unwrap(); - let body_owner_kind = self.tcx.hir.body_owner_kind(id); + let id = self.tcx.hir().as_local_node_id(self.source.def_id).unwrap(); + let body_owner_kind = self.tcx.hir().body_owner_kind(id); if let (hir::BodyOwnerKind::Fn, None) = (body_owner_kind, self.source.promoted) { @@ -575,10 +575,10 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { // The `tmp0`, `tmp1`, and `tmp2` in our example abonve. let tuple_tmp_args = tuple_tys.iter().enumerate().map(|(i, ty)| { - // This is e.g. `tuple_tmp.0` in our example above. + // This is e.g., `tuple_tmp.0` in our example above. let tuple_field = Operand::Move(tuple.clone().field(Field::new(i), ty)); - // Spill to a local to make e.g. `tmp0`. + // Spill to a local to make e.g., `tmp0`. self.create_temp_if_necessary(tuple_field, callsite, caller_mir) }); @@ -707,12 +707,19 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { self.in_cleanup_block = false; } - fn visit_retag(&mut self, fn_entry: &mut bool, place: &mut Place<'tcx>, loc: Location) { - self.super_retag(fn_entry, place, loc); + fn visit_retag( + &mut self, + kind: &mut RetagKind, + place: &mut Place<'tcx>, + loc: Location, + ) { + self.super_retag(kind, place, loc); // We have to patch all inlined retags to be aware that they are no longer // happening on function entry. - *fn_entry = false; + if *kind == RetagKind::FnEntry { + *kind = RetagKind::Default; + } } fn visit_terminator_kind(&mut self, block: BasicBlock, diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index a77e9b502ac..005c1a08aff 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -91,7 +91,7 @@ fn mir_keys<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, krate: CrateNum) _: ast::NodeId, _: Span) { if let hir::VariantData::Tuple(_, node_id) = *v { - self.set.insert(self.tcx.hir.local_def_id(node_id)); + self.set.insert(self.tcx.hir().local_def_id(node_id)); } intravisit::walk_struct_def(self, v) } @@ -99,7 +99,7 @@ fn mir_keys<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, krate: CrateNum) NestedVisitorMap::None } } - tcx.hir.krate().visit_all_item_likes(&mut GatherCtors { + tcx.hir().krate().visit_all_item_likes(&mut GatherCtors { tcx, set: &mut set, }.as_deep_visitor()); @@ -219,8 +219,8 @@ fn mir_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Stea } fn mir_validated<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal> { - let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); - if let hir::BodyOwnerKind::Const = tcx.hir.body_owner_kind(node_id) { + let node_id = tcx.hir().as_local_node_id(def_id).unwrap(); + if let hir::BodyOwnerKind::Const = tcx.hir().body_owner_kind(node_id) { // Ensure that we compute the `mir_const_qualif` for constants at // this point, before we steal the mir-const result. let _ = tcx.mir_const_qualif(def_id); diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index c5add626078..f5bf73b4300 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -123,7 +123,7 @@ impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> { } } else if let TempState::Defined { ref mut uses, .. } = *temp { // We always allow borrows, even mutable ones, as we need - // to promote mutable borrows of some ZSTs e.g. `&mut []`. + // to promote mutable borrows of some ZSTs e.g., `&mut []`. let allowed_use = context.is_borrow() || context.is_nonmutating_use(); debug!("visit_local: allowed_use={:?}", allowed_use); if allowed_use { @@ -412,7 +412,8 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>, initial_locals, 0, vec![], - mir.span + mir.span, + vec![], ), tcx, source: mir, diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index bcee6d75b5a..b854f029e51 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -17,6 +17,8 @@ use rustc_data_structures::bit_set::BitSet; use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::sync::Lrc; +use rustc_target::spec::abi::Abi; use rustc::hir; use rustc::hir::def_id::DefId; use rustc::mir::interpret::ConstValue; @@ -28,13 +30,12 @@ use rustc::mir::*; use rustc::mir::traversal::ReversePostorder; use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext, NonMutatingUseContext}; use rustc::middle::lang_items; -use rustc_target::spec::abi::Abi; +use rustc::session::config::nightly_options; use syntax::ast::LitKind; use syntax::feature_gate::{UnstableFeatures, feature_err, emit_feature_err, GateIssue}; use syntax_pos::{Span, DUMMY_SP}; use std::fmt; -use rustc_data_structures::sync::Lrc; use std::usize; use transform::{MirPass, MirSource}; @@ -552,7 +553,13 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { this.super_place(place, context, location); match proj.elem { ProjectionElem::Deref => { - this.add(Qualif::NOT_CONST); + if context.is_mutating_use() { + // `not_const` errors out in const contexts + this.not_const() + } else { + // just make sure this doesn't get promoted + this.add(Qualif::NOT_CONST); + } let base_ty = proj.base.ty(this.mir, this.tcx).to_ty(this.tcx); match this.mode { Mode::Fn => {}, @@ -639,7 +646,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { self.add(qualif); // Just in case the type is more specific than - // the definition, e.g. impl associated const + // the definition, e.g., impl associated const // with type parameters, take it into account. self.qualif.restrict(constant.literal.ty, self.tcx, self.param_env); } @@ -952,10 +959,10 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } } _ => { - // in normal functions we only care about promotion + // In normal functions we only care about promotion. if self.mode == Mode::Fn { - // never promote const fn calls of - // functions without #[rustc_promotable] + // Never promote const fn calls of + // functions without `#[rustc_promotable]`. if self.tcx.is_promotable_const_fn(def_id) { is_const_fn = true; is_promotable_const_fn = true; @@ -963,19 +970,19 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { is_const_fn = true; } } else { - // stable const fn or unstable const fns with their feature gate + // stable const fns or unstable const fns with their feature gate // active if self.tcx.is_const_fn(def_id) { is_const_fn = true; } else if self.is_const_panic_fn(def_id) { - // check the const_panic feature gate + // Check the const_panic feature gate. // FIXME: cannot allow this inside `allow_internal_unstable` // because that would make `panic!` insta stable in constants, - // since the macro is marked with the attr + // since the macro is marked with the attribute. if self.tcx.features().const_panic { is_const_fn = true; } else { - // don't allow panics in constants without the feature gate + // Don't allow panics in constants without the feature gate. emit_feature_err( &self.tcx.sess.parse_sess, "const_panic", @@ -984,25 +991,28 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { &format!("panicking in {}s is unstable", self.mode), ); } - } else if let Some(feat) = self.tcx.is_unstable_const_fn(def_id) { - // check `#[unstable]` const fns or `#[rustc_const_unstable]` - // functions without the feature gate active in this crate to - // report a better error message than the one below + } else if let Some(feature) + = self.tcx.is_unstable_const_fn(def_id) { + // Check `#[unstable]` const fns or `#[rustc_const_unstable]` + // functions without the feature gate active in this crate in + // order to report a better error message than the one below. if self.span.allows_unstable() { - // `allow_internal_unstable` can make such calls stable + // `allow_internal_unstable` can make such calls stable. is_const_fn = true; } else { let mut err = self.tcx.sess.struct_span_err(self.span, &format!("`{}` is not yet stable as a const fn", self.tcx.item_path_str(def_id))); - help!(&mut err, - "in Nightly builds, add `#![feature({})]` \ - to the crate attributes to enable", - feat); + if nightly_options::is_nightly_build() { + help!(&mut err, + "add `#![feature({})]` to the \ + crate attributes to enable", + feature); + } err.emit(); } } else { - // FIXME(#24111) Remove this check when const fn stabilizes + // FIXME(#24111): remove this check when const fn stabilizes. let (msg, note) = if let UnstableFeatures::Disallow = self.tcx.sess.opts.unstable_features { (format!("calls in {}s are limited to \ @@ -1081,7 +1091,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { // we care about constness, not promotability. // If we checked for promotability, we'd miss out on // the results of function calls (which are never promoted - // in runtime code) + // in runtime code). // This is not a problem, because the argument explicitly // requests constness, in contrast to regular promotion // which happens even without the user requesting it. @@ -1098,7 +1108,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { }); } - // non-const fn calls. + // non-const fn calls if !is_const_fn { self.qualif = Qualif::NOT_CONST; if self.mode != Mode::Fn { @@ -1131,7 +1141,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { // Deny *any* live drops anywhere other than functions. if self.mode != Mode::Fn { - // HACK(eddyb) Emulate a bit of dataflow analysis, + // HACK(eddyb): emulate a bit of dataflow analysis, // conservatively, that drop elaboration will do. let needs_drop = if let Place::Local(local) = *place { if self.local_qualif[local].map_or(true, |q| q.contains(Qualif::NEEDS_DROP)) { @@ -1174,7 +1184,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { if self.mir.local_kind(index) == LocalKind::Var && self.const_fn_arg_vars.insert(index) && !self.tcx.features().const_let { - // Direct use of an argument is permitted. match *rvalue { Rvalue::Use(Operand::Copy(Place::Local(local))) | @@ -1185,7 +1194,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } _ => {} } - // Avoid a generic error for other uses of arguments. if self.qualif.contains(Qualif::FN_ARGUMENT) { let decl = &self.mir.local_decls[index]; @@ -1233,7 +1241,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { StatementKind::StorageDead(_) | StatementKind::InlineAsm {..} | StatementKind::Retag { .. } | - StatementKind::EscapeToRaw { .. } | StatementKind::AscribeUserType(..) | StatementKind::Nop => {} } @@ -1259,7 +1266,7 @@ pub fn provide(providers: &mut Providers) { fn mir_const_qualif<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> (u8, Lrc>) { - // NB: This `borrow()` is guaranteed to be valid (i.e., the value + // N.B., 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 // performing the steal. @@ -1293,9 +1300,9 @@ impl MirPass for QualifyAndPromoteConstants { } let def_id = src.def_id; - let id = tcx.hir.as_local_node_id(def_id).unwrap(); + let id = tcx.hir().as_local_node_id(def_id).unwrap(); let mut const_promoted_temps = None; - let mode = match tcx.hir.body_owner_kind(id) { + let mode = match tcx.hir().body_owner_kind(id) { hir::BodyOwnerKind::Fn => { if tcx.is_const_fn(def_id) { Mode::ConstFn @@ -1344,6 +1351,37 @@ impl MirPass for QualifyAndPromoteConstants { // Do the actual promotion, now that we know what's viable. promote_consts::promote_candidates(mir, tcx, temps, candidates); } else { + if !mir.control_flow_destroyed.is_empty() { + let mut locals = mir.vars_iter(); + if let Some(local) = locals.next() { + let span = mir.local_decls[local].source_info.span; + let mut error = tcx.sess.struct_span_err( + span, + &format!( + "new features like let bindings are not permitted in {}s \ + which also use short circuiting operators", + mode, + ), + ); + for (span, kind) in mir.control_flow_destroyed.iter() { + error.span_note( + *span, + &format!("use of {} here does not actually short circuit due to \ + the const evaluator presently not being able to do control flow. \ + See https://github.com/rust-lang/rust/issues/49146 for more \ + information.", kind), + ); + } + for local in locals { + let span = mir.local_decls[local].source_info.span; + error.span_note( + span, + "more locals defined here", + ); + } + error.emit(); + } + } let promoted_temps = if mode == Mode::Const { // Already computed by `mir_const_qualif`. const_promoted_temps.unwrap() diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index 13e134ba859..c1c5b18915a 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -2,6 +2,7 @@ use rustc::hir::def_id::DefId; use rustc::hir; use rustc::mir::*; use rustc::ty::{self, Predicate, TyCtxt}; +use rustc_target::spec::abi; use std::borrow::Cow; use syntax_pos::Span; @@ -229,7 +230,7 @@ fn check_statement( check_rvalue(tcx, mir, rval, span) } - StatementKind::FakeRead(..) => Err((span, "match in const fn is unstable".into())), + StatementKind::FakeRead(_, place) => check_place(tcx, mir, place, span, PlaceMode::Read), // just an assignment StatementKind::SetDiscriminant { .. } => Ok(()), @@ -242,7 +243,6 @@ fn check_statement( | StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | StatementKind::Retag { .. } - | StatementKind::EscapeToRaw { .. } | StatementKind::AscribeUserType(..) | StatementKind::Nop => Ok(()), } @@ -338,19 +338,40 @@ fn check_terminator( } => { let fn_ty = func.ty(mir, tcx); if let ty::FnDef(def_id, _) = fn_ty.sty { - if tcx.is_min_const_fn(def_id) { - check_operand(tcx, mir, func, span)?; - for arg in args { - check_operand(tcx, mir, arg, span)?; - } - Ok(()) - } else { - Err(( + // some intrinsics are waved through if called inside the + // standard library. Users never need to call them directly + match tcx.fn_sig(def_id).abi() { + abi::Abi::RustIntrinsic => match &tcx.item_name(def_id).as_str()[..] { + | "size_of" + | "min_align_of" + | "needs_drop" + => {}, + _ => return Err(( + span, + "can only call a curated list of intrinsics in `min_const_fn`".into(), + )), + }, + abi::Abi::Rust if tcx.is_min_const_fn(def_id) => {}, + abi::Abi::Rust => return Err(( span, "can only call other `min_const_fn` within a `min_const_fn`".into(), - )) + )), + abi => return Err(( + span, + format!( + "cannot call functions with `{}` abi in `min_const_fn`", + abi, + ).into(), + )), } + + check_operand(tcx, mir, func, span)?; + + for arg in args { + check_operand(tcx, mir, arg, span)?; + } + Ok(()) } else { Err((span, "can only call other const fns within const fn".into())) } diff --git a/src/librustc_mir/transform/remove_noop_landing_pads.rs b/src/librustc_mir/transform/remove_noop_landing_pads.rs index a31d12baed2..cdab5a1d7b0 100644 --- a/src/librustc_mir/transform/remove_noop_landing_pads.rs +++ b/src/librustc_mir/transform/remove_noop_landing_pads.rs @@ -58,15 +58,14 @@ impl RemoveNoopLandingPads { } StatementKind::Assign(Place::Local(_), box Rvalue::Use(_)) => { - // Writing to a local (e.g. a drop flag) does not + // Writing to a local (e.g., a drop flag) does not // turn a landing pad to a non-nop } StatementKind::Assign { .. } | StatementKind::SetDiscriminant { .. } | StatementKind::InlineAsm { .. } | - StatementKind::Retag { .. } | - StatementKind::EscapeToRaw { .. } => { + StatementKind::Retag { .. } => { return false; } } diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index f852195b835..e1eeeb8301c 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -34,7 +34,7 @@ impl MirPass for SanityCheck { fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource, mir: &mut Mir<'tcx>) { let def_id = src.def_id; - let id = tcx.hir.as_local_node_id(def_id).unwrap(); + let id = tcx.hir().as_local_node_id(def_id).unwrap(); if !tcx.has_attr(def_id, "rustc_mir") { debug!("skipping rustc_peek::SanityCheck on {}", tcx.item_path_str(def_id)); return; @@ -95,8 +95,8 @@ pub fn sanity_check_via_rustc_peek<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &Mir<'tcx>, id: ast::NodeId, _attributes: &[ast::Attribute], - results: &DataflowResults) - where O: BitDenotation + HasMoveData<'tcx> + results: &DataflowResults<'tcx, O>) + where O: BitDenotation<'tcx, Idx=MovePathIndex> + HasMoveData<'tcx> { debug!("sanity_check_via_rustc_peek id: {:?}", id); // FIXME: this is not DRY. Figure out way to abstract this and @@ -110,9 +110,9 @@ pub fn sanity_check_via_rustc_peek<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &Mir<'tcx>, - results: &DataflowResults, + results: &DataflowResults<'tcx, O>, bb: mir::BasicBlock) where - O: BitDenotation + HasMoveData<'tcx> + O: BitDenotation<'tcx, Idx=MovePathIndex> + HasMoveData<'tcx> { let move_data = results.0.operator.move_data(); let mir::BasicBlockData { ref statements, ref terminator, is_cleanup: _ } = mir[bb]; @@ -162,7 +162,6 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir::StatementKind::StorageDead(_) | mir::StatementKind::InlineAsm { .. } | mir::StatementKind::Retag { .. } | - mir::StatementKind::EscapeToRaw { .. } | mir::StatementKind::AscribeUserType(..) | mir::StatementKind::Nop => continue, mir::StatementKind::SetDiscriminant{ .. } => diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index f643870dec2..592f721b2f5 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -108,10 +108,14 @@ impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> { pub fn simplify(mut self) { self.strip_nops(); + let mut start = START_BLOCK; + loop { let mut changed = false; - for bb in (0..self.basic_blocks.len()).map(BasicBlock::new) { + self.collapse_goto_chain(&mut start, &mut changed); + + for bb in self.basic_blocks.indices() { if self.pred_count[bb] == 0 { continue } @@ -142,6 +146,27 @@ impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> { if !changed { break } } + + if start != START_BLOCK { + debug_assert!(self.pred_count[START_BLOCK] == 0); + self.basic_blocks.swap(START_BLOCK, start); + self.pred_count.swap(START_BLOCK, start); + + // pred_count == 1 if the start block has no predecessor _blocks_. + if self.pred_count[START_BLOCK] > 1 { + for (bb, data) in self.basic_blocks.iter_enumerated_mut() { + if self.pred_count[bb] == 0 { + continue; + } + + for target in data.terminator_mut().successors_mut() { + if *target == start { + *target = START_BLOCK; + } + } + } + } + } } // Collapse a goto chain starting from `start` diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs index ae0483e3c14..8566f845f23 100644 --- a/src/librustc_mir/util/borrowck_errors.rs +++ b/src/librustc_mir/util/borrowck_errors.rs @@ -261,6 +261,7 @@ pub trait BorrowckErrors<'cx>: Sized + Copy { old_loan_span: Span, old_opt_via: &str, previous_end_span: Option, + second_borrow_desc: &str, o: Origin, ) -> DiagnosticBuilder<'cx> { let mut err = struct_span_err!( @@ -274,7 +275,10 @@ pub trait BorrowckErrors<'cx>: Sized + Copy { kind_new, OGN = o ); - err.span_label(new_loan_span, format!("borrow occurs here{}", opt_via)); + err.span_label( + new_loan_span, + format!("{}borrow occurs here{}", second_borrow_desc, opt_via), + ); err.span_label( old_loan_span, format!("{} construction occurs here{}", container_name, old_opt_via), diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 2c7f337b3b1..4f381e0a3d2 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -24,8 +24,8 @@ use std::u32; #[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum DropFlagState { - Present, // i.e. initialized - Absent, // i.e. deinitialized or "moved" + Present, // i.e., initialized + Absent, // i.e., deinitialized or "moved" } impl DropFlagState { diff --git a/src/librustc_mir/util/graphviz.rs b/src/librustc_mir/util/graphviz.rs index 0b883f68bff..58963a40ad0 100644 --- a/src/librustc_mir/util/graphviz.rs +++ b/src/librustc_mir/util/graphviz.rs @@ -38,7 +38,7 @@ pub fn write_mir_fn_graphviz<'tcx, W>(tcx: TyCtxt<'_, '_, 'tcx>, w: &mut W) -> io::Result<()> where W: Write { - writeln!(w, "digraph Mir_{} {{", tcx.hir.as_local_node_id(def_id).unwrap())?; + writeln!(w, "digraph Mir_{} {{", tcx.hir().as_local_node_id(def_id).unwrap())?; // Global graph properties writeln!(w, r#" graph [fontname="monospace"];"#)?; diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index 12c13b8f815..22554acc6ad 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -29,7 +29,7 @@ //! ``` //! //! This means that users of this analysis still have to check whether -//! pre-existing references can be used to access the value (e.g. at movable +//! pre-existing references can be used to access the value (e.g., at movable //! generator yield points, all pre-existing references are invalidated, so this //! doesn't matter). @@ -343,7 +343,7 @@ fn dump_matched_mir_node<'a, 'tcx, V: Idx>( ) { let mut file_path = PathBuf::new(); file_path.push(Path::new(&tcx.sess.opts.debugging_opts.dump_mir_dir)); - let item_id = tcx.hir.as_local_node_id(source.def_id).unwrap(); + let item_id = tcx.hir().as_local_node_id(source.def_id).unwrap(); let file_name = format!("rustc.node{}{}-liveness.mir", item_id, pass_name); file_path.push(&file_name); let _ = fs::File::create(&file_path).and_then(|mut file| { diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index c74492fe649..0db9b23925a 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -24,7 +24,7 @@ use std::path::{Path, PathBuf}; use super::graphviz::write_mir_fn_graphviz; use transform::MirSource; -const INDENT: &'static str = " "; +const INDENT: &str = " "; /// Alignment for lining up comments following MIR statements pub(crate) const ALIGN: usize = 40; @@ -193,7 +193,7 @@ fn dump_path( let mut file_path = PathBuf::new(); file_path.push(Path::new(&tcx.sess.opts.debugging_opts.dump_mir_dir)); - let item_name = tcx.hir + let item_name = tcx.hir() .def_path(source.def_id) .to_filename_friendly_no_crate(); @@ -569,8 +569,8 @@ pub fn write_mir_intro<'a, 'gcx, 'tcx>( } fn write_mir_sig(tcx: TyCtxt, src: MirSource, mir: &Mir, w: &mut dyn Write) -> io::Result<()> { - let id = tcx.hir.as_local_node_id(src.def_id).unwrap(); - let body_owner_kind = tcx.hir.body_owner_kind(id); + let id = tcx.hir().as_local_node_id(src.def_id).unwrap(); + let body_owner_kind = tcx.hir().body_owner_kind(id); match (body_owner_kind, src.promoted) { (_, Some(i)) => write!(w, "{:?} in", i)?, (hir::BodyOwnerKind::Fn, _) => write!(w, "fn")?, diff --git a/src/librustc_msan/Cargo.toml b/src/librustc_msan/Cargo.toml index 29165675a2a..78c39d03e45 100644 --- a/src/librustc_msan/Cargo.toml +++ b/src/librustc_msan/Cargo.toml @@ -16,4 +16,4 @@ cmake = "0.1.18" [dependencies] alloc = { path = "../liballoc" } core = { path = "../libcore" } -compiler_builtins = { path = "../rustc/compiler_builtins_shim" } +compiler_builtins = "0.1.0" diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index b878a330ab6..9a35721e3e1 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -404,7 +404,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } ItemKind::Mod(_) => { - // Ensure that `path` attributes on modules are recorded as used (c.f. #35584). + // Ensure that `path` attributes on modules are recorded as used (cf. issue #35584). attr::first_attr_value_str_by_name(&item.attrs, "path"); if attr::contains_name(&item.attrs, "warn_directory_ownership") { let lint = lint::builtin::LEGACY_DIRECTORY_OWNERSHIP; @@ -529,7 +529,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } -// Bans nested `impl Trait`, e.g. `impl Into`. +// Bans nested `impl Trait`, e.g., `impl Into`. // Nested `impl Trait` _is_ allowed in associated type position, // e.g `impl Iterator` struct NestedImplTraitVisitor<'a> { diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index 42ead92783d..a5d2edbc5d4 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -41,7 +41,6 @@ pub mod ast_validation; pub mod rvalue_promotion; pub mod hir_stats; pub mod loops; -mod mir_stats; __build_diagnostic_array! { librustc_passes, DIAGNOSTICS } diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs deleted file mode 100644 index fb37f03a1cc..00000000000 --- a/src/librustc_passes/mir_stats.rs +++ /dev/null @@ -1,256 +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. - -// The visitors in this module collect sizes and counts of the most important -// pieces of MIR. The resulting numbers are good approximations but not -// completely accurate (some things might be counted twice, others missed). - -use rustc::mir::{AggregateKind, AssertMessage, BasicBlock, BasicBlockData}; -use rustc::mir::{Constant, Location, Local, LocalDecl}; -use rustc::mir::{Place, PlaceElem, PlaceProjection}; -use rustc::mir::{Mir, Operand, ProjectionElem}; -use rustc::mir::{Rvalue, SourceInfo, Statement, StatementKind}; -use rustc::mir::{Terminator, TerminatorKind, SourceScope, SourceScopeData}; -use rustc::mir::interpret::EvalErrorKind; -use rustc::mir::visit as mir_visit; -use rustc::ty::{self, ClosureSubsts, TyCtxt}; -use rustc::util::nodemap::{FxHashMap}; - -struct NodeData { - count: usize, - size: usize, -} - -struct StatCollector<'a, 'tcx: 'a> { - _tcx: TyCtxt<'a, 'tcx, 'tcx>, - data: FxHashMap<&'static str, NodeData>, -} - -impl<'a, 'tcx> StatCollector<'a, 'tcx> { - - fn record_with_size(&mut self, label: &'static str, node_size: usize) { - let entry = self.data.entry(label).or_insert(NodeData { - count: 0, - size: 0, - }); - - entry.count += 1; - entry.size = node_size; - } - - fn record(&mut self, label: &'static str, node: &T) { - self.record_with_size(label, ::std::mem::size_of_val(node)); - } -} - -impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> { - fn visit_mir(&mut self, mir: &Mir<'tcx>) { - self.record("Mir", mir); - - // since the `super_mir` method does not traverse the MIR of - // promoted rvalues, (but we still want to gather statistics - // on the structures represented there) we manually traverse - // the promoted rvalues here. - for promoted_mir in &mir.promoted { - self.visit_mir(promoted_mir); - } - - self.super_mir(mir); - } - - fn visit_basic_block_data(&mut self, block: BasicBlock, data: &BasicBlockData<'tcx>) { - self.record("BasicBlockData", data); - self.super_basic_block_data(block, data); - } - - fn visit_source_scope_data(&mut self, scope_data: &SourceScopeData) { - self.record("SourceScopeData", scope_data); - self.super_source_scope_data(scope_data); - } - - fn visit_statement(&mut self, - block: BasicBlock, - statement: &Statement<'tcx>, - location: Location) { - self.record("Statement", statement); - self.record(match statement.kind { - StatementKind::Assign(..) => "StatementKind::Assign", - StatementKind::FakeRead(..) => "StatementKind::FakeRead", - StatementKind::Retag { .. } => "StatementKind::Retag", - StatementKind::EscapeToRaw { .. } => "StatementKind::EscapeToRaw", - StatementKind::SetDiscriminant { .. } => "StatementKind::SetDiscriminant", - StatementKind::StorageLive(..) => "StatementKind::StorageLive", - StatementKind::StorageDead(..) => "StatementKind::StorageDead", - StatementKind::InlineAsm { .. } => "StatementKind::InlineAsm", - StatementKind::AscribeUserType(..) => "StatementKind::AscribeUserType", - StatementKind::Nop => "StatementKind::Nop", - }, &statement.kind); - self.super_statement(block, statement, location); - } - - fn visit_terminator(&mut self, - block: BasicBlock, - terminator: &Terminator<'tcx>, - location: Location) { - self.record("Terminator", terminator); - self.super_terminator(block, terminator, location); - } - - fn visit_terminator_kind(&mut self, - block: BasicBlock, - kind: &TerminatorKind<'tcx>, - location: Location) { - self.record("TerminatorKind", kind); - self.record(match *kind { - TerminatorKind::Goto { .. } => "TerminatorKind::Goto", - TerminatorKind::SwitchInt { .. } => "TerminatorKind::SwitchInt", - TerminatorKind::Resume => "TerminatorKind::Resume", - TerminatorKind::Abort => "TerminatorKind::Abort", - TerminatorKind::Return => "TerminatorKind::Return", - TerminatorKind::Unreachable => "TerminatorKind::Unreachable", - TerminatorKind::Drop { .. } => "TerminatorKind::Drop", - TerminatorKind::DropAndReplace { .. } => "TerminatorKind::DropAndReplace", - TerminatorKind::Call { .. } => "TerminatorKind::Call", - TerminatorKind::Assert { .. } => "TerminatorKind::Assert", - TerminatorKind::GeneratorDrop => "TerminatorKind::GeneratorDrop", - TerminatorKind::Yield { .. } => "TerminatorKind::Yield", - TerminatorKind::FalseEdges { .. } => "TerminatorKind::FalseEdges", - TerminatorKind::FalseUnwind { .. } => "TerminatorKind::FalseUnwind", - }, kind); - self.super_terminator_kind(block, kind, location); - } - - fn visit_assert_message(&mut self, msg: &AssertMessage<'tcx>, location: Location) { - self.record("AssertMessage", msg); - self.record(match *msg { - EvalErrorKind::BoundsCheck { .. } => "AssertMessage::BoundsCheck", - EvalErrorKind::Overflow(..) => "AssertMessage::Overflow", - EvalErrorKind::OverflowNeg => "AssertMessage::OverflowNeg", - EvalErrorKind::DivisionByZero => "AssertMessage::DivisionByZero", - EvalErrorKind::RemainderByZero => "AssertMessage::RemainderByZero", - EvalErrorKind::GeneratorResumedAfterReturn => { - "AssertMessage::GeneratorResumedAfterReturn" - } - EvalErrorKind::GeneratorResumedAfterPanic => { - "AssertMessage::GeneratorResumedAfterPanic" - } - _ => bug!(), - }, msg); - self.super_assert_message(msg, location); - } - - fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { - self.record("Rvalue", rvalue); - let rvalue_kind = match *rvalue { - Rvalue::Use(..) => "Rvalue::Use", - Rvalue::Repeat(..) => "Rvalue::Repeat", - Rvalue::Ref(..) => "Rvalue::Ref", - Rvalue::Len(..) => "Rvalue::Len", - Rvalue::Cast(..) => "Rvalue::Cast", - Rvalue::BinaryOp(..) => "Rvalue::BinaryOp", - Rvalue::CheckedBinaryOp(..) => "Rvalue::CheckedBinaryOp", - Rvalue::UnaryOp(..) => "Rvalue::UnaryOp", - Rvalue::Discriminant(..) => "Rvalue::Discriminant", - Rvalue::NullaryOp(..) => "Rvalue::NullaryOp", - Rvalue::Aggregate(ref kind, ref _operands) => { - // AggregateKind is not distinguished by visit API, so - // record it. (`super_rvalue` handles `_operands`.) - self.record(match **kind { - AggregateKind::Array(_) => "AggregateKind::Array", - AggregateKind::Tuple => "AggregateKind::Tuple", - AggregateKind::Adt(..) => "AggregateKind::Adt", - AggregateKind::Closure(..) => "AggregateKind::Closure", - AggregateKind::Generator(..) => "AggregateKind::Generator", - }, kind); - - "Rvalue::Aggregate" - } - }; - self.record(rvalue_kind, rvalue); - self.super_rvalue(rvalue, location); - } - - fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) { - self.record("Operand", operand); - self.record(match *operand { - Operand::Copy(..) => "Operand::Copy", - Operand::Move(..) => "Operand::Move", - Operand::Constant(..) => "Operand::Constant", - }, operand); - self.super_operand(operand, location); - } - - fn visit_place(&mut self, - place: &Place<'tcx>, - context: mir_visit::PlaceContext<'tcx>, - location: Location) { - self.record("Place", place); - self.record(match *place { - Place::Local(..) => "Place::Local", - Place::Static(..) => "Place::Static", - Place::Promoted(..) => "Place::Promoted", - Place::Projection(..) => "Place::Projection", - }, place); - self.super_place(place, context, location); - } - - fn visit_projection(&mut self, - place: &PlaceProjection<'tcx>, - context: mir_visit::PlaceContext<'tcx>, - location: Location) { - self.record("PlaceProjection", place); - self.super_projection(place, context, location); - } - - fn visit_projection_elem(&mut self, - place: &PlaceElem<'tcx>, - location: Location) { - self.record("PlaceElem", place); - self.record(match *place { - ProjectionElem::Deref => "PlaceElem::Deref", - ProjectionElem::Subslice { .. } => "PlaceElem::Subslice", - ProjectionElem::Field(..) => "PlaceElem::Field", - ProjectionElem::Index(..) => "PlaceElem::Index", - ProjectionElem::ConstantIndex { .. } => "PlaceElem::ConstantIndex", - ProjectionElem::Downcast(..) => "PlaceElem::Downcast", - }, place); - self.super_projection_elem(place, location); - } - - fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) { - self.record("Constant", constant); - self.super_constant(constant, location); - } - - fn visit_source_info(&mut self, source_info: &SourceInfo) { - self.record("SourceInfo", source_info); - self.super_source_info(source_info); - } - - fn visit_closure_substs(&mut self, substs: &ClosureSubsts<'tcx>, _: Location) { - self.record("ClosureSubsts", substs); - self.super_closure_substs(substs); - } - - fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, _: Location) { - self.record("Const", constant); - self.super_const(constant); - } - - fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) { - self.record("LocalDecl", local_decl); - self.super_local_decl(local, local_decl); - } - - fn visit_source_scope(&mut self, scope: &SourceScope) { - self.record("VisiblityScope", scope); - self.super_source_scope(scope); - } -} diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index 099c6df32ad..bfe8b677a5e 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -50,8 +50,8 @@ pub fn provide(providers: &mut Providers) { } pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - for &body_id in &tcx.hir.krate().body_ids { - let def_id = tcx.hir.body_owner_def_id(body_id); + for &body_id in &tcx.hir().krate().body_ids { + let def_id = tcx.hir().body_owner_def_id(body_id); tcx.const_is_rvalue_promotable_to_static(def_id); } tcx.sess.abort_if_errors(); @@ -63,10 +63,10 @@ fn const_is_rvalue_promotable_to_static<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, { assert!(def_id.is_local()); - let node_id = tcx.hir.as_local_node_id(def_id) + let node_id = tcx.hir().as_local_node_id(def_id) .expect("rvalue_promotable_map invoked with non-local def-id"); - let body_id = tcx.hir.body_owned_by(node_id); - let body_hir_id = tcx.hir.node_to_hir_id(body_id.node_id); + let body_id = tcx.hir().body_owned_by(node_id); + let body_hir_id = tcx.hir().node_to_hir_id(body_id.node_id); tcx.rvalue_promotable_map(def_id).contains(&body_hir_id.local_id) } @@ -91,9 +91,9 @@ fn rvalue_promotable_map<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }; // `def_id` should be a `Body` owner - let node_id = tcx.hir.as_local_node_id(def_id) + let node_id = tcx.hir().as_local_node_id(def_id) .expect("rvalue_promotable_map invoked with non-local def-id"); - let body_id = tcx.hir.body_owned_by(node_id); + let body_id = tcx.hir().body_owned_by(node_id); let _ = visitor.check_nested_body(body_id); Lrc::new(visitor.result) @@ -189,8 +189,8 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> { impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> { fn check_nested_body(&mut self, body_id: hir::BodyId) -> Promotability { - let item_id = self.tcx.hir.body_owner(body_id); - let item_def_id = self.tcx.hir.local_def_id(item_id); + let item_id = self.tcx.hir().body_owner(body_id); + let item_def_id = self.tcx.hir().local_def_id(item_id); let outer_in_fn = self.in_fn; let outer_tables = self.tables; @@ -200,7 +200,7 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> { self.in_fn = false; self.in_static = false; - match self.tcx.hir.body_owner_kind(item_id) { + match self.tcx.hir().body_owner_kind(item_id) { hir::BodyOwnerKind::Fn => self.in_fn = true, hir::BodyOwnerKind::Static(_) => self.in_static = true, _ => {} @@ -211,7 +211,7 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> { self.param_env = self.tcx.param_env(item_def_id); self.identity_substs = Substs::identity_for_item(self.tcx, item_def_id); - let body = self.tcx.hir.body(body_id); + let body = self.tcx.hir().body(body_id); let tcx = self.tcx; let param_env = self.param_env; @@ -383,7 +383,7 @@ fn check_expr_kind<'a, 'tcx>( NotPromotable }; // Just in case the type is more specific than the definition, - // e.g. impl associated const with type parameters, check it. + // e.g., impl associated const with type parameters, check it. // Also, trait associated consts are relaxed by this. promotable | v.type_promotability(node_ty) } diff --git a/src/librustc_plugin/load.rs b/src/librustc_plugin/load.rs index bf59165a9c4..ad55672fb47 100644 --- a/src/librustc_plugin/load.rs +++ b/src/librustc_plugin/load.rs @@ -144,7 +144,7 @@ impl<'a> PluginLoader<'a> { // Intentionally leak the dynamic library. We can't ever unload it // since the library can make things that will live arbitrarily long - // (e.g. an @-box cycle or a thread). + // (e.g., an @-box cycle or a thread). mem::forget(lib); registrar diff --git a/src/librustc_plugin/registry.rs b/src/librustc_plugin/registry.rs index 6c10ac7ea5c..2fb28a8a66f 100644 --- a/src/librustc_plugin/registry.rs +++ b/src/librustc_plugin/registry.rs @@ -60,8 +60,6 @@ pub struct Registry<'a> { #[doc(hidden)] pub attributes: Vec<(String, AttributeType)>, - - whitelisted_custom_derives: Vec, } impl<'a> Registry<'a> { @@ -77,7 +75,6 @@ impl<'a> Registry<'a> { lint_groups: FxHashMap::default(), llvm_passes: vec![], attributes: vec![], - whitelisted_custom_derives: Vec::new(), } } @@ -130,19 +127,6 @@ impl<'a> Registry<'a> { })); } - /// This can be used in place of `register_syntax_extension` to register legacy custom derives - /// (i.e. attribute syntax extensions whose name begins with `derive_`). Legacy custom - /// derives defined by this function do not trigger deprecation warnings when used. - pub fn register_custom_derive(&mut self, name: ast::Name, extension: SyntaxExtension) { - assert!(name.as_str().starts_with("derive_")); - self.whitelisted_custom_derives.push(name); - self.register_syntax_extension(name, extension); - } - - pub fn take_whitelisted_custom_derives(&mut self) -> Vec { - ::std::mem::replace(&mut self.whitelisted_custom_derives, Vec::new()) - } - /// Register a macro of the usual kind. /// /// This is a convenience wrapper for `register_syntax_extension`. diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 6d9abbf5af2..86e3b231fc7 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -23,8 +23,7 @@ extern crate rustc_typeck; extern crate syntax_pos; extern crate rustc_data_structures; -use rustc::hir::{self, PatKind}; -use hir::Node; +use rustc::hir::{self, Node, PatKind}; use rustc::hir::def::Def; use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; @@ -36,14 +35,14 @@ use rustc::ty::fold::TypeVisitor; use rustc::ty::query::Providers; use rustc::ty::subst::UnpackedKind; use rustc::util::nodemap::NodeSet; +use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::sync::Lrc; use syntax::ast::{self, CRATE_NODE_ID, Ident}; use syntax::symbol::keywords; use syntax_pos::Span; use std::cmp; use std::mem::replace; -use rustc_data_structures::fx::FxHashSet; -use rustc_data_structures::sync::Lrc; mod diagnostics; @@ -60,7 +59,7 @@ struct PubRestrictedVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> Visitor<'tcx> for PubRestrictedVisitor<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::All(&self.tcx.hir) + NestedVisitorMap::All(&self.tcx.hir()) } fn visit_vis(&mut self, vis: &'tcx hir::Visibility) { self.has_pub_restricted = self.has_pub_restricted || vis.node.is_pub_restricted(); @@ -74,11 +73,11 @@ impl<'a, 'tcx> Visitor<'tcx> for PubRestrictedVisitor<'a, 'tcx> { struct EmbargoVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, - // Accessibility levels for reachable nodes + // Accessibility levels for reachable nodes. access_levels: AccessLevels, - // Previous accessibility level, None means unreachable + // Previous accessibility level; `None` means unreachable. prev_level: Option, - // Have something changed in the level map? + // Has something changed in the level map? changed: bool, } @@ -97,7 +96,7 @@ impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> { ty::Projection(ref proj) => proj.trait_ref(self.tcx).def_id, _ => return Some(AccessLevel::Public) }; - if let Some(node_id) = self.tcx.hir.as_local_node_id(ty_def_id) { + if let Some(node_id) = self.tcx.hir().as_local_node_id(ty_def_id) { self.get(node_id) } else { Some(AccessLevel::Public) @@ -106,7 +105,7 @@ impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> { fn impl_trait_level(&self, impl_def_id: DefId) -> Option { if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_def_id) { - if let Some(node_id) = self.tcx.hir.as_local_node_id(trait_ref.def_id) { + if let Some(node_id) = self.tcx.hir().as_local_node_id(trait_ref.def_id) { return self.get(node_id); } } @@ -117,10 +116,10 @@ impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> { self.access_levels.map.get(&id).cloned() } - // Updates node level and returns the updated level + // Updates node level and returns the updated level. fn update(&mut self, id: ast::NodeId, level: Option) -> Option { let old_level = self.get(id); - // Accessibility levels can only grow + // Accessibility levels can only grow. if level > old_level { self.access_levels.map.insert(id, level.unwrap()); self.changed = true; @@ -134,7 +133,7 @@ impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> { -> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { ReachEverythingInTheInterfaceVisitor { access_level: self.prev_level.map(|l| l.min(AccessLevel::Reachable)), - item_def_id: self.tcx.hir.local_def_id(item_id), + item_def_id: self.tcx.hir().local_def_id(item_id), ev: self, } } @@ -144,21 +143,21 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { /// We want to visit items in the context of their containing /// module and so forth, so supply a crate for doing a deep walk. fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::All(&self.tcx.hir) + NestedVisitorMap::All(&self.tcx.hir()) } fn visit_item(&mut self, item: &'tcx hir::Item) { let inherited_item_level = match item.node { - // Impls inherit level from their types and traits + // Impls inherit level from their types and traits. hir::ItemKind::Impl(..) => { - let def_id = self.tcx.hir.local_def_id(item.id); + let def_id = self.tcx.hir().local_def_id(item.id); cmp::min(self.item_ty_level(def_id), self.impl_trait_level(def_id)) } - // Foreign mods inherit level from parents + // Foreign modules inherit level from parents. hir::ItemKind::ForeignMod(..) => { self.prev_level } - // Other `pub` items inherit levels from parents + // Other `pub` items inherit levels from parents. hir::ItemKind::Const(..) | hir::ItemKind::Enum(..) | hir::ItemKind::ExternCrate(..) | hir::ItemKind::GlobalAsm(..) | hir::ItemKind::Fn(..) | hir::ItemKind::Mod(..) | hir::ItemKind::Static(..) | hir::ItemKind::Struct(..) | @@ -169,10 +168,10 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { } }; - // Update level of the item itself + // Update level of the item itself. let item_level = self.update(item.id, inherited_item_level); - // Update levels of nested things + // Update levels of nested things. match item.node { hir::ItemKind::Enum(ref def, _) => { for variant in &def.variants { @@ -220,7 +219,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { // It (and its children) are revisited if the change applies. hir::ItemKind::Existential(ref ty_data) => { if let Some(impl_trait_fn) = ty_data.impl_trait_fn { - if let Some(node_id) = self.tcx.hir.as_local_node_id(impl_trait_fn) { + if let Some(node_id) = self.tcx.hir().as_local_node_id(impl_trait_fn) { self.update(node_id, Some(AccessLevel::ReachableFromImplTrait)); } } @@ -240,23 +239,23 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { // reachability level through interfaces and children. let orig_level = replace(&mut self.prev_level, item_level); - // Mark all items in interfaces of reachable items as reachable + // Mark all items in interfaces of reachable items as reachable. match item.node { - // The interface is empty + // The interface is empty. hir::ItemKind::ExternCrate(..) => {} - // All nested items are checked by visit_item + // All nested items are checked by `visit_item`. hir::ItemKind::Mod(..) => {} - // Re-exports are handled in visit_mod + // Re-exports are handled in `visit_mod`. hir::ItemKind::Use(..) => {} - // The interface is empty + // The interface is empty. hir::ItemKind::GlobalAsm(..) => {} hir::ItemKind::Existential(hir::ExistTy { impl_trait_fn: Some(_), .. }) => { if item_level.is_some() { - // Reach the (potentially private) type and the API being exposed + // Reach the (potentially private) type and the API being exposed. self.reach(item.id).ty().predicates(); } } - // Visit everything + // Visit everything. hir::ItemKind::Const(..) | hir::ItemKind::Static(..) | hir::ItemKind::Existential(..) | hir::ItemKind::Fn(..) | hir::ItemKind::Ty(..) => { @@ -286,7 +285,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { self.reach(item.id).generics().predicates(); } } - // Visit everything except for private impl items + // Visit everything except for private impl items. hir::ItemKind::Impl(.., ref trait_ref, _, ref impl_item_refs) => { if item_level.is_some() { self.reach(item.id).generics().predicates().impl_trait_ref(); @@ -300,7 +299,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { } } - // Visit everything, but enum variants have their own levels + // Visit everything, but enum variants have their own levels. hir::ItemKind::Enum(ref def, _) => { if item_level.is_some() { self.reach(item.id).generics().predicates(); @@ -316,7 +315,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { } } } - // Visit everything, but foreign items have their own levels + // Visit everything, but foreign items have their own levels. hir::ItemKind::ForeignMod(ref foreign_mod) => { for foreign_item in &foreign_mod.items { if self.get(foreign_item.id).is_some() { @@ -324,7 +323,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { } } } - // Visit everything except for private fields + // Visit everything except for private fields. hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => { if item_level.is_some() { @@ -348,7 +347,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { // Blocks can have public items, for example impls, but they always // start as completely private regardless of publicity of a function, - // constant, type, field, etc. in which this block resides + // constant, type, field, etc., in which this block resides. intravisit::walk_block(self, b); self.prev_level = orig_level; @@ -358,12 +357,12 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { // This code is here instead of in visit_item so that the // crate module gets processed as well. if self.prev_level.is_some() { - let def_id = self.tcx.hir.local_def_id(id); + let def_id = self.tcx.hir().local_def_id(id); if let Some(exports) = self.tcx.module_exports(def_id) { for export in exports.iter() { if export.vis == ty::Visibility::Public { if let Some(def_id) = export.def.opt_def_id() { - if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) { + if let Some(node_id) = self.tcx.hir().as_local_node_id(def_id) { self.update(node_id, Some(AccessLevel::Exported)); } } @@ -381,8 +380,11 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { return } - let module_did = ty::DefIdTree::parent(self.tcx, self.tcx.hir.local_def_id(md.id)).unwrap(); - let mut module_id = self.tcx.hir.as_local_node_id(module_did).unwrap(); + let module_did = ty::DefIdTree::parent( + self.tcx, + self.tcx.hir().local_def_id(md.id) + ).unwrap(); + let mut module_id = self.tcx.hir().as_local_node_id(module_did).unwrap(); let level = if md.vis.node.is_pub() { self.get(module_id) } else { None }; let level = self.update(md.id, level); if level.is_none() { @@ -391,9 +393,9 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { loop { let module = if module_id == ast::CRATE_NODE_ID { - &self.tcx.hir.krate().module - } else if let hir::ItemKind::Mod(ref module) = self.tcx.hir.expect_item(module_id).node - { + &self.tcx.hir().krate().module + } else if let hir::ItemKind::Mod(ref module) = + self.tcx.hir().expect_item(module_id).node { module } else { unreachable!() @@ -401,10 +403,10 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { for id in &module.item_ids { self.update(id.id, level); } - let def_id = self.tcx.hir.local_def_id(module_id); + let def_id = self.tcx.hir().local_def_id(module_id); if let Some(exports) = self.tcx.module_exports(def_id) { for export in exports.iter() { - if let Some(node_id) = self.tcx.hir.as_local_node_id(export.def.def_id()) { + if let Some(node_id) = self.tcx.hir().as_local_node_id(export.def.def_id()) { self.update(node_id, level); } } @@ -413,7 +415,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { if module_id == ast::CRATE_NODE_ID { break } - module_id = self.tcx.hir.get_parent_node(module_id); + module_id = self.tcx.hir().get_parent_node(module_id); } } } @@ -473,8 +475,8 @@ impl<'b, 'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { } fn check_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) { - if let Some(node_id) = self.ev.tcx.hir.as_local_node_id(trait_ref.def_id) { - let item = self.ev.tcx.hir.expect_item(node_id); + if let Some(node_id) = self.ev.tcx.hir().as_local_node_id(trait_ref.def_id) { + let item = self.ev.tcx.hir().expect_item(node_id); self.ev.update(item.id, self.access_level); } } @@ -495,7 +497,7 @@ impl<'b, 'a, 'tcx> TypeVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'b }; if let Some(def_id) = ty_def_id { - if let Some(node_id) = self.ev.tcx.hir.as_local_node_id(def_id) { + if let Some(node_id) = self.ev.tcx.hir().as_local_node_id(def_id) { self.ev.update(node_id, self.access_level); } } @@ -521,10 +523,10 @@ struct NamePrivacyVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> NamePrivacyVisitor<'a, 'tcx> { // Checks that a field in a struct constructor (expression or pattern) is accessible. fn check_field(&mut self, - use_ctxt: Span, // Syntax context of the field name at the use site - span: Span, // Span of the field pattern, e.g. `x: 0` - def: &'tcx ty::AdtDef, // Definition of the struct or enum - field: &'tcx ty::FieldDef) { // Definition of the field + use_ctxt: Span, // syntax context of the field name at the use site + span: Span, // span of the field pattern, e.g., `x: 0` + def: &'tcx ty::AdtDef, // definition of the struct or enum + field: &'tcx ty::FieldDef) { // definition of the field let ident = Ident::new(keywords::Invalid.name(), use_ctxt); let def_id = self.tcx.adjust_ident(ident, def.did, self.current_item).1; if !def.is_enum() && !field.vis.is_accessible_from(def_id, self.tcx) { @@ -536,14 +538,14 @@ impl<'a, 'tcx> NamePrivacyVisitor<'a, 'tcx> { } } -// Set the correct TypeckTables for the given `item_id` (or an empty table if -// there is no TypeckTables for the item). +// Set the correct `TypeckTables` for the given `item_id` (or an empty table if +// there is no `TypeckTables` for the item). fn update_tables<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId, tables: &mut &'a ty::TypeckTables<'tcx>, empty_tables: &'a ty::TypeckTables<'tcx>) -> &'a ty::TypeckTables<'tcx> { - let def_id = tcx.hir.local_def_id(item_id); + let def_id = tcx.hir().local_def_id(item_id); if tcx.has_typeck_tables(def_id) { replace(tables, tcx.typeck_tables_of(def_id)) @@ -556,12 +558,12 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> { /// We want to visit items in the context of their containing /// module and so forth, so supply a crate for doing a deep walk. fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::All(&self.tcx.hir) + NestedVisitorMap::All(&self.tcx.hir()) } fn visit_nested_body(&mut self, body: hir::BodyId) { let orig_tables = replace(&mut self.tables, self.tcx.body_tables(body)); - let body = self.tcx.hir.body(body); + let body = self.tcx.hir().body(body); self.visit_body(body); self.tables = orig_tables; } @@ -657,19 +659,19 @@ struct TypePrivacyVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> { fn def_id_visibility(&self, did: DefId) -> ty::Visibility { - match self.tcx.hir.as_local_node_id(did) { + match self.tcx.hir().as_local_node_id(did) { Some(node_id) => { - let vis = match self.tcx.hir.get(node_id) { + let vis = match self.tcx.hir().get(node_id) { Node::Item(item) => &item.vis, Node::ForeignItem(foreign_item) => &foreign_item.vis, Node::ImplItem(impl_item) => &impl_item.vis, Node::TraitItem(..) | Node::Variant(..) => { - return self.def_id_visibility(self.tcx.hir.get_parent_did(node_id)); + return self.def_id_visibility(self.tcx.hir().get_parent_did(node_id)); } Node::StructCtor(vdata) => { - let struct_node_id = self.tcx.hir.get_parent(node_id); - let struct_vis = match self.tcx.hir.get(struct_node_id) { + let struct_node_id = self.tcx.hir().get_parent(node_id); + let struct_vis = match self.tcx.hir().get(struct_node_id) { Node::Item(item) => &item.vis, node => bug!("unexpected node kind: {:?}", node), }; @@ -684,7 +686,7 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> { // If the structure is marked as non_exhaustive then lower the // visibility to within the crate. - let struct_def_id = self.tcx.hir.get_parent_did(node_id); + let struct_def_id = self.tcx.hir().get_parent_did(node_id); let adt_def = self.tcx.adt_def(struct_def_id); if adt_def.non_enum_variant().is_field_list_non_exhaustive() && ctor_vis == ty::Visibility::Public @@ -707,7 +709,7 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> { self.def_id_visibility(did).is_accessible_from(self.current_item, self.tcx) } - // Take node ID of an expression or pattern and check its type for privacy. + // Take node-id of an expression or pattern and check its type for privacy. fn check_expr_pat_type(&mut self, id: hir::HirId, span: Span) -> bool { self.span = span; if self.tables.node_id_to_type(id).visit_with(self) { @@ -741,13 +743,13 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { /// We want to visit items in the context of their containing /// module and so forth, so supply a crate for doing a deep walk. fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::All(&self.tcx.hir) + NestedVisitorMap::All(&self.tcx.hir()) } fn visit_nested_body(&mut self, body: hir::BodyId) { let orig_tables = replace(&mut self.tables, self.tcx.body_tables(body)); let orig_in_body = replace(&mut self.in_body, true); - let body = self.tcx.hir.body(body); + let body = self.tcx.hir().body(body); self.visit_body(body); self.tables = orig_tables; self.in_body = orig_in_body; @@ -859,7 +861,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { intravisit::walk_qpath(self, qpath, id, span); } - // Check types of patterns + // Check types of patterns. fn visit_pat(&mut self, pattern: &'tcx hir::Pat) { if self.check_expr_pat_type(pattern.hir_id, pattern.span) { // Do not check nested patterns if the error already happened. @@ -880,7 +882,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { intravisit::walk_local(self, local); } - // Check types in item interfaces + // Check types in item interfaces. fn visit_item(&mut self, item: &'tcx hir::Item) { let orig_current_item = self.current_item; let orig_tables = update_tables(self.tcx, @@ -888,7 +890,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { &mut self.tables, self.empty_tables); let orig_in_body = replace(&mut self.in_body, false); - self.current_item = self.tcx.hir.local_def_id(item.id); + self.current_item = self.tcx.hir().local_def_id(item.id); intravisit::walk_item(self, item); self.tables = orig_tables; self.in_body = orig_in_body; @@ -1012,18 +1014,18 @@ struct ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, access_levels: &'a AccessLevels, in_variant: bool, - // set of errors produced by this obsolete visitor + // Set of errors produced by this obsolete visitor. old_error_set: NodeSet, } struct ObsoleteCheckTypeForPrivatenessVisitor<'a, 'b: 'a, 'tcx: 'b> { inner: &'a ObsoleteVisiblePrivateTypesVisitor<'b, 'tcx>, - /// whether the type refers to private types. + /// Whether the type refers to private types. contains_private: bool, - /// whether we've recurred at all (i.e. if we're pointing at the - /// first type on which visit_ty was called). + /// Whether we've recurred at all (i.e., if we're pointing at the + /// first type on which `visit_ty` was called). at_outer_type: bool, - // whether that first type is a public path. + /// Whether that first type is a public path. outer_type_is_public_path: bool, } @@ -1036,10 +1038,10 @@ impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { // A path can only be private if: // it's in this crate... - if let Some(node_id) = self.tcx.hir.as_local_node_id(did) { + if let Some(node_id) = self.tcx.hir().as_local_node_id(did) { // .. and it corresponds to a private type in the AST (this returns - // None for type parameters) - match self.tcx.hir.find(node_id) { + // `None` for type parameters). + match self.tcx.hir().find(node_id) { Some(Node::Item(ref item)) => !item.vis.node.is_pub(), Some(_) | None => false, } @@ -1050,7 +1052,7 @@ impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { fn trait_is_public(&self, trait_id: ast::NodeId) -> bool { // FIXME: this would preferably be using `exported_items`, but all - // traits are exported currently (see `EmbargoVisitor.exported_trait`) + // traits are exported currently (see `EmbargoVisitor.exported_trait`). self.access_levels.is_public(trait_id) } @@ -1076,8 +1078,7 @@ impl<'a, 'b, 'tcx, 'v> Visitor<'v> for ObsoleteCheckTypeForPrivatenessVisitor<'a if let hir::TyKind::Path(hir::QPath::Resolved(_, ref path)) = ty.node { if self.inner.path_is_private_type(path) { self.contains_private = true; - // found what we're looking for so let's stop - // working. + // Found what we're looking for, so let's stop working. return } } @@ -1090,7 +1091,7 @@ impl<'a, 'b, 'tcx, 'v> Visitor<'v> for ObsoleteCheckTypeForPrivatenessVisitor<'a intravisit::walk_ty(self, ty) } - // don't want to recurse into [, .. expr] + // Don't want to recurse into `[, .. expr]`. fn visit_expr(&mut self, _: &hir::Expr) {} } @@ -1098,12 +1099,12 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { /// We want to visit items in the context of their containing /// module and so forth, so supply a crate for doing a deep walk. fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::All(&self.tcx.hir) + NestedVisitorMap::All(&self.tcx.hir()) } fn visit_item(&mut self, item: &'tcx hir::Item) { match item.node { - // contents of a private mod can be re-exported, so we need + // Contents of a private mod can be re-exported, so we need // to check internals. hir::ItemKind::Mod(_) => {} @@ -1121,19 +1122,19 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { } } - // impls need some special handling to try to offer useful + // Impls need some special handling to try to offer useful // error messages without (too many) false positives - // (i.e. we could just return here to not check them at + // (i.e., we could just return here to not check them at // all, or some worse estimation of whether an impl is // publicly visible). hir::ItemKind::Impl(.., ref g, ref trait_ref, ref self_, ref impl_item_refs) => { // `impl [... for] Private` is never visible. let self_contains_private; - // impl [... for] Public<...>, but not `impl [... for] - // Vec` or `(Public,)` etc. + // `impl [... for] Public<...>`, but not `impl [... for] + // Vec` or `(Public,)`, etc. let self_is_public_path; - // check the properties of the Self type: + // Check the properties of the `Self` type: { let mut visitor = ObsoleteCheckTypeForPrivatenessVisitor { inner: self, @@ -1146,7 +1147,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { self_is_public_path = visitor.outer_type_is_public_path; } - // miscellaneous info about the impl + // Miscellaneous info about the impl: // `true` iff this is `impl Private for ...`. let not_private_trait = @@ -1154,7 +1155,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { |tr| { let did = tr.path.def.def_id(); - if let Some(node_id) = self.tcx.hir.as_local_node_id(did) { + if let Some(node_id) = self.tcx.hir().as_local_node_id(did) { self.trait_is_public(node_id) } else { true // external traits must be public @@ -1173,7 +1174,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { trait_ref.is_some() || impl_item_refs.iter() .any(|impl_item_ref| { - let impl_item = self.tcx.hir.impl_item(impl_item_ref.id); + let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); match impl_item.node { hir::ImplItemKind::Const(..) | hir::ImplItemKind::Method(..) => { @@ -1198,7 +1199,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { // should only walk into public items so that we // don't erroneously report errors for private // types in private items. - let impl_item = self.tcx.hir.impl_item(impl_item_ref.id); + let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); match impl_item.node { hir::ImplItemKind::Const(..) | hir::ImplItemKind::Method(..) @@ -1231,7 +1232,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { // Those in 3. are warned with this call. for impl_item_ref in impl_item_refs { - let impl_item = self.tcx.hir.impl_item(impl_item_ref.id); + let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); if let hir::ImplItemKind::Type(ref ty) = impl_item.node { self.visit_ty(ty); } @@ -1239,12 +1240,12 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { } } } else if trait_ref.is_none() && self_is_public_path { - // impl Public { ... }. Any public static + // `impl Public { ... }`. Any public static // methods will be visible as `Public::foo`. let mut found_pub_static = false; for impl_item_ref in impl_item_refs { if self.item_is_public(&impl_item_ref.id.node_id, &impl_item_ref.vis) { - let impl_item = self.tcx.hir.impl_item(impl_item_ref.id); + let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); match impl_item_ref.kind { hir::AssociatedItemKind::Const => { found_pub_static = true; @@ -1269,7 +1270,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { // we're introducing a new name. hir::ItemKind::Ty(..) => return, - // not at all public, so we don't care + // Not at all public, so we don't care. _ if !self.item_is_public(&item.id, &item.vis) => { return; } @@ -1279,7 +1280,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { // We've carefully constructed it so that if we're here, then // any `visit_ty`'s will be called on things that are in - // public signatures, i.e. things that we're interested in for + // public signatures, i.e., things that we're interested in for // this visitor. intravisit::walk_item(self, item); } @@ -1337,7 +1338,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { } } - // we don't need to introspect into these at all: an + // We don't need to introspect into these at all: an // expression/block context can't possibly contain exported things. // (Making them no-ops stops us from traversing the whole AST without // having to be super careful about our `walk_...` calls above.) @@ -1356,9 +1357,9 @@ struct SearchInterfaceForPrivateItemsVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId, span: Span, - /// The visitor checks that each component type is at least this visible + /// The visitor checks that each component type is at least this visible. required_visibility: ty::Visibility, - /// The visibility of the least visible component that has been visited + /// The visibility of the least visible component that has been visited. min_visibility: ty::Visibility, has_pub_restricted: bool, has_old_errors: bool, @@ -1381,7 +1382,7 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> { } fn predicates(&mut self) -> &mut Self { - // NB: We use `explicit_predicates_of` and not `predicates_of` + // N.B., we use `explicit_predicates_of` and not `predicates_of` // because we don't want to report privacy errors due to where // clauses that the compiler inferred. We only want to // consider the ones that the user wrote. This is important @@ -1426,9 +1427,9 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> { } fn check_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) { - // Non-local means public (private items can't leave their crate, modulo bugs) - if let Some(node_id) = self.tcx.hir.as_local_node_id(trait_ref.def_id) { - let item = self.tcx.hir.expect_item(node_id); + // Non-local means public (private items can't leave their crate, modulo bugs). + if let Some(node_id) = self.tcx.hir().as_local_node_id(trait_ref.def_id) { + let item = self.tcx.hir().expect_item(node_id); let vis = ty::Visibility::from_hir(&item.vis, node_id, self.tcx); if !vis.is_at_least(self.min_visibility, self.tcx) { self.min_visibility = vis; @@ -1475,9 +1476,9 @@ impl<'a, 'tcx: 'a> TypeVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<' }; if let Some(def_id) = ty_def_id { - // Non-local means public (private items can't leave their crate, modulo bugs) - if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) { - let hir_vis = match self.tcx.hir.find(node_id) { + // Non-local means public (private items can't leave their crate, modulo bugs). + if let Some(node_id) = self.tcx.hir().as_local_node_id(def_id) { + let hir_vis = match self.tcx.hir().find(node_id) { Some(Node::Item(item)) => &item.vis, Some(Node::ForeignItem(item)) => &item.vis, _ => bug!("expected item of foreign item"), @@ -1537,7 +1538,7 @@ impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> { has_old_errors = true; break; } - let parent = self.tcx.hir.get_parent_node(id); + let parent = self.tcx.hir().get_parent_node(id); if parent == id { break; } @@ -1551,8 +1552,8 @@ impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> { SearchInterfaceForPrivateItemsVisitor { tcx: self.tcx, - item_def_id: self.tcx.hir.local_def_id(item_id), - span: self.tcx.hir.span(item_id), + item_def_id: self.tcx.hir().local_def_id(item_id), + span: self.tcx.hir().span(item_id), min_visibility: ty::Visibility::Public, required_visibility, has_pub_restricted: self.has_pub_restricted, @@ -1564,7 +1565,7 @@ impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir) + NestedVisitorMap::OnlyBodies(&self.tcx.hir()) } fn visit_item(&mut self, item: &'tcx hir::Item) { @@ -1576,30 +1577,29 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> let item_visibility = ty::Visibility::from_hir(&item.vis, item.id, tcx); match item.node { - // Crates are always public + // Crates are always public. hir::ItemKind::ExternCrate(..) => {} - // All nested items are checked by visit_item + // All nested items are checked by `visit_item`. hir::ItemKind::Mod(..) => {} - // Checked in resolve + // Checked in resolve. hir::ItemKind::Use(..) => {} - // No subitems + // No subitems. hir::ItemKind::GlobalAsm(..) => {} hir::ItemKind::Existential(hir::ExistTy { impl_trait_fn: Some(_), .. }) => { // Check the traits being exposed, as they're separate, - // e.g. `impl Iterator` has two predicates, + // e.g., `impl Iterator` has two predicates, // `X: Iterator` and `::Item == T`, // where `X` is the `impl Iterator` itself, // stored in `predicates_of`, not in the `Ty` itself. - self.check(item.id, item_visibility).predicates(); } - // Subitems of these items have inherited publicity + // Subitems of these items have inherited publicity. hir::ItemKind::Const(..) | hir::ItemKind::Static(..) | hir::ItemKind::Fn(..) | hir::ItemKind::Existential(..) | hir::ItemKind::Ty(..) => { self.check(item.id, item_visibility).generics().predicates().ty(); - // Recurse for e.g. `impl Trait` (see `visit_ty`). + // Recurse for e.g., `impl Trait` (see `visit_ty`). self.inner_visibility = item_visibility; intravisit::walk_item(self, item); } @@ -1631,14 +1631,14 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> } } } - // Subitems of foreign modules have their own publicity + // Subitems of foreign modules have their own publicity. hir::ItemKind::ForeignMod(ref foreign_mod) => { for foreign_item in &foreign_mod.items { let vis = ty::Visibility::from_hir(&foreign_item.vis, item.id, tcx); self.check(foreign_item.id, vis).generics().predicates().ty(); } } - // Subitems of structs and unions have their own publicity + // Subitems of structs and unions have their own publicity. hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => { self.check(item.id, item_visibility).generics().predicates(); @@ -1649,37 +1649,37 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> } } // An inherent impl is public when its type is public - // Subitems of inherent impls have their own publicity + // Subitems of inherent impls have their own publicity. hir::ItemKind::Impl(.., None, _, ref impl_item_refs) => { let ty_vis = self.check(item.id, ty::Visibility::Invisible).ty().min_visibility; self.check(item.id, ty_vis).generics().predicates(); for impl_item_ref in impl_item_refs { - let impl_item = self.tcx.hir.impl_item(impl_item_ref.id); + let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); let impl_item_vis = ty::Visibility::from_hir(&impl_item.vis, item.id, tcx); let mut check = self.check(impl_item.id, min(impl_item_vis, ty_vis)); check.in_assoc_ty = impl_item_ref.kind == hir::AssociatedItemKind::Type; check.generics().predicates().ty(); - // Recurse for e.g. `impl Trait` (see `visit_ty`). + // Recurse for e.g., `impl Trait` (see `visit_ty`). self.inner_visibility = impl_item_vis; intravisit::walk_impl_item(self, impl_item); } } // A trait impl is public when both its type and its trait are public - // Subitems of trait impls have inherited publicity + // Subitems of trait impls have inherited publicity. hir::ItemKind::Impl(.., Some(_), _, ref impl_item_refs) => { let vis = self.check(item.id, ty::Visibility::Invisible) .ty().impl_trait_ref().min_visibility; self.check(item.id, vis).generics().predicates(); for impl_item_ref in impl_item_refs { - let impl_item = self.tcx.hir.impl_item(impl_item_ref.id); + let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); let mut check = self.check(impl_item.id, vis); check.in_assoc_ty = impl_item_ref.kind == hir::AssociatedItemKind::Type; check.generics().predicates().ty(); - // Recurse for e.g. `impl Trait` (see `visit_ty`). + // Recurse for e.g., `impl Trait` (see `visit_ty`). self.inner_visibility = vis; intravisit::walk_impl_item(self, impl_item); } @@ -1688,12 +1688,12 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> } fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem) { - // handled in `visit_item` above + // Handled in `visit_item` above. } - // Don't recurse into expressions in array sizes or const initializers + // Don't recurse into expressions in array sizes or const initializers. fn visit_expr(&mut self, _: &'tcx hir::Expr) {} - // Don't recurse into patterns in function arguments + // Don't recurse into patterns in function arguments. fn visit_pat(&mut self, _: &'tcx hir::Pat) {} } @@ -1713,7 +1713,7 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, -> Lrc { assert_eq!(krate, LOCAL_CRATE); - let krate = tcx.hir.krate(); + let krate = tcx.hir().krate(); let empty_tables = ty::TypeckTables::empty(None); // Check privacy of names not checked in previous compilation stages. @@ -1775,7 +1775,7 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pub_restricted_visitor.has_pub_restricted }; - // Check for private types and traits in public interfaces + // Check for private types and traits in public interfaces. let mut visitor = PrivateItemsInPublicInterfacesVisitor { tcx, has_pub_restricted, diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 0fa41cb484f..6cfa9f95082 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -83,7 +83,7 @@ impl<'a> ToNameBinding<'a> for (Def, ty::Visibility, Span, Mark, IsMacroExport) } } -impl<'a, 'cl> Resolver<'a, 'cl> { +impl<'a> Resolver<'a> { /// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined; /// otherwise, reports an error. pub fn define(&mut self, parent: Module<'a>, ident: Ident, ns: Namespace, def: T) @@ -145,7 +145,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { } _ => None, }.map(|ctxt| Segment::from_ident(Ident::new( - keywords::CrateRoot.name(), use_tree.prefix.span.shrink_to_lo().with_ctxt(ctxt) + keywords::PathRoot.name(), use_tree.prefix.span.shrink_to_lo().with_ctxt(ctxt) ))); let prefix = crate_root.into_iter().chain(prefix_iter).collect::>(); @@ -153,18 +153,18 @@ impl<'a, 'cl> Resolver<'a, 'cl> { let empty_for_self = |prefix: &[Segment]| { prefix.is_empty() || - prefix.len() == 1 && prefix[0].ident.name == keywords::CrateRoot.name() + prefix.len() == 1 && prefix[0].ident.name == keywords::PathRoot.name() }; match use_tree.kind { ast::UseTreeKind::Simple(rename, ..) => { - let mut ident = use_tree.ident(); + let mut ident = use_tree.ident().gensym_if_underscore(); let mut module_path = prefix; let mut source = module_path.pop().unwrap(); let mut type_ns_only = false; if nested { // Correctly handle `self` - if source.ident.name == keywords::SelfValue.name() { + if source.ident.name == keywords::SelfLower.name() { type_ns_only = true; if empty_for_self(&module_path) { @@ -185,7 +185,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { } } else { // Disallow `self` - if source.ident.name == keywords::SelfValue.name() { + if source.ident.name == keywords::SelfLower.name() { resolve_error(self, use_tree.span, ResolutionError::SelfImportsOnlyAllowedWithin); @@ -205,7 +205,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // `crate_name` should not be interpreted as relative. module_path.push(Segment { ident: Ident { - name: keywords::CrateRoot.name(), + name: keywords::PathRoot.name(), span: source.ident.span, }, id: Some(self.session.next_node_id()), @@ -230,13 +230,18 @@ impl<'a, 'cl> Resolver<'a, 'cl> { } let subclass = SingleImport { - target: ident, source: source.ident, - result: PerNS { + target: ident, + source_bindings: PerNS { type_ns: Cell::new(Err(Undetermined)), value_ns: Cell::new(Err(Undetermined)), macro_ns: Cell::new(Err(Undetermined)), }, + target_bindings: PerNS { + type_ns: Cell::new(None), + value_ns: Cell::new(None), + macro_ns: Cell::new(None), + }, type_ns_only, }; self.add_import_directive( @@ -270,7 +275,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // Ensure there is at most one `self` in the list let self_spans = items.iter().filter_map(|&(ref use_tree, _)| { if let ast::UseTreeKind::Simple(..) = use_tree.kind { - if use_tree.ident().name == keywords::SelfValue.name() { + if use_tree.ident().name == keywords::SelfLower.name() { return Some(use_tree.span); } } @@ -305,7 +310,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { let new_span = prefix[prefix.len() - 1].ident.span; let tree = ast::UseTree { prefix: ast::Path::from_ident( - Ident::new(keywords::SelfValue.name(), new_span) + Ident::new(keywords::SelfLower.name(), new_span) ), kind: ast::UseTreeKind::Simple( Some(Ident::new(keywords::Underscore.name().gensymed(), new_span)), @@ -318,7 +323,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // This particular use tree &tree, id, &prefix, true, // The whole `use` item - parent_scope.clone(), item, ty::Visibility::Invisible, root_span, + parent_scope, item, ty::Visibility::Invisible, root_span, ); } } @@ -329,7 +334,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { fn build_reduced_graph_for_item(&mut self, item: &Item, parent_scope: ParentScope<'a>) { let parent = parent_scope.module; let expansion = parent_scope.expansion; - let ident = item.ident; + let ident = item.ident.gensym_if_underscore(); let sp = item.span; let vis = self.resolve_visibility(&item.vis); @@ -344,13 +349,13 @@ impl<'a, 'cl> Resolver<'a, 'cl> { } ItemKind::ExternCrate(orig_name) => { - let module = if orig_name.is_none() && ident.name == keywords::SelfValue.name() { + let module = if orig_name.is_none() && ident.name == keywords::SelfLower.name() { self.session .struct_span_err(item.span, "`extern crate self;` requires renaming") .span_suggestion(item.span, "try", "extern crate self as name;".into()) .emit(); return; - } else if orig_name == Some(keywords::SelfValue.name()) { + } else if orig_name == Some(keywords::SelfLower.name()) { if !self.session.features_untracked().extern_crate_self { emit_feature_err(&self.session.parse_sess, "extern_crate_self", item.span, GateIssue::Language, "`extern crate self` is unstable"); @@ -623,7 +628,11 @@ impl<'a, 'cl> Resolver<'a, 'cl> { /// Builds the reduced graph for a single item in an external crate. fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'a>, child: Export) { - let Export { ident, def, vis, span, .. } = child; + let Export { ident, def, vis, span } = child; + // FIXME: We shouldn't create the gensym here, it should come from metadata, + // but metadata cannot encode gensyms currently, so we create it here. + // This is only a guess, two equivalent idents may incorrectly get different gensyms here. + let ident = ident.gensym_if_underscore(); let def_id = def.def_id(); let expansion = Mark::root(); // FIXME(jseyfried) intercrate hygiene match def { @@ -783,7 +792,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { "an `extern crate` loading macros must be at the crate root"); } if let ItemKind::ExternCrate(Some(orig_name)) = item.node { - if orig_name == keywords::SelfValue.name() { + if orig_name == keywords::SelfLower.name() { self.session.span_err(attr.span, "`macro_use` is not supported on `extern crate self`"); } @@ -879,13 +888,13 @@ impl<'a, 'cl> Resolver<'a, 'cl> { } } -pub struct BuildReducedGraphVisitor<'a, 'b: 'a, 'c: 'b> { - pub resolver: &'a mut Resolver<'b, 'c>, +pub struct BuildReducedGraphVisitor<'a, 'b: 'a> { + pub resolver: &'a mut Resolver<'b>, pub current_legacy_scope: LegacyScope<'b>, pub expansion: Mark, } -impl<'a, 'b, 'cl> BuildReducedGraphVisitor<'a, 'b, 'cl> { +impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { fn visit_invoc(&mut self, id: ast::NodeId) -> &'b InvocationData<'b> { let mark = id.placeholder_to_mark(); self.resolver.current_module.unresolved_invocations.borrow_mut().insert(mark); @@ -908,7 +917,7 @@ macro_rules! method { } } -impl<'a, 'b, 'cl> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b, 'cl> { +impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> { method!(visit_impl_item: ast::ImplItem, ast::ImplItemKind::Macro, walk_impl_item); method!(visit_expr: ast::Expr, ast::ExprKind::Mac, walk_expr); method!(visit_pat: ast::Pat, ast::PatKind::Mac, walk_pat); @@ -1026,4 +1035,15 @@ impl<'a, 'b, 'cl> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b, 'cl> { } visit::walk_attribute(self, attr); } + + fn visit_ident(&mut self, ident: Ident) { + if ident.name == keywords::DollarCrate.name() { + let name = match self.resolver.resolve_crate_root(ident).kind { + ModuleKind::Def(_, name) if name != keywords::Invalid.name() => name, + _ => keywords::Crate.name(), + }; + ident.span.ctxt().set_dollar_crate_name(name); + } + visit::walk_ident(self, ident); + } } diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index 659ca1f5b9f..5d231d845cf 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -31,8 +31,8 @@ use syntax::visit::{self, Visitor}; use syntax_pos::{Span, MultiSpan, DUMMY_SP}; -struct UnusedImportCheckVisitor<'a, 'b: 'a, 'd: 'b> { - resolver: &'a mut Resolver<'b, 'd>, +struct UnusedImportCheckVisitor<'a, 'b: 'a> { + resolver: &'a mut Resolver<'b>, /// All the (so far) unused imports, grouped path list unused_imports: NodeMap>, base_id: ast::NodeId, @@ -40,21 +40,21 @@ struct UnusedImportCheckVisitor<'a, 'b: 'a, 'd: 'b> { } // Deref and DerefMut impls allow treating UnusedImportCheckVisitor as Resolver. -impl<'a, 'b, 'd> Deref for UnusedImportCheckVisitor<'a, 'b, 'd> { - type Target = Resolver<'b, 'd>; +impl<'a, 'b> Deref for UnusedImportCheckVisitor<'a, 'b> { + type Target = Resolver<'b>; - fn deref<'c>(&'c self) -> &'c Resolver<'b, 'd> { + fn deref<'c>(&'c self) -> &'c Resolver<'b> { &*self.resolver } } -impl<'a, 'b, 'd> DerefMut for UnusedImportCheckVisitor<'a, 'b, 'd> { - fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b, 'd> { +impl<'a, 'b> DerefMut for UnusedImportCheckVisitor<'a, 'b> { + fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b> { &mut *self.resolver } } -impl<'a, 'b, 'd> UnusedImportCheckVisitor<'a, 'b, 'd> { +impl<'a, 'b> UnusedImportCheckVisitor<'a, 'b> { // We have information about whether `use` (import) directives are actually // used now. If an import is not used at all, we signal a lint error. fn check_import(&mut self, item_id: ast::NodeId, id: ast::NodeId, span: Span) { @@ -77,7 +77,7 @@ impl<'a, 'b, 'd> UnusedImportCheckVisitor<'a, 'b, 'd> { } } -impl<'a, 'b, 'cl> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b, 'cl> { +impl<'a, 'b> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b> { fn visit_item(&mut self, item: &'a ast::Item) { self.item_span = item.span; diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 2681295cf9b..77302390714 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -295,9 +295,8 @@ that has been imported into the current module. Erroneous code example: ```compile_fail,E0259 -# #![feature(libc)] extern crate core; -extern crate libc as core; +extern crate std as core; fn main() {} ``` @@ -308,9 +307,8 @@ external crate imported into the current module. Correct example: ``` -# #![feature(libc)] extern crate core; -extern crate libc as other_name; +extern crate std as other_name; fn main() {} ``` diff --git a/src/librustc_resolve/error_reporting.rs b/src/librustc_resolve/error_reporting.rs index e2a6303f579..5ff012662f9 100644 --- a/src/librustc_resolve/error_reporting.rs +++ b/src/librustc_resolve/error_reporting.rs @@ -17,7 +17,7 @@ use syntax_pos::Span; use resolve_imports::ImportResolver; use std::cmp::Reverse; -impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { +impl<'a, 'b:'a> ImportResolver<'a, 'b> { /// Add suggestions for a path that cannot be resolved. pub(crate) fn make_path_suggestion( &mut self, @@ -30,7 +30,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { match (path.get(0), path.get(1)) { // `{{root}}::ident::...` on both editions. // On 2015 `{{root}}` is usually added implicitly. - (Some(fst), Some(snd)) if fst.ident.name == keywords::CrateRoot.name() && + (Some(fst), Some(snd)) if fst.ident.name == keywords::PathRoot.name() && !snd.ident.is_path_segment_keyword() => {} // `ident::...` on 2018 (Some(fst), _) if fst.ident.span.rust_2018() && @@ -61,7 +61,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { parent_scope: &ParentScope<'b>, ) -> Option<(Vec, Option)> { // Replace first ident with `self` and check if that is valid. - path[0].ident.name = keywords::SelfValue.name(); + path[0].ident.name = keywords::SelfLower.name(); let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No); debug!("make_missing_self_suggestion: path={:?} result={:?}", path, result); if let PathResult::Module(..) = result { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index fdac1e3b816..794e5741d62 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -84,7 +84,7 @@ use rustc_data_structures::sync::Lrc; use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver}; use macros::{InvocationData, LegacyBinding, ParentScope}; -// NB: This module needs to be declared first so diagnostics are +// N.B., this module needs to be declared first so diagnostics are // registered before they are used. mod diagnostics; mod error_reporting; @@ -638,7 +638,7 @@ impl<'a> PathSource<'a> { // A minimal representation of a path segment. We use this in resolve because // we synthesize 'path segments' which don't have the rest of an AST or HIR -// PathSegment. +// `PathSegment`. #[derive(Clone, Copy, Debug)] pub struct Segment { ident: Ident, @@ -742,7 +742,7 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder { } /// This thing walks the whole crate in DFS manner, visiting each item, resolving names as it goes. -impl<'a, 'tcx, 'cl> Visitor<'tcx> for Resolver<'a, 'cl> { +impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { fn visit_item(&mut self, item: &'tcx Item) { self.resolve_item(item); } @@ -769,7 +769,7 @@ impl<'a, 'tcx, 'cl> Visitor<'tcx> for Resolver<'a, 'cl> { self.smart_resolve_path(ty.id, qself.as_ref(), path, PathSource::Type); } TyKind::ImplicitSelf => { - let self_ty = keywords::SelfType.ident(); + let self_ty = keywords::SelfUpper.ident(); let def = self.resolve_ident_in_lexical_scope(self_ty, TypeNS, Some(ty.id), ty.span) .map_or(Def::Err, |d| d.def()); self.record_def(ty.id, PathResolution::new(def)); @@ -1173,10 +1173,6 @@ impl<'a> ModuleData<'a> { } } - fn is_local(&self) -> bool { - self.normal_ancestor_id.is_local() - } - fn nearest_item_scope(&'a self) -> Module<'a> { if self.is_trait() { self.parent.unwrap() } else { self } } @@ -1476,7 +1472,7 @@ pub struct ExternPreludeEntry<'a> { /// The main resolver class. /// /// This is the visitor that walks the whole crate. -pub struct Resolver<'a, 'b: 'a> { +pub struct Resolver<'a> { session: &'a Session, cstore: &'a CStore, @@ -1519,8 +1515,12 @@ pub struct Resolver<'a, 'b: 'a> { /// The current self item if inside an ADT (used for better errors). current_self_item: Option, - /// FIXME: Refactor things so that this is passed through arguments and not resolver. + /// FIXME: Refactor things so that these fields are passed through arguments and not resolver. + /// We are resolving a last import segment during import validation. last_import_segment: bool, + /// This binding should be ignored during in-module resolution, so that we don't get + /// "self-confirming" import resolutions during import validation. + blacklisted_binding: Option<&'a NameBinding<'a>>, /// The idents for the primitive types. primitive_type_table: PrimitiveTypeTable, @@ -1576,7 +1576,7 @@ pub struct Resolver<'a, 'b: 'a> { arenas: &'a ResolverArenas<'a>, dummy_binding: &'a NameBinding<'a>, - crate_loader: &'a mut CrateLoader<'b>, + crate_loader: &'a mut CrateLoader<'a>, macro_names: FxHashSet, builtin_macros: FxHashMap>, macro_use_prelude: FxHashMap>, @@ -1584,7 +1584,6 @@ pub struct Resolver<'a, 'b: 'a> { macro_map: FxHashMap>, macro_defs: FxHashMap, local_macro_def_scopes: FxHashMap>, - pub whitelisted_legacy_custom_derives: Vec, pub found_unresolved_macro: bool, /// List of crate local macros that we need to warn about as being unused. @@ -1651,7 +1650,7 @@ impl<'a> ResolverArenas<'a> { } } -impl<'a, 'b: 'a, 'cl: 'b> ty::DefIdTree for &'a Resolver<'b, 'cl> { +impl<'a, 'b: 'a> ty::DefIdTree for &'a Resolver<'b> { fn parent(self, id: DefId) -> Option { match id.krate { LOCAL_CRATE => self.definitions.def_key(id.index).parent, @@ -1662,7 +1661,7 @@ impl<'a, 'b: 'a, 'cl: 'b> ty::DefIdTree for &'a Resolver<'b, 'cl> { /// This interface is used through the AST→HIR step, to embed full paths into the HIR. After that /// the resolver is no longer needed as all the relevant information is inline. -impl<'a, 'cl> hir::lowering::Resolver for Resolver<'a, 'cl> { +impl<'a> hir::lowering::Resolver for Resolver<'a> { fn resolve_hir_path( &mut self, path: &ast::Path, @@ -1679,7 +1678,7 @@ impl<'a, 'cl> hir::lowering::Resolver for Resolver<'a, 'cl> { components: &[&str], is_value: bool ) -> hir::Path { - let segments = iter::once(keywords::CrateRoot.ident()) + let segments = iter::once(keywords::PathRoot.ident()) .chain( crate_root.into_iter() .chain(components.iter().cloned()) @@ -1708,7 +1707,7 @@ impl<'a, 'cl> hir::lowering::Resolver for Resolver<'a, 'cl> { } } -impl<'a, 'crateloader> Resolver<'a, 'crateloader> { +impl<'a> Resolver<'a> { /// Rustdoc uses this to resolve things in a recoverable way. ResolutionError<'a> /// isn't something that can be returned because it can't be made to live that long, /// and also it's a private type. Fortunately rustdoc doesn't need to know the error, @@ -1721,7 +1720,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> { let path = if path_str.starts_with("::") { ast::Path { span, - segments: iter::once(keywords::CrateRoot.ident()) + segments: iter::once(keywords::PathRoot.ident()) .chain({ path_str.split("::").skip(1).map(Ident::from_str) }) @@ -1797,15 +1796,15 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> { } } -impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { +impl<'a> Resolver<'a> { pub fn new(session: &'a Session, cstore: &'a CStore, krate: &Crate, crate_name: &str, make_glob_map: MakeGlobMap, - crate_loader: &'a mut CrateLoader<'crateloader>, + crate_loader: &'a mut CrateLoader<'a>, arenas: &'a ResolverArenas<'a>) - -> Resolver<'a, 'crateloader> { + -> Resolver<'a> { let root_def_id = DefId::local(CRATE_DEF_INDEX); let root_module_kind = ModuleKind::Def(Def::Mod(root_def_id), keywords::Invalid.name()); let graph_root = arenas.alloc_module(ModuleData { @@ -1871,6 +1870,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { current_self_type: None, current_self_item: None, last_import_segment: false, + blacklisted_binding: None, primitive_type_table: PrimitiveTypeTable::new(), @@ -1917,7 +1917,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { macro_defs, local_macro_def_scopes: FxHashMap::default(), name_already_seen: FxHashMap::default(), - whitelisted_legacy_custom_derives: Vec::new(), potentially_unused_imports: Vec::new(), struct_constructors: Default::default(), found_unresolved_macro: false, @@ -2036,7 +2035,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { let record_used = record_used_id.is_some(); assert!(ns == TypeNS || ns == ValueNS); if ns == TypeNS { - ident.span = if ident.name == keywords::SelfType.name() { + ident.span = if ident.name == keywords::SelfUpper.name() { // FIXME(jseyfried) improve `Self` hygiene ident.span.with_ctxt(SyntaxContext::empty()) } else { @@ -2605,7 +2604,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { result } - /// This is called to resolve a trait reference from an `impl` (i.e. `impl Trait for Foo`) + /// This is called to resolve a trait reference from an `impl` (i.e., `impl Trait for Foo`) fn with_optional_trait_ref(&mut self, opt_trait_ref: Option<&TraitRef>, f: F) -> T where F: FnOnce(&mut Resolver, Option) -> T { @@ -2649,7 +2648,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { let mut self_type_rib = Rib::new(NormalRibKind); // plain insert (no renaming, types are not currently hygienic....) - self_type_rib.bindings.insert(keywords::SelfType.ident(), self_def); + self_type_rib.bindings.insert(keywords::SelfUpper.ident(), self_def); self.ribs[TypeNS].push(self_type_rib); f(self); self.ribs[TypeNS].pop(); @@ -2660,7 +2659,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { { let self_def = Def::SelfCtor(impl_id); let mut self_type_rib = Rib::new(NormalRibKind); - self_type_rib.bindings.insert(keywords::SelfType.ident(), self_def); + self_type_rib.bindings.insert(keywords::SelfUpper.ident(), self_def); self.ribs[ValueNS].push(self_type_rib); f(self); self.ribs[ValueNS].pop(); @@ -2887,7 +2886,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { self.resolve_pattern(&pattern, PatternSource::Match, &mut bindings_list); } - // This has to happen *after* we determine which pat_idents are variants + // This has to happen *after* we determine which pat_idents are variants. self.check_consistent_bindings(&arm.pats); if let Some(ast::Guard::If(ref expr)) = arm.guard { @@ -3007,6 +3006,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { // Visit all direct subpatterns of this pattern. let outer_pat_id = pat.id; pat.walk(&mut |pat| { + debug!("resolve_pattern pat={:?} node={:?}", pat, pat.node); match pat.node { PatKind::Ident(bmode, ident, ref opt_pat) => { // First try to resolve the identifier as some existing @@ -3029,8 +3029,8 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { Def::StructCtor(..) | Def::VariantCtor(..) | Def::Const(..) | Def::Static(..) => { // This is unambiguously a fresh binding, either syntactically - // (e.g. `IDENT @ PAT` or `ref IDENT`) or because `IDENT` resolves - // to something unusable as a pattern (e.g. constructor function), + // (e.g., `IDENT @ PAT` or `ref IDENT`) or because `IDENT` resolves + // to something unusable as a pattern (e.g., constructor function), // but we still conservatively report an error, see // issues/33118#issuecomment-233962221 for one reason why. resolve_error( @@ -3146,7 +3146,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { let item_span = path.last().unwrap().ident.span; let (mod_prefix, mod_str) = if path.len() == 1 { (String::new(), "this scope".to_string()) - } else if path.len() == 2 && path[0].ident.name == keywords::CrateRoot.name() { + } else if path.len() == 2 && path[0].ident.name == keywords::PathRoot.name() { (String::new(), "the crate root".to_string()) } else { let mod_path = &path[..path.len() - 1]; @@ -3163,6 +3163,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { format!("not found in {}", mod_str), item_span) }; + let code = DiagnosticId::Error(code.into()); let mut err = this.session.struct_span_err_with_code(base_span, &base_msg, code); @@ -3186,11 +3187,22 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { return (err, Vec::new()); } if is_self_value(path, ns) { + debug!("smart_resolve_path_fragment E0424 source:{:?}", source); + __diagnostic_used!(E0424); err.code(DiagnosticId::Error("E0424".into())); - err.span_label(span, format!("`self` value is a keyword \ - only available in \ - methods with `self` parameter")); + err.span_label(span, match source { + PathSource::Pat => { + format!("`self` value is a keyword \ + and may not be bound to \ + variables or shadowed") + } + _ => { + format!("`self` value is a keyword \ + only available in methods \ + with `self` parameter") + } + }); return (err, Vec::new()); } @@ -3206,9 +3218,9 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { for (sp, variant_path, enum_path) in enum_candidates { if sp.is_dummy() { let msg = format!("there is an enum variant `{}`, \ - try using `{}`?", - variant_path, - enum_path); + try using `{}`?", + variant_path, + enum_path); err.help(&msg); } else { err.span_suggestion_with_applicability( @@ -3260,7 +3272,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { let mut levenshtein_worked = false; - // Try Levenshtein. + // Try Levenshtein algorithm. if let Some(candidate) = this.lookup_typo_candidate(path, ns, is_expected, span) { err.span_label(ident_span, format!("did you mean `{}`?", candidate)); levenshtein_worked = true; @@ -3515,13 +3527,13 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } fn self_type_is_available(&mut self, span: Span) -> bool { - let binding = self.resolve_ident_in_lexical_scope(keywords::SelfType.ident(), + let binding = self.resolve_ident_in_lexical_scope(keywords::SelfUpper.ident(), TypeNS, None, span); if let Some(LexicalScopeBinding::Def(def)) = binding { def != Def::Err } else { false } } fn self_value_is_available(&mut self, self_span: Span, path_span: Span) -> bool { - let ident = Ident::new(keywords::SelfValue.name(), self_span); + let ident = Ident::new(keywords::SelfLower.name(), self_span); let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, None, path_span); if let Some(LexicalScopeBinding::Def(def)) = binding { def != Def::Err } else { false } } @@ -3614,7 +3626,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { let res = self.smart_resolve_path_fragment( id, None, - &path[..qself.position + 1], + &path[..=qself.position], span, PathSource::TraitItem(ns), CrateLint::QPathTrait { @@ -3673,7 +3685,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { }; if path.len() > 1 && !global_by_default && result.base_def() != Def::Err && - path[0].ident.name != keywords::CrateRoot.name() && + path[0].ident.name != keywords::PathRoot.name() && path[0].ident.name != keywords::DollarCrate.name() { let unqualified_result = { match self.resolve_path_without_parent_scope( @@ -3755,7 +3767,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { let name = ident.name; allow_super &= ns == TypeNS && - (name == keywords::SelfValue.name() || + (name == keywords::SelfLower.name() || name == keywords::Super.name()); if ns == TypeNS { @@ -3779,24 +3791,24 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { return PathResult::Failed(ident.span, msg, false); } if i == 0 { - if name == keywords::SelfValue.name() { + if name == keywords::SelfLower.name() { let mut ctxt = ident.span.ctxt().modern(); module = Some(ModuleOrUniformRoot::Module( self.resolve_self(&mut ctxt, self.current_module))); continue; } if name == keywords::Extern.name() || - name == keywords::CrateRoot.name() && ident.span.rust_2018() { + name == keywords::PathRoot.name() && ident.span.rust_2018() { module = Some(ModuleOrUniformRoot::ExternPrelude); continue; } - if name == keywords::CrateRoot.name() && + if name == keywords::PathRoot.name() && ident.span.rust_2015() && self.session.rust_2018() { // `::a::b` from 2015 macro on 2018 global edition module = Some(ModuleOrUniformRoot::CrateRootAndExternPrelude); continue; } - if name == keywords::CrateRoot.name() || + if name == keywords::PathRoot.name() || name == keywords::Crate.name() || name == keywords::DollarCrate.name() { // `::a::b`, `crate::a::b` or `$crate::a::b` @@ -3809,12 +3821,12 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { // Report special messages for path segment keywords in wrong positions. if ident.is_path_segment_keyword() && i != 0 { - let name_str = if name == keywords::CrateRoot.name() { + let name_str = if name == keywords::PathRoot.name() { "crate root".to_string() } else { format!("`{}`", name) }; - let msg = if i == 1 && path[0].ident.name == keywords::CrateRoot.name() { + let msg = if i == 1 && path[0].ident.name == keywords::PathRoot.name() { format!("global paths cannot start with {}", name_str) } else { format!("{} in paths can only be used in start position", name_str) @@ -3944,7 +3956,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { // We're only interested in `use` paths which should start with // `{{root}}` or `extern` currently. - if first_name != keywords::Extern.name() && first_name != keywords::CrateRoot.name() { + if first_name != keywords::Extern.name() && first_name != keywords::PathRoot.name() { return } @@ -3953,7 +3965,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { Some(Segment { ident, .. }) if ident.name == keywords::Crate.name() => return, // Otherwise go below to see if it's an extern crate Some(_) => {} - // If the path has length one (and it's `CrateRoot` most likely) + // If the path has length one (and it's `PathRoot` most likely) // then we don't know whether we're gonna be importing a crate or an // item in our crate. Defer this lint to elsewhere None => return, @@ -4322,7 +4334,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { for pat in pats { this.resolve_pattern(pat, PatternSource::WhileLet, &mut bindings_list); } - // This has to happen *after* we determine which pat_idents are variants + // This has to happen *after* we determine which pat_idents are variants. this.check_consistent_bindings(pats); this.visit_block(block); this.ribs[ValueNS].pop(); @@ -4608,7 +4620,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { /// When name resolution fails, this method can be used to look up candidate /// entities with the expected name. It allows filtering them using the /// supplied predicate (which should be used to only accept the types of - /// definitions expected e.g. traits). The lookup spans across all crates. + /// definitions expected e.g., traits). The lookup spans across all crates. /// /// NOTE: The method does not look into imports, but this is not a problem, /// since we report the definitions (thus, the de-aliased imports). @@ -4740,7 +4752,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } else { let ctxt = ident.span.ctxt(); Some(Segment::from_ident(Ident::new( - keywords::CrateRoot.name(), path.span.shrink_to_lo().with_ctxt(ctxt) + keywords::PathRoot.name(), path.span.shrink_to_lo().with_ctxt(ctxt) ))) }; @@ -5090,17 +5102,17 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } fn is_self_type(path: &[Segment], namespace: Namespace) -> bool { - namespace == TypeNS && path.len() == 1 && path[0].ident.name == keywords::SelfType.name() + namespace == TypeNS && path.len() == 1 && path[0].ident.name == keywords::SelfUpper.name() } fn is_self_value(path: &[Segment], namespace: Namespace) -> bool { - namespace == ValueNS && path.len() == 1 && path[0].ident.name == keywords::SelfValue.name() + namespace == ValueNS && path.len() == 1 && path[0].ident.name == keywords::SelfLower.name() } fn names_to_string(idents: &[Ident]) -> String { let mut result = String::new(); for (i, ident) in idents.iter() - .filter(|ident| ident.name != keywords::CrateRoot.name()) + .filter(|ident| ident.name != keywords::PathRoot.name()) .enumerate() { if i > 0 { result.push_str("::"); diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 5db3efee9f6..81633c8f57f 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -10,7 +10,7 @@ use {AmbiguityError, AmbiguityKind, AmbiguityErrorMisc}; use {CrateLint, Resolver, ResolutionError, ScopeSet, Weak}; -use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult, Segment, ToNameBinding}; +use {Module, NameBinding, NameBindingKind, PathResult, Segment, ToNameBinding}; use {is_known_tool, resolve_error}; use ModuleOrUniformRoot; use Namespace::*; @@ -21,22 +21,16 @@ use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX, DefIndex, use rustc::hir::def::{Def, NonMacroAttrKind}; use rustc::hir::map::{self, DefCollector}; use rustc::{ty, lint}; -use syntax::ast::{self, Name, Ident}; +use syntax::ast::{self, Ident}; use syntax::attr; use syntax::errors::DiagnosticBuilder; use syntax::ext::base::{self, Determinacy}; -use syntax::ext::base::{MacroKind, SyntaxExtension, Resolver as SyntaxResolver}; +use syntax::ext::base::{MacroKind, SyntaxExtension}; use syntax::ext::expand::{AstFragment, Invocation, InvocationKind}; 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}; -use syntax::feature_gate::EXPLAIN_DERIVE_UNDERSCORE; -use syntax::fold::{self, Folder}; -use syntax::parse::parser::PathStyle; -use syntax::parse::token::{self, Token}; -use syntax::ptr::P; +use syntax::feature_gate::{feature_err, is_builtin_attr_name, GateIssue}; use syntax::symbol::{Symbol, keywords}; -use syntax::tokenstream::{TokenStream, TokenTree, Delimited, DelimSpan}; use syntax::util::lev_distance::find_best_match_for_name; use syntax_pos::{Span, DUMMY_SP}; use errors::Applicability; @@ -125,7 +119,7 @@ fn sub_namespace_match(candidate: Option, requirement: Option base::Resolver for Resolver<'a, 'crateloader> { +impl<'a> base::Resolver for Resolver<'a> { fn next_node_id(&mut self) -> ast::NodeId { self.session.next_node_id() } @@ -142,62 +136,6 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> { mark } - fn eliminate_crate_var(&mut self, item: P) -> P { - struct EliminateCrateVar<'b, 'a: 'b, 'crateloader: 'a>( - &'b mut Resolver<'a, 'crateloader>, Span - ); - - impl<'a, 'b, 'crateloader> Folder for EliminateCrateVar<'a, 'b, 'crateloader> { - fn fold_path(&mut self, path: ast::Path) -> ast::Path { - match self.fold_qpath(None, path) { - (None, path) => path, - _ => unreachable!(), - } - } - - fn fold_qpath(&mut self, mut qself: Option, mut path: ast::Path) - -> (Option, ast::Path) { - qself = qself.map(|ast::QSelf { ty, path_span, position }| { - ast::QSelf { - ty: self.fold_ty(ty), - path_span: self.new_span(path_span), - position, - } - }); - - if path.segments[0].ident.name == keywords::DollarCrate.name() { - let module = self.0.resolve_crate_root(path.segments[0].ident); - path.segments[0].ident.name = keywords::CrateRoot.name(); - if !module.is_local() { - let span = path.segments[0].ident.span; - path.segments.insert(1, match module.kind { - ModuleKind::Def(_, name) => ast::PathSegment::from_ident( - ast::Ident::with_empty_ctxt(name).with_span_pos(span) - ), - _ => unreachable!(), - }); - if let Some(qself) = &mut qself { - qself.position += 1; - } - } - } - (qself, path) - } - - fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { - fold::noop_fold_mac(mac, self) - } - } - - let ret = EliminateCrateVar(self, item.span).fold_item(item); - assert!(ret.len() == 1); - ret.into_iter().next().unwrap() - } - - fn is_whitelisted_legacy_custom_derive(&self, name: Name) -> bool { - self.whitelisted_legacy_custom_derives.contains(&name) - } - fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment, derives: &[Mark]) { let invocation = self.invocations[&mark]; @@ -240,79 +178,6 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> { ImportResolver { resolver: self }.resolve_imports() } - // Resolves attribute and derive legacy macros from `#![plugin(..)]`. - fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec, allow_derive: bool) - -> Option { - if !allow_derive { - return None; - } - - // Check for legacy derives - for i in 0..attrs.len() { - let name = attrs[i].name(); - - if name == "derive" { - let result = attrs[i].parse_list(&self.session.parse_sess, |parser| { - parser.parse_path_allowing_meta(PathStyle::Mod) - }); - - let mut traits = match result { - Ok(traits) => traits, - Err(mut e) => { - e.cancel(); - continue - } - }; - - for j in 0..traits.len() { - if traits[j].segments.len() > 1 { - continue - } - let trait_name = traits[j].segments[0].ident.name; - let legacy_name = Symbol::intern(&format!("derive_{}", trait_name)); - if !self.builtin_macros.contains_key(&legacy_name) { - continue - } - let span = traits.remove(j).span; - self.gate_legacy_custom_derive(legacy_name, span); - if traits.is_empty() { - attrs.remove(i); - } else { - let mut tokens = Vec::with_capacity(traits.len() - 1); - for (j, path) in traits.iter().enumerate() { - if j > 0 { - tokens.push(TokenTree::Token(attrs[i].span, Token::Comma).into()); - } - tokens.reserve((path.segments.len() * 2).saturating_sub(1)); - for (k, segment) in path.segments.iter().enumerate() { - if k > 0 { - tokens.push(TokenTree::Token(path.span, Token::ModSep).into()); - } - let tok = Token::from_ast_ident(segment.ident); - tokens.push(TokenTree::Token(path.span, tok).into()); - } - } - let delim_span = DelimSpan::from_single(attrs[i].span); - attrs[i].tokens = TokenTree::Delimited(delim_span, Delimited { - delim: token::Paren, - tts: TokenStream::concat(tokens).into(), - }).into(); - } - return Some(ast::Attribute { - path: ast::Path::from_ident(Ident::new(legacy_name, span)), - tokens: TokenStream::empty(), - id: attr::mk_attr_id(), - style: ast::AttrStyle::Outer, - is_sugared_doc: false, - span, - }); - } - } - } - - None - } - fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: Mark, force: bool) -> Result>, Determinacy> { let (path, kind, derives_in_scope, after_derive) = match invoc.kind { @@ -340,7 +205,6 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> { self.definitions.add_parent_module_of_macro_def(invoc.expansion_data.mark, normal_module_def_id); invoc.expansion_data.mark.set_default_transparency(ext.default_transparency()); - invoc.expansion_data.mark.set_is_builtin(def_id.krate == CrateNum::BuiltinMacros); } Ok(Some(ext)) @@ -371,7 +235,7 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> { } } -impl<'a, 'cl> Resolver<'a, 'cl> { +impl<'a> Resolver<'a> { pub fn dummy_parent_scope(&self) -> ParentScope<'a> { self.invoc_parent_scope(Mark::root(), Vec::new()) } @@ -430,11 +294,6 @@ impl<'a, 'cl> Resolver<'a, 'cl> { feature_err(&self.session.parse_sess, "rustc_attrs", path.span, GateIssue::Language, &msg).emit(); } - } else if name.starts_with("derive_") { - if !features.custom_derive { - feature_err(&self.session.parse_sess, "custom_derive", path.span, - GateIssue::Language, EXPLAIN_DERIVE_UNDERSCORE).emit(); - } } else if !features.custom_attribute { let msg = format!("The attribute `{}` is currently unknown to the \ compiler and may have meaning added to it in the \ @@ -445,7 +304,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { } } else { // Not only attributes, but anything in macro namespace can result in - // `Def::NonMacroAttr` definition (e.g. `inline!()`), so we must report + // `Def::NonMacroAttr` definition (e.g., `inline!()`), so we must report // an error for those cases. let msg = format!("expected a macro, found {}", def.kind_name()); self.session.span_err(path.span, &msg); @@ -522,7 +381,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // Resolve an identifier in lexical scope. // This is a variation of `fn resolve_ident_in_lexical_scope` that can be run during // expansion and import resolution (perhaps they can be merged in the future). - // The function is used for resolving initial segments of macro paths (e.g. `foo` in + // The function is used for resolving initial segments of macro paths (e.g., `foo` in // `foo::bar!(); or `foo!();`) and also for import paths on 2018 edition. crate fn early_resolve_ident_in_lexical_scope( &mut self, @@ -674,7 +533,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { _ => Err(Determinacy::Determined), } WhereToResolve::CrateRoot => { - let root_ident = Ident::new(keywords::CrateRoot.name(), orig_ident.span); + let root_ident = Ident::new(keywords::PathRoot.name(), orig_ident.span); let root_module = self.resolve_crate_root(root_ident); let binding = self.resolve_ident_in_module_ext( ModuleOrUniformRoot::Module(root_module), @@ -960,7 +819,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { break 'ok; } if rust_2015 { - let root_ident = Ident::new(keywords::CrateRoot.name(), orig_ident.span); + let root_ident = Ident::new(keywords::PathRoot.name(), orig_ident.span); let root_module = self.resolve_crate_root(root_ident); if self.resolve_ident_in_module_ext(ModuleOrUniformRoot::Module(root_module), orig_ident, ns, None, false, path_span) @@ -977,12 +836,14 @@ impl<'a, 'cl> Resolver<'a, 'cl> { let what = self.binding_description(binding, ident, flags.contains(Flags::MISC_FROM_PRELUDE)); let note_msg = format!("this import refers to {what}", what = what); - if binding.span.is_dummy() { + let label_span = if binding.span.is_dummy() { err.note(¬e_msg); + ident.span } else { err.span_note(binding.span, ¬e_msg); - err.span_label(binding.span, "not an extern crate passed with `--extern`"); - } + binding.span + }; + err.span_label(label_span, "not an extern crate passed with `--extern`"); err.emit(); } @@ -1216,14 +1077,4 @@ impl<'a, 'cl> Resolver<'a, 'cl> { self.define(module, ident, MacroNS, (def, vis, item.span, expansion)); } } - - fn gate_legacy_custom_derive(&mut self, name: Symbol, span: Span) { - if !self.session.features_untracked().custom_derive { - let sess = &self.session.parse_sess; - let explain = feature_gate::EXPLAIN_CUSTOM_DERIVE; - emit_feature_err(sess, "custom_derive", span, GateIssue::Language, explain); - } else if !self.is_whitelisted_legacy_custom_derive(name) { - self.session.span_warn(span, feature_gate::EXPLAIN_DEPR_CUSTOM_DERIVE); - } - } } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index e7cd32f4e81..7b55ee9ce33 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -42,9 +42,15 @@ use std::{mem, ptr}; #[derive(Clone, Debug)] pub enum ImportDirectiveSubclass<'a> { SingleImport { - target: Ident, + /// `source` in `use prefix::source as target`. source: Ident, - result: PerNS, Determinacy>>>, + /// `target` in `use prefix::source as target`. + target: Ident, + /// Bindings to which `source` refers to. + source_bindings: PerNS, Determinacy>>>, + /// Bindings introduced by `target`. + target_bindings: PerNS>>>, + /// `true` for `...::{self [as target]}` imports, `false` otherwise. type_ns_only: bool, }, GlobImport { @@ -128,7 +134,7 @@ impl<'a> NameResolution<'a> { } } -impl<'a, 'crateloader> Resolver<'a, 'crateloader> { +impl<'a> Resolver<'a> { fn resolution(&self, module: Module<'a>, ident: Ident, ns: Namespace) -> &'a RefCell> { *module.resolutions.borrow_mut().entry((ident.modern(), ns)) @@ -198,7 +204,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> { .to_name_binding(self.arenas); return Ok(binding); } else if ident.name == keywords::Super.name() || - ident.name == keywords::SelfValue.name() { + ident.name == keywords::SelfLower.name() { // FIXME: Implement these with renaming requirements so that e.g. // `use super;` doesn't work, but `use super as name;` does. // Fall through here to get an error from `early_resolve_...`. @@ -227,6 +233,11 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> { } let check_usable = |this: &mut Self, binding: &'a NameBinding<'a>| { + if let Some(blacklisted_binding) = this.blacklisted_binding { + if ptr::eq(binding, blacklisted_binding) { + return Err((Determined, Weak::No)); + } + } // `extern crate` are always usable for backwards compatibility, see issue #37020, // remove this together with `PUB_USE_OF_PRIVATE_EXTERN_CRATE`. let usable = this.is_accessible(binding.vis) || binding.is_extern_crate(); @@ -419,7 +430,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> { crate fn import(&self, binding: &'a NameBinding<'a>, directive: &'a ImportDirective<'a>) -> &'a NameBinding<'a> { let vis = if binding.pseudo_vis().is_at_least(directive.vis.get(), self) || - // c.f. `PUB_USE_OF_PRIVATE_EXTERN_CRATE` + // cf. `PUB_USE_OF_PRIVATE_EXTERN_CRATE` !directive.is_glob() && binding.is_extern_crate() { directive.vis.get() } else { @@ -530,7 +541,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> { // If the resolution becomes a success, define it in the module's glob importers. fn update_resolution(&mut self, module: Module<'a>, ident: Ident, ns: Namespace, f: F) -> T - where F: FnOnce(&mut Resolver<'a, 'crateloader>, &mut NameResolution<'a>) -> T + where F: FnOnce(&mut Resolver<'a>, &mut NameResolution<'a>) -> T { // Ensure that `resolution` isn't borrowed when defining in the module's glob importers, // during which the resolution might end up getting re-defined via a glob cycle. @@ -581,30 +592,30 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> { } } -pub struct ImportResolver<'a, 'b: 'a, 'c: 'a + 'b> { - pub resolver: &'a mut Resolver<'b, 'c>, +pub struct ImportResolver<'a, 'b: 'a> { + pub resolver: &'a mut Resolver<'b>, } -impl<'a, 'b: 'a, 'c: 'a + 'b> ::std::ops::Deref for ImportResolver<'a, 'b, 'c> { - type Target = Resolver<'b, 'c>; - fn deref(&self) -> &Resolver<'b, 'c> { +impl<'a, 'b: 'a> ::std::ops::Deref for ImportResolver<'a, 'b> { + type Target = Resolver<'b>; + fn deref(&self) -> &Resolver<'b> { self.resolver } } -impl<'a, 'b: 'a, 'c: 'a + 'b> ::std::ops::DerefMut for ImportResolver<'a, 'b, 'c> { - fn deref_mut(&mut self) -> &mut Resolver<'b, 'c> { +impl<'a, 'b: 'a> ::std::ops::DerefMut for ImportResolver<'a, 'b> { + fn deref_mut(&mut self) -> &mut Resolver<'b> { self.resolver } } -impl<'a, 'b: 'a, 'c: 'a + 'b> ty::DefIdTree for &'a ImportResolver<'a, 'b, 'c> { +impl<'a, 'b: 'a> ty::DefIdTree for &'a ImportResolver<'a, 'b> { fn parent(self, id: DefId) -> Option { self.resolver.parent(id) } } -impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { +impl<'a, 'b:'a> ImportResolver<'a, 'b> { // Import resolution // // This is a fixed-point algorithm. We resolve imports until our efforts @@ -642,10 +653,10 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { if let Some((span, err, note)) = self.finalize_import(import) { errors = true; - if let SingleImport { source, ref result, .. } = import.subclass { + if let SingleImport { source, ref source_bindings, .. } = import.subclass { if source.name == "self" { // Silence `unresolved import` error if E0429 is already emitted - if let Err(Determined) = result.value_ns.get() { + if let Err(Determined) = source_bindings.value_ns.get() { continue; } } @@ -765,9 +776,11 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { }; directive.imported_module.set(Some(module)); - let (source, target, result, type_ns_only) = match directive.subclass { - SingleImport { source, target, ref result, type_ns_only } => - (source, target, result, type_ns_only), + let (source, target, source_bindings, target_bindings, type_ns_only) = + match directive.subclass { + SingleImport { source, target, ref source_bindings, + ref target_bindings, type_ns_only } => + (source, target, source_bindings, target_bindings, type_ns_only), GlobImport { .. } => { self.resolve_glob_import(directive); return true; @@ -777,7 +790,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { let mut indeterminate = false; self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS { - if let Err(Undetermined) = result[ns].get() { + if let Err(Undetermined) = source_bindings[ns].get() { // For better failure detection, pretend that the import will // not define any names while resolving its module path. let orig_vis = directive.vis.replace(ty::Visibility::Invisible); @@ -786,13 +799,13 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { ); directive.vis.set(orig_vis); - result[ns].set(binding); + source_bindings[ns].set(binding); } else { return }; let parent = directive.parent_scope.module; - match result[ns].get() { + match source_bindings[ns].get() { Err(Undetermined) => indeterminate = true, Err(Determined) => { this.update_resolution(parent, target, ns, |_, resolution| { @@ -810,6 +823,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { } Ok(binding) => { let imported_binding = this.import(binding, directive); + target_bindings[ns].set(Some(imported_binding)); let conflict = this.try_define(parent, target, ns, imported_binding); if let Err(old_binding) = conflict { this.report_conflict(parent, target, ns, imported_binding, old_binding); @@ -829,14 +843,16 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { self.current_module = directive.parent_scope.module; let orig_vis = directive.vis.replace(ty::Visibility::Invisible); + let prev_ambiguity_errors_len = self.ambiguity_errors.len(); let path_res = self.resolve_path(&directive.module_path, None, &directive.parent_scope, true, directive.span, directive.crate_lint()); + let no_ambiguity = self.ambiguity_errors.len() == prev_ambiguity_errors_len; directive.vis.set(orig_vis); let module = match path_res { PathResult::Module(module) => { // Consistency checks, analogous to `finalize_current_module_macro_resolutions`. if let Some(initial_module) = directive.imported_module.get() { - if module != initial_module && self.ambiguity_errors.is_empty() { + if module != initial_module && no_ambiguity { span_bug!(directive.span, "inconsistent resolution for an import"); } } else { @@ -850,37 +866,42 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { module } PathResult::Failed(span, msg, false) => { - assert!(!self.ambiguity_errors.is_empty() || - directive.imported_module.get().is_none()); - resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); + if no_ambiguity { + assert!(directive.imported_module.get().is_none()); + resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); + } return None; } PathResult::Failed(span, msg, true) => { - assert!(!self.ambiguity_errors.is_empty() || - directive.imported_module.get().is_none()); - return if let Some((suggested_path, note)) = self.make_path_suggestion( - span, directive.module_path.clone(), &directive.parent_scope - ) { - Some(( - span, - format!("did you mean `{}`?", Segment::names_to_string(&suggested_path)), - note, - )) - } else { - Some((span, msg, None)) - }; + if no_ambiguity { + assert!(directive.imported_module.get().is_none()); + return Some(match self.make_path_suggestion(span, directive.module_path.clone(), + &directive.parent_scope) { + Some((suggestion, note)) => ( + span, + format!("did you mean `{}`?", Segment::names_to_string(&suggestion)), + note, + ), + None => (span, msg, None), + }); + } + return None; } PathResult::NonModule(path_res) if path_res.base_def() == Def::Err => { + if no_ambiguity { + assert!(directive.imported_module.get().is_none()); + } // The error was already reported earlier. - assert!(!self.ambiguity_errors.is_empty() || - directive.imported_module.get().is_none()); return None; } PathResult::Indeterminate | PathResult::NonModule(..) => unreachable!(), }; - let (ident, result, type_ns_only) = match directive.subclass { - SingleImport { source, ref result, type_ns_only, .. } => (source, result, type_ns_only), + let (ident, target, source_bindings, target_bindings, type_ns_only) = + match directive.subclass { + SingleImport { source, target, ref source_bindings, + ref target_bindings, type_ns_only } => + (source, target, source_bindings, target_bindings, type_ns_only), GlobImport { is_prelude, ref max_vis } => { if directive.module_path.len() <= 1 { // HACK(eddyb) `lint_if_path_starts_with_module` needs at least @@ -919,20 +940,28 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { let mut all_ns_err = true; self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS { let orig_vis = directive.vis.replace(ty::Visibility::Invisible); + let orig_blacklisted_binding = + mem::replace(&mut this.blacklisted_binding, target_bindings[ns].get()); let orig_last_import_segment = mem::replace(&mut this.last_import_segment, true); let binding = this.resolve_ident_in_module( module, ident, ns, Some(&directive.parent_scope), true, directive.span ); this.last_import_segment = orig_last_import_segment; + this.blacklisted_binding = orig_blacklisted_binding; directive.vis.set(orig_vis); match binding { Ok(binding) => { // Consistency checks, analogous to `finalize_current_module_macro_resolutions`. - let initial_def = result[ns].get().map(|initial_binding| { + let initial_def = source_bindings[ns].get().map(|initial_binding| { all_ns_err = false; - this.record_use(ident, ns, initial_binding, - directive.module_path.is_empty()); + if let Some(target_binding) = target_bindings[ns].get() { + if target.name == "_" && + initial_binding.is_extern_crate() && !initial_binding.is_import() { + this.record_use(ident, ns, target_binding, + directive.module_path.is_empty()); + } + } initial_binding.def_ignoring_ambiguity() }); let def = binding.def_ignoring_ambiguity(); @@ -986,7 +1015,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { NameBindingKind::Import { binding, .. } => { match binding.kind { // Never suggest the name that has binding error - // i.e. the name that cannot be previously resolved + // i.e., the name that cannot be previously resolved NameBindingKind::Def(Def::Err, _) => return None, _ => Some(&i.name), } @@ -1034,7 +1063,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { let mut reexport_error = None; let mut any_successful_reexport = false; self.per_ns(|this, ns| { - if let Ok(binding) = result[ns].get() { + if let Ok(binding) = source_bindings[ns].get() { let vis = directive.vis.get(); if !binding.pseudo_vis().is_at_least(vis, &*this) { reexport_error = Some((ns, binding)); @@ -1078,7 +1107,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { let mut full_path = directive.module_path.clone(); full_path.push(Segment::from_ident(ident)); self.per_ns(|this, ns| { - if let Ok(binding) = result[ns].get() { + if let Ok(binding) = source_bindings[ns].get() { this.lint_if_path_starts_with_module( directive.crate_lint(), &full_path, @@ -1092,7 +1121,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { // Record what this import resolves to for later uses in documentation, // this may resolve to either a value or a type, but for documentation // purposes it's good enough to just favor one over the other. - self.per_ns(|this, ns| if let Some(binding) = result[ns].get().ok() { + self.per_ns(|this, ns| if let Some(binding) = source_bindings[ns].get().ok() { let mut def = binding.def(); if let Def::Macro(def_id, _) = def { // `DefId`s from the "built-in macro crate" should not leak from resolve because @@ -1263,8 +1292,8 @@ fn import_path_to_string(names: &[Ident], subclass: &ImportDirectiveSubclass, span: Span) -> String { let pos = names.iter() - .position(|p| span == p.span && p.name != keywords::CrateRoot.name()); - let global = !names.is_empty() && names[0].name == keywords::CrateRoot.name(); + .position(|p| span == p.span && p.name != keywords::PathRoot.name()); + let global = !names.is_empty() && names[0].name == keywords::PathRoot.name(); if let Some(pos) = pos { let names = if global { &names[1..pos + 1] } else { &names[..pos + 1] }; names_to_string(names) diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 15c8861eb3f..b1c1c9635bf 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -126,7 +126,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { where F: FnOnce(&mut DumpVisitor<'l, 'tcx, 'll, O>), { - let item_def_id = self.tcx.hir.local_def_id(item_id); + let item_def_id = self.tcx.hir().local_def_id(item_id); if self.tcx.has_typeck_tables(item_def_id) { let tables = self.tcx.typeck_tables_of(item_def_id); let old_tables = self.save_ctxt.tables; @@ -249,7 +249,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { collector.visit_pat(&arg.pat); for (id, ident, ..) in collector.collected_idents { - let hir_id = self.tcx.hir.node_to_hir_id(id); + let hir_id = self.tcx.hir().node_to_hir_id(id); let typ = match self.save_ctxt.tables.node_id_to_type_opt(hir_id) { Some(s) => s.to_string(), None => continue, @@ -673,7 +673,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { } self.process_generic_params(type_parameters, "", item.id); for impl_item in impl_items { - let map = &self.tcx.hir; + let map = &self.tcx.hir(); self.process_impl_item(impl_item, map.local_def_id(item.id)); } } @@ -752,7 +752,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { // walk generics and methods self.process_generic_params(generics, &qualname, item.id); for method in methods { - let map = &self.tcx.hir; + let map = &self.tcx.hir(); self.process_trait_item(method, map.local_def_id(item.id)) } } @@ -866,7 +866,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { match p.node { PatKind::Struct(ref _path, ref fields, _) => { // FIXME do something with _path? - let hir_id = self.tcx.hir.node_to_hir_id(p.id); + let hir_id = self.tcx.hir().node_to_hir_id(p.id); let adt = match self.save_ctxt.tables.node_id_to_type_opt(hir_id) { Some(ty) => ty.ty_adt_def().unwrap(), None => { @@ -911,7 +911,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { } else { "".to_owned() }; - let hir_id = self.tcx.hir.node_to_hir_id(id); + let hir_id = self.tcx.hir().node_to_hir_id(id); let typ = self.save_ctxt .tables .node_id_to_type_opt(hir_id) @@ -982,7 +982,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { ast::Mutability::Immutable => value.to_string(), _ => String::new(), }; - let hir_id = self.tcx.hir.node_to_hir_id(id); + let hir_id = self.tcx.hir().node_to_hir_id(id); let typ = match self.save_ctxt.tables.node_id_to_type_opt(hir_id) { Some(typ) => { let typ = typ.to_string(); @@ -1204,7 +1204,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { let access = access_from!(self.save_ctxt, root_item.vis, id); // The parent def id of a given use tree is always the enclosing item. - let parent = self.save_ctxt.tcx.hir.opt_local_def_id(id) + let parent = self.save_ctxt.tcx.hir().opt_local_def_id(id) .and_then(|id| self.save_ctxt.tcx.parent_def_id(id)) .map(::id_from_def_id); @@ -1357,7 +1357,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc let name_span = item.ident.span; if !self.span.filter_generated(name_span) { let span = self.span_from_span(name_span); - let parent = self.save_ctxt.tcx.hir.opt_local_def_id(item.id) + let parent = self.save_ctxt.tcx.hir().opt_local_def_id(item.id) .and_then(|id| self.save_ctxt.tcx.parent_def_id(id)) .map(::id_from_def_id); self.dumper.import( @@ -1510,7 +1510,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc self.process_macro_use(ex.span); match ex.node { ast::ExprKind::Struct(ref path, ref fields, ref base) => { - let hir_expr = self.save_ctxt.tcx.hir.expect_expr(ex.id); + let hir_expr = self.save_ctxt.tcx.hir().expect_expr(ex.id); let adt = match self.save_ctxt.tables.expr_ty_opt(&hir_expr) { Some(ty) if ty.ty_adt_def().is_some() => ty.ty_adt_def().unwrap(), _ => { diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 82c4795a29d..e0acc150ee3 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -110,7 +110,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } } - // Returns path to the compilation output (e.g. libfoo-12345678.rmeta) + // Returns path to the compilation output (e.g., libfoo-12345678.rmeta) pub fn compilation_output(&self, crate_name: &str) -> PathBuf { let sess = &self.tcx.sess; // Save-analysis is emitted per whole session, not per each crate type @@ -383,7 +383,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let name = ident.to_string(); let qualname = format!("::{}::{}", self.tcx.node_path_str(scope), ident); filter!(self.span_utils, ident.span); - let def_id = self.tcx.hir.local_def_id(field.id); + let def_id = self.tcx.hir().local_def_id(field.id); let typ = self.tcx.type_of(def_id).to_string(); @@ -415,18 +415,18 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { // The qualname for a method is the trait name or name of the struct in an impl in // which the method is declared in, followed by the method's name. let (qualname, parent_scope, decl_id, docs, attributes) = - match self.tcx.impl_of_method(self.tcx.hir.local_def_id(id)) { - Some(impl_id) => match self.tcx.hir.get_if_local(impl_id) { + match self.tcx.impl_of_method(self.tcx.hir().local_def_id(id)) { + Some(impl_id) => match self.tcx.hir().get_if_local(impl_id) { Some(Node::Item(item)) => match item.node { hir::ItemKind::Impl(.., ref ty, _) => { let mut qualname = String::from("<"); - qualname.push_str(&self.tcx.hir.node_to_pretty_string(ty.id)); + qualname.push_str(&self.tcx.hir().node_to_pretty_string(ty.id)); let trait_id = self.tcx.trait_id_of_impl(impl_id); let mut decl_id = None; let mut docs = String::new(); let mut attrs = vec![]; - if let Some(Node::ImplItem(item)) = self.tcx.hir.find(id) { + if let Some(Node::ImplItem(item)) = self.tcx.hir().find(id) { docs = self.docs_for_attrs(&item.attrs); attrs = item.attrs.to_vec(); } @@ -463,12 +463,12 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { ); } }, - None => match self.tcx.trait_of_item(self.tcx.hir.local_def_id(id)) { + None => match self.tcx.trait_of_item(self.tcx.hir().local_def_id(id)) { Some(def_id) => { let mut docs = String::new(); let mut attrs = vec![]; - if let Some(Node::TraitItem(item)) = self.tcx.hir.find(id) { + if let Some(Node::TraitItem(item)) = self.tcx.hir().find(id) { docs = self.docs_for_attrs(&item.attrs); attrs = item.attrs.to_vec(); } @@ -529,14 +529,14 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } pub fn get_expr_data(&self, expr: &ast::Expr) -> Option { - let hir_node = self.tcx.hir.expect_expr(expr.id); + let hir_node = self.tcx.hir().expect_expr(expr.id); let ty = self.tables.expr_ty_adjusted_opt(&hir_node); if ty.is_none() || ty.unwrap().sty == ty::Error { return None; } match expr.node { ast::ExprKind::Field(ref sub_ex, ident) => { - let hir_node = match self.tcx.hir.find(sub_ex.id) { + let hir_node = match self.tcx.hir().find(sub_ex.id) { Some(Node::Expr(expr)) => expr, _ => { debug!( @@ -587,7 +587,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } } ast::ExprKind::MethodCall(ref seg, ..) => { - let expr_hir_id = self.tcx.hir.definitions().node_to_hir_id(expr.id); + let expr_hir_id = self.tcx.hir().definitions().node_to_hir_id(expr.id); let method_id = match self.tables.type_dependent_defs().get(expr_hir_id) { Some(id) => id.def_id(), None => { @@ -622,7 +622,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } pub fn get_path_def(&self, id: NodeId) -> HirDef { - match self.tcx.hir.get(id) { + match self.tcx.hir().get(id) { Node::TraitRef(tr) => tr.path.def, Node::Item(&hir::Item { @@ -656,7 +656,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { node: hir::PatKind::TupleStruct(ref qpath, ..), .. }) => { - let hir_id = self.tcx.hir.node_to_hir_id(id); + let hir_id = self.tcx.hir().node_to_hir_id(id); self.tables.qpath_def(qpath, hir_id) } @@ -1183,7 +1183,7 @@ fn id_from_def_id(id: DefId) -> rls_data::Id { } fn id_from_node_id(id: NodeId, scx: &SaveContext) -> rls_data::Id { - let def_id = scx.tcx.hir.opt_local_def_id(id); + let def_id = scx.tcx.hir().opt_local_def_id(id); def_id.map(|id| id_from_def_id(id)).unwrap_or_else(|| { // Create a *fake* `DefId` out of a `NodeId` by subtracting the `NodeId` // out of the maximum u32 value. This will work unless you have *billions* diff --git a/src/librustc_target/abi/call/mod.rs b/src/librustc_target/abi/call/mod.rs index 489bb37fc26..1c3763c6e37 100644 --- a/src/librustc_target/abi/call/mod.rs +++ b/src/librustc_target/abi/call/mod.rs @@ -164,7 +164,7 @@ impl Reg { } /// An argument passed entirely registers with the -/// same kind (e.g. HFA / HVA on PPC64 and AArch64). +/// same kind (e.g., HFA / HVA on PPC64 and AArch64). #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub struct Uniform { pub unit: Reg, @@ -173,7 +173,7 @@ pub struct Uniform { /// * equal to `unit.size` (one scalar/vector) /// * a multiple of `unit.size` (an array of scalar/vectors) /// * if `unit.kind` is `Integer`, the last element - /// can be shorter, i.e. `{ i64, i64, i32 }` for + /// can be shorter, i.e., `{ i64, i64, i32 }` for /// 64-bit integers with a total size of 20 bytes pub total: Size, } diff --git a/src/librustc_target/abi/call/s390x.rs b/src/librustc_target/abi/call/s390x.rs index d6d8ea71918..fe1c8751792 100644 --- a/src/librustc_target/abi/call/s390x.rs +++ b/src/librustc_target/abi/call/s390x.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// FIXME: The assumes we're using the non-vector ABI, i.e. compiling +// FIXME: The assumes we're using the non-vector ABI, i.e., compiling // for a pre-z13 machine or using -mno-vx. use abi::call::{FnType, ArgType, Reg}; diff --git a/src/librustc_target/abi/call/x86_64.rs b/src/librustc_target/abi/call/x86_64.rs index f091f80924d..0f27300dc3b 100644 --- a/src/librustc_target/abi/call/x86_64.rs +++ b/src/librustc_target/abi/call/x86_64.rs @@ -15,7 +15,7 @@ use abi::call::{ArgType, CastTarget, FnType, Reg, RegKind}; use abi::{self, Abi, HasDataLayout, LayoutOf, Size, TyLayout, TyLayoutMethods}; /// Classification of "eightbyte" components. -// NB: the order of the variants is from general to specific, +// N.B., the order of the variants is from general to specific, // such that `unify(a, b)` is the "smaller" of `a` and `b`. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)] enum Class { diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 50ce0ad6915..5912da9d3aa 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -409,7 +409,7 @@ impl Align { /// Compute the best alignment possible for the given offset /// (the largest power of two that the offset is a multiple of). /// - /// NB: for an offset of `0`, this happens to return `2^64`. + /// N.B., for an offset of `0`, this happens to return `2^64`. pub fn max_for_offset(offset: Size) -> Align { Align { pow2: offset.bytes().trailing_zeros() as u8, @@ -639,7 +639,7 @@ pub struct Scalar { /// /// This is intended specifically to mirror LLVM’s `!range` metadata, /// semantics. - // FIXME(eddyb) always use the shortest range, e.g. by finding + // FIXME(eddyb) always use the shortest range, e.g., by finding // the largest space between two consecutive valid values and // taking everything else as the (shortest) valid range. pub valid_range: RangeInclusive, @@ -887,12 +887,12 @@ impl LayoutDetails { } /// The details of the layout of a type, alongside the type itself. -/// Provides various type traversal APIs (e.g. recursing into fields). +/// Provides various type traversal APIs (e.g., recursing into fields). /// /// Note that the details are NOT guaranteed to always be identical /// to those obtained from `layout_of(ty)`, as we need to produce /// layouts for which Rust types do not exist, such as enum variants -/// or synthetic fields of enums (i.e. discriminants) and fat pointers. +/// or synthetic fields of enums (i.e., discriminants) and fat pointers. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub struct TyLayout<'a, Ty> { pub ty: Ty, diff --git a/src/librustc_target/spec/abi.rs b/src/librustc_target/spec/abi.rs index 6d8c8eb19f0..919744fe046 100644 --- a/src/librustc_target/spec/abi.rs +++ b/src/librustc_target/spec/abi.rs @@ -12,7 +12,7 @@ use std::fmt; #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Clone, Copy, Debug)] pub enum Abi { - // NB: This ordering MUST match the AbiDatas array below. + // N.B., this ordering MUST match the AbiDatas array below. // (This is ensured by the test indices_are_correct().) // Single platform ABIs diff --git a/src/librustc_target/spec/apple_ios_base.rs b/src/librustc_target/spec/apple_ios_base.rs index e926e4913d6..ef41ea31e3e 100644 --- a/src/librustc_target/spec/apple_ios_base.rs +++ b/src/librustc_target/spec/apple_ios_base.rs @@ -74,6 +74,8 @@ fn build_pre_link_args(arch: Arch) -> Result { args.insert(LinkerFlavor::Gcc, vec!["-arch".to_string(), arch_name.to_string(), + "-isysroot".to_string(), + sdk_root.clone(), "-Wl,-syslibroot".to_string(), sdk_root]); diff --git a/src/librustc_target/spec/armv7_linux_androideabi.rs b/src/librustc_target/spec/armv7_linux_androideabi.rs index 06abe0b2c9e..b1bc4df0a16 100644 --- a/src/librustc_target/spec/armv7_linux_androideabi.rs +++ b/src/librustc_target/spec/armv7_linux_androideabi.rs @@ -10,6 +10,11 @@ use spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; +// This target if is for the baseline of the Android v7a ABI +// in thumb mode. It's named armv7-* instead of thumbv7-* +// for historical reasons. See the thumbv7neon variant for +// enabling NEON. + // See https://developer.android.com/ndk/guides/abis.html#v7a // for target ABI requirements. diff --git a/src/librustc_target/spec/armv7_unknown_linux_gnueabihf.rs b/src/librustc_target/spec/armv7_unknown_linux_gnueabihf.rs index 14e8fa9dc02..5e9a127f2f4 100644 --- a/src/librustc_target/spec/armv7_unknown_linux_gnueabihf.rs +++ b/src/librustc_target/spec/armv7_unknown_linux_gnueabihf.rs @@ -10,6 +10,9 @@ use spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; +// This target is for glibc Linux on ARMv7 without NEON or +// thumb-mode. See the thumbv7neon variant for enabling both. + pub fn target() -> TargetResult { let base = super::linux_base::opts(); Ok(Target { diff --git a/src/librustc_target/spec/armv7_unknown_linux_musleabihf.rs b/src/librustc_target/spec/armv7_unknown_linux_musleabihf.rs index 6e71cb307b9..66aa8d1dfcf 100644 --- a/src/librustc_target/spec/armv7_unknown_linux_musleabihf.rs +++ b/src/librustc_target/spec/armv7_unknown_linux_musleabihf.rs @@ -10,6 +10,8 @@ use spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; +// This target is for musl Linux on ARMv7 without thumb-mode or NEON. + pub fn target() -> TargetResult { let base = super::linux_musl_base::opts(); Ok(Target { diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 5b8070cbf3d..15f31275fd0 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -68,6 +68,7 @@ mod linux_musl_base; mod openbsd_base; mod netbsd_base; mod solaris_base; +mod uefi_base; mod windows_base; mod windows_msvc_base; mod thumb_base; @@ -234,7 +235,7 @@ macro_rules! supported_targets { $(mod $module;)* /// List of supported targets - const TARGETS: &'static [&'static str] = &[$($triple),*]; + const TARGETS: &[&str] = &[$($triple),*]; fn load_specific(target: &str) -> TargetResult { match target { @@ -254,12 +255,12 @@ macro_rules! supported_targets { } } - pub fn get_targets() -> Box> { - Box::new(TARGETS.iter().filter_map(|t| -> Option { + pub fn get_targets() -> impl Iterator { + TARGETS.iter().filter_map(|t| -> Option { load_specific(t) .and(Ok(t.to_string())) .ok() - })) + }) } #[cfg(test)] @@ -313,6 +314,7 @@ supported_targets! { ("armv5te-unknown-linux-gnueabi", armv5te_unknown_linux_gnueabi), ("armv5te-unknown-linux-musleabi", armv5te_unknown_linux_musleabi), ("armv7-unknown-linux-gnueabihf", armv7_unknown_linux_gnueabihf), + ("thumbv7neon-unknown-linux-gnueabihf", thumbv7neon_unknown_linux_gnueabihf), ("armv7-unknown-linux-musleabihf", armv7_unknown_linux_musleabihf), ("aarch64-unknown-linux-gnu", aarch64_unknown_linux_gnu), @@ -330,6 +332,7 @@ supported_targets! { ("x86_64-linux-android", x86_64_linux_android), ("arm-linux-androideabi", arm_linux_androideabi), ("armv7-linux-androideabi", armv7_linux_androideabi), + ("thumbv7neon-linux-androideabi", thumbv7neon_linux_androideabi), ("aarch64-linux-android", aarch64_linux_android), ("aarch64-unknown-freebsd", aarch64_unknown_freebsd), @@ -400,6 +403,8 @@ supported_targets! { ("thumbv7em-none-eabi", thumbv7em_none_eabi), ("thumbv7em-none-eabihf", thumbv7em_none_eabihf), ("thumbv8m.base-none-eabi", thumbv8m_base_none_eabi), + ("thumbv8m.main-none-eabi", thumbv8m_main_none_eabi), + ("thumbv8m.main-none-eabihf", thumbv8m_main_none_eabihf), ("msp430-none-elf", msp430_none_elf), @@ -417,6 +422,8 @@ supported_targets! { ("aarch64-unknown-none", aarch64_unknown_none), ("x86_64-fortanix-unknown-sgx", x86_64_fortanix_unknown_sgx), + + ("x86_64-unknown-uefi", x86_64_unknown_uefi), } /// Everything `rustc` knows about how to compile for a specific target. @@ -603,7 +610,7 @@ pub struct TargetOptions { /// `eh_unwind_resume` lang item. pub custom_unwind_resume: bool, - /// Flag indicating whether ELF TLS (e.g. #[thread_local]) is available for + /// Flag indicating whether ELF TLS (e.g., #[thread_local]) is available for /// this target. pub has_elf_tls: bool, // This is mainly for easy compatibility with emscripten. diff --git a/src/librustc_target/spec/thumb_base.rs b/src/librustc_target/spec/thumb_base.rs index 22e5f49fd59..d760f5bf1f7 100644 --- a/src/librustc_target/spec/thumb_base.rs +++ b/src/librustc_target/spec/thumb_base.rs @@ -18,8 +18,9 @@ // - Cortex-M4(F) // - Cortex-M7(F) // - Cortex-M23 +// - Cortex-M33 // -// We have opted for these instead of one target per processor (e.g. `cortex-m0`, `cortex-m3`, +// We have opted for these instead of one target per processor (e.g., `cortex-m0`, `cortex-m3`, // etc) because the differences between some processors like the cortex-m0 and cortex-m1 are almost // non-existent from the POV of codegen so it doesn't make sense to have separate targets for them. // And if differences exist between two processors under the same target, rustc flags can be used to diff --git a/src/librustc_target/spec/thumbv7neon_linux_androideabi.rs b/src/librustc_target/spec/thumbv7neon_linux_androideabi.rs new file mode 100644 index 00000000000..eebbf85400c --- /dev/null +++ b/src/librustc_target/spec/thumbv7neon_linux_androideabi.rs @@ -0,0 +1,44 @@ +// 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. + +use spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; + +// This target if is for the Android v7a ABI in thumb mode with +// NEON unconditionally enabled and, therefore, with 32 FPU registers +// enabled as well. See section A2.6.2 on page A2-56 in +// https://static.docs.arm.com/ddi0406/cd/DDI0406C_d_armv7ar_arm.pdf + +// See https://developer.android.com/ndk/guides/abis.html#v7a +// for target ABI requirements. + +pub fn target() -> TargetResult { + let mut base = super::android_base::opts(); + base.features = "+v7,+thumb-mode,+thumb2,+vfp3,+neon".to_string(); + base.max_atomic_width = Some(64); + base.pre_link_args + .get_mut(&LinkerFlavor::Gcc).unwrap().push("-march=armv7-a".to_string()); + + Ok(Target { + llvm_target: "armv7-none-linux-android".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), + arch: "arm".to_string(), + target_os: "android".to_string(), + target_env: "".to_string(), + target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, + options: TargetOptions { + abi_blacklist: super::arm_base::abi_blacklist(), + .. base + }, + }) +} diff --git a/src/librustc_target/spec/thumbv7neon_unknown_linux_gnueabihf.rs b/src/librustc_target/spec/thumbv7neon_unknown_linux_gnueabihf.rs new file mode 100644 index 00000000000..8e641e2f6eb --- /dev/null +++ b/src/librustc_target/spec/thumbv7neon_unknown_linux_gnueabihf.rs @@ -0,0 +1,42 @@ +// 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. + +use spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; + +// This target is for glibc Linux on ARMv7 with thumb mode enabled +// (for consistency with Android and Debian-based distributions) +// and with NEON unconditionally enabled and, therefore, with 32 FPU +// registers enabled as well. See section A2.6.2 on page A2-56 in +// https://static.docs.arm.com/ddi0406/cd/DDI0406C_d_armv7ar_arm.pdf + +pub fn target() -> TargetResult { + let base = super::linux_base::opts(); + Ok(Target { + llvm_target: "armv7-unknown-linux-gnueabihf".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), + arch: "arm".to_string(), + target_os: "linux".to_string(), + target_env: "gnu".to_string(), + target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, + + options: TargetOptions { + // Info about features at https://wiki.debian.org/ArmHardFloatPort + features: "+v7,+thumb-mode,+thumb2,+vfp3,+neon".to_string(), + cpu: "generic".to_string(), + max_atomic_width: Some(64), + abi_blacklist: super::arm_base::abi_blacklist(), + .. base + } + }) +} diff --git a/src/librustc_target/spec/thumbv8m_main_none_eabi.rs b/src/librustc_target/spec/thumbv8m_main_none_eabi.rs new file mode 100644 index 00000000000..6dc203e81bf --- /dev/null +++ b/src/librustc_target/spec/thumbv8m_main_none_eabi.rs @@ -0,0 +1,34 @@ +// 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. + +// Targets the Cortex-M33 processor (Armv8-M Mainline architecture profile), +// without the Floating Point extension. + +use spec::{LinkerFlavor, LldFlavor, Target, TargetOptions, TargetResult}; + +pub fn target() -> TargetResult { + Ok(Target { + llvm_target: "thumbv8m.main-none-eabi".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), + arch: "arm".to_string(), + target_os: "none".to_string(), + target_env: String::new(), + target_vendor: String::new(), + linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), + + options: TargetOptions { + max_atomic_width: Some(32), + .. super::thumb_base::opts() + }, + }) +} diff --git a/src/librustc_target/spec/thumbv8m_main_none_eabihf.rs b/src/librustc_target/spec/thumbv8m_main_none_eabihf.rs new file mode 100644 index 00000000000..dc7728c2bd5 --- /dev/null +++ b/src/librustc_target/spec/thumbv8m_main_none_eabihf.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. + +// Targets the Cortex-M33 processor (Armv8-M Mainline architecture profile), +// with the Floating Point extension. + +use spec::{LinkerFlavor, LldFlavor, Target, TargetOptions, TargetResult}; + +pub fn target() -> TargetResult { + Ok(Target { + llvm_target: "thumbv8m.main-none-eabihf".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), + arch: "arm".to_string(), + target_os: "none".to_string(), + target_env: String::new(), + target_vendor: String::new(), + linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), + + options: TargetOptions { + // If the Floating Point extension is implemented in the Cortex-M33 + // processor, the Cortex-M33 Technical Reference Manual states that + // the FPU uses the FPv5 architecture, single-precision instructions + // and 16 D registers. + // These parameters map to the following LLVM features. + features: "+fp-armv8,+fp-only-sp,+d16".to_string(), + max_atomic_width: Some(32), + .. super::thumb_base::opts() + }, + }) +} diff --git a/src/librustc_target/spec/uefi_base.rs b/src/librustc_target/spec/uefi_base.rs new file mode 100644 index 00000000000..9b18c3faad7 --- /dev/null +++ b/src/librustc_target/spec/uefi_base.rs @@ -0,0 +1,75 @@ +// 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. + +// This defines a base target-configuration for native UEFI systems. The UEFI specification has +// quite detailed sections on the ABI of all the supported target architectures. In almost all +// cases it simply follows what Microsoft Windows does. Hence, whenever in doubt, see the MSDN +// documentation. +// UEFI uses COFF/PE32+ format for binaries. All binaries must be statically linked. No dynamic +// linker is supported. As native to COFF, binaries are position-dependent, but will be relocated +// by the loader if the pre-chosen memory location is already in use. +// UEFI forbids running code on anything but the boot-CPU. Not interrupts are allowed other than +// the timer-interrupt. Device-drivers are required to use polling-based models. Furthermore, all +// code runs in the same environment, no process separation is supported. + +use spec::{LinkArgs, LinkerFlavor, LldFlavor, PanicStrategy, TargetOptions}; +use std::default::Default; + +pub fn opts() -> TargetOptions { + let mut pre_link_args = LinkArgs::new(); + + pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Link), vec![ + // Suppress the verbose logo and authorship debugging output, which would needlessly + // clog any log files. + "/NOLOGO".to_string(), + + // UEFI is fully compatible to non-executable data pages. Tell the compiler that + // non-code sections can be marked as non-executable, including stack pages. + "/NXCOMPAT".to_string(), + + // There is no runtime for UEFI targets, prevent them from being linked. UEFI targets + // must be freestanding. + "/nodefaultlib".to_string(), + + // Non-standard subsystems have no default entry-point in PE+ files. We have to define + // one. "efi_main" seems to be a common choice amongst other implementations and the + // spec. + "/entry:efi_main".to_string(), + + // COFF images have a "Subsystem" field in their header, which defines what kind of + // program it is. UEFI has 3 fields reserved, which are EFI_APPLICATION, + // EFI_BOOT_SERVICE_DRIVER, and EFI_RUNTIME_DRIVER. We default to EFI_APPLICATION, + // which is very likely the most common option. Individual projects can override this + // with custom linker flags. + // The subsystem-type only has minor effects on the application. It defines the memory + // regions the application is loaded into (runtime-drivers need to be put into + // reserved areas), as well as whether a return from the entry-point is treated as + // exit (default for applications). + "/subsystem:efi_application".to_string(), + ]); + + TargetOptions { + dynamic_linking: false, + executables: true, + disable_redzone: true, + exe_suffix: ".efi".to_string(), + allows_weak_linkage: false, + panic_strategy: PanicStrategy::Abort, + stack_probes: true, + singlethread: true, + emit_debug_gdb_scripts: false, + + linker: Some("lld-link".to_string()), + lld_flavor: LldFlavor::Link, + pre_link_args, + + .. Default::default() + } +} diff --git a/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs b/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs index 07383b3d648..6a6aab2bea3 100644 --- a/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs +++ b/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs @@ -10,28 +10,29 @@ use std::iter; -use super::{LinkerFlavor, Target, TargetOptions, PanicStrategy}; +use super::{LinkerFlavor, PanicStrategy, Target, TargetOptions}; pub fn target() -> Result { const PRE_LINK_ARGS: &[&str] = &[ "-Wl,--as-needed", "-Wl,-z,noexecstack", "-m64", - "-fuse-ld=gold", - "-nostdlib", - "-shared", - "-Wl,-e,sgx_entry", - "-Wl,-Bstatic", - "-Wl,--gc-sections", - "-Wl,-z,text", - "-Wl,-z,norelro", - "-Wl,--rosegment", - "-Wl,--no-undefined", - "-Wl,--error-unresolved-symbols", - "-Wl,--no-undefined-version", - "-Wl,-Bsymbolic", - "-Wl,--export-dynamic", + "-fuse-ld=gold", + "-nostdlib", + "-shared", + "-Wl,-e,sgx_entry", + "-Wl,-Bstatic", + "-Wl,--gc-sections", + "-Wl,-z,text", + "-Wl,-z,norelro", + "-Wl,--rosegment", + "-Wl,--no-undefined", + "-Wl,--error-unresolved-symbols", + "-Wl,--no-undefined-version", + "-Wl,-Bsymbolic", + "-Wl,--export-dynamic", ]; + const EXPORT_SYMBOLS: &[&str] = &[ "sgx_entry", "HEAP_BASE", @@ -41,18 +42,26 @@ pub fn target() -> Result { "ENCLAVE_SIZE", "CFGDATA_BASE", "DEBUG", + "EH_FRM_HDR_BASE", + "EH_FRM_HDR_SIZE", + "TEXT_BASE", + "TEXT_SIZE", ]; let opts = TargetOptions { dynamic_linking: false, executables: true, linker_is_gnu: true, max_atomic_width: Some(64), - panic_strategy: PanicStrategy::Abort, + panic_strategy: PanicStrategy::Unwind, cpu: "x86-64".into(), + features: "+rdrnd,+rdseed".into(), position_independent_executables: true, - pre_link_args: iter::once( - (LinkerFlavor::Gcc, PRE_LINK_ARGS.iter().cloned().map(String::from).collect()) - ).collect(), + pre_link_args: iter::once(( + LinkerFlavor::Gcc, + PRE_LINK_ARGS.iter().cloned().map(String::from).collect(), + )) + .collect(), + post_link_objects: vec!["libunwind.a".into()], override_export_symbols: Some(EXPORT_SYMBOLS.iter().cloned().map(String::from).collect()), ..Default::default() }; diff --git a/src/librustc_target/spec/x86_64_unknown_uefi.rs b/src/librustc_target/spec/x86_64_unknown_uefi.rs new file mode 100644 index 00000000000..ea68afa7173 --- /dev/null +++ b/src/librustc_target/spec/x86_64_unknown_uefi.rs @@ -0,0 +1,58 @@ +// 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. + +// This defines the amd64 target for UEFI systems as described in the UEFI specification. See the +// uefi-base module for generic UEFI options. On x86_64 systems (mostly called "x64" in the spec) +// UEFI systems always run in long-mode, have the interrupt-controller pre-configured and force a +// single-CPU execution. +// The win64 ABI is used. It differs from the sysv64 ABI, so we must use a windows target with +// LLVM. "x86_64-unknown-windows" is used to get the minimal subset of windows-specific features. + +use spec::{LinkerFlavor, LldFlavor, Target, TargetResult}; + +pub fn target() -> TargetResult { + let mut base = super::uefi_base::opts(); + base.cpu = "x86-64".to_string(); + base.max_atomic_width = Some(64); + + // We disable MMX and SSE for now. UEFI does not prevent these from being used, but there have + // been reports to GRUB that some firmware does not initialize the FP exception handlers + // properly. Therefore, using FP coprocessors will end you up at random memory locations when + // you throw FP exceptions. + // To be safe, we disable them for now and force soft-float. This can be revisited when we + // have more test coverage. Disabling FP served GRUB well so far, so it should be good for us + // as well. + base.features = "-mmx,-sse,+soft-float".to_string(); + + // UEFI systems run without a host OS, hence we cannot assume any code locality. We must tell + // LLVM to expect code to reference any address in the address-space. The "large" code-model + // places no locality-restrictions, so it fits well here. + base.code_model = Some("large".to_string()); + + // UEFI mostly mirrors the calling-conventions used on windows. In case of x86-64 this means + // small structs will be returned as int. This shouldn't matter much, since the restrictions + // placed by the UEFI specifications forbid any ABI to return structures. + base.abi_return_struct_as_int = true; + + Ok(Target { + llvm_target: "x86_64-unknown-windows".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "64".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:w-i64:64-f80:128-n8:16:32:64-S128".to_string(), + target_os: "uefi".to_string(), + target_env: "".to_string(), + target_vendor: "unknown".to_string(), + arch: "x86_64".to_string(), + linker_flavor: LinkerFlavor::Lld(LldFlavor::Link), + + options: base, + }) +} diff --git a/src/librustc_traits/Cargo.toml b/src/librustc_traits/Cargo.toml index f057cbb5033..48a5864d0da 100644 --- a/src/librustc_traits/Cargo.toml +++ b/src/librustc_traits/Cargo.toml @@ -18,4 +18,4 @@ rustc_target = { path = "../librustc_target" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } chalk-engine = { version = "0.8.0", default-features=false } -smallvec = { version = "0.6.5", features = ["union"] } +smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } diff --git a/src/librustc_traits/chalk_context/resolvent_ops.rs b/src/librustc_traits/chalk_context/resolvent_ops.rs index df6458a766d..73aa8a10724 100644 --- a/src/librustc_traits/chalk_context/resolvent_ops.rs +++ b/src/librustc_traits/chalk_context/resolvent_ops.rs @@ -17,7 +17,7 @@ use rustc::traits::{ }; use rustc::ty::{self, Ty}; use rustc::ty::subst::Kind; -use rustc::ty::relate::{Relate, RelateResult, TypeRelation}; +use rustc::ty::relate::{self, Relate, RelateResult, TypeRelation}; use syntax_pos::DUMMY_SP; use super::{ChalkInferenceContext, ChalkArenas, ChalkExClause, ConstrainedSubst}; @@ -137,6 +137,10 @@ impl TypeRelation<'cx, 'gcx, 'tcx> for AnswerSubstitutor<'cx, 'gcx, 'tcx> { self.infcx.tcx } + fn trait_object_mode(&self) -> relate::TraitObjectMode { + self.infcx.trait_object_mode() + } + fn tag(&self) -> &'static str { "chalk_context::answer_substitutor" } diff --git a/src/librustc_traits/implied_outlives_bounds.rs b/src/librustc_traits/implied_outlives_bounds.rs index 7514c2c18e7..d46ce8b10b9 100644 --- a/src/librustc_traits/implied_outlives_bounds.rs +++ b/src/librustc_traits/implied_outlives_bounds.rs @@ -77,7 +77,7 @@ fn compute_implied_outlives_bounds<'tcx>( let obligations = wf::obligations(infcx, param_env, DUMMY_NODE_ID, ty, DUMMY_SP).unwrap_or(vec![]); - // NB: All of these predicates *ought* to be easily proven + // N.B., all of these predicates *ought* to be easily proven // true. In fact, their correctness is (mostly) implied by // other parts of the program. However, in #42552, we had // an annoying scenario where: diff --git a/src/librustc_traits/lowering/environment.rs b/src/librustc_traits/lowering/environment.rs index 519b0ac6105..ad034bfff5a 100644 --- a/src/librustc_traits/lowering/environment.rs +++ b/src/librustc_traits/lowering/environment.rs @@ -228,8 +228,8 @@ crate fn environment<'a, 'tcx>( // could bound lifetimes. .map(Clause::ForAll); - let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); - let node = tcx.hir.get(node_id); + let node_id = tcx.hir().as_local_node_id(def_id).unwrap(); + let node = tcx.hir().get(node_id); let mut is_fn = false; let mut is_impl = false; diff --git a/src/librustc_traits/lowering/mod.rs b/src/librustc_traits/lowering/mod.rs index 2d8e5b48aac..473eebbde78 100644 --- a/src/librustc_traits/lowering/mod.rs +++ b/src/librustc_traits/lowering/mod.rs @@ -43,7 +43,7 @@ crate fn provide(p: &mut Providers) { } crate trait Lower { - /// Lower a rustc construct (e.g. `ty::TraitPredicate`) to a chalk-like type. + /// Lower a rustc construct (e.g., `ty::TraitPredicate`) to a chalk-like type. fn lower(&self) -> T; } @@ -90,9 +90,9 @@ where } /// `ty::Binder` is used for wrapping a rustc construction possibly containing generic -/// lifetimes, e.g. `for<'a> T: Fn(&'a i32)`. Instead of representing higher-ranked things -/// in that leaf-form (i.e. `Holds(Implemented(Binder))` in the previous -/// example), we model them with quantified domain goals, e.g. as for the previous example: +/// lifetimes, e.g., `for<'a> T: Fn(&'a i32)`. Instead of representing higher-ranked things +/// in that leaf-form (i.e., `Holds(Implemented(Binder))` in the previous +/// example), we model them with quantified domain goals, e.g., as for the previous example: /// `forall<'a> { T: Fn(&'a i32) }` which corresponds to something like /// `Binder`. impl<'tcx, T> Lower> for ty::Binder @@ -248,7 +248,7 @@ fn program_clauses_for_trait<'a, 'tcx>( // and that named bound regions have a def-id, it is safe // to just inject `hypotheses` (which contains named vars bound at index `0`) // into this binding level. This may change if we ever allow where clauses - // to bind types (e.g. for GATs things), because bound types only use a `BoundVar` + // to bind types (e.g., for GATs things), because bound types only use a `BoundVar` // index (no def-id). hypotheses, @@ -560,7 +560,7 @@ pub fn program_clauses_for_associated_type_value<'a, 'tcx>( // ``` // // FIXME: For the moment, we don't account for where clauses written on the associated - // ty definition (i.e. in the trait def, as in `type AssocType where T: Sized`). + // ty definition (i.e., in the trait def, as in `type AssocType where T: Sized`). // ``` // forall { // forall { @@ -615,7 +615,7 @@ pub fn dump_program_clauses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { } let mut visitor = ClauseDumper { tcx }; - tcx.hir + tcx.hir() .krate() .visit_all_item_likes(&mut visitor.as_deep_visitor()); } @@ -626,7 +626,7 @@ struct ClauseDumper<'a, 'tcx: 'a> { impl<'a, 'tcx> ClauseDumper<'a, 'tcx> { fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) { - let def_id = self.tcx.hir.local_def_id(node_id); + let def_id = self.tcx.hir().local_def_id(node_id); for attr in attrs { let mut clauses = None; @@ -664,7 +664,7 @@ impl<'a, 'tcx> ClauseDumper<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for ClauseDumper<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir) + NestedVisitorMap::OnlyBodies(&self.tcx.hir()) } fn visit_item(&mut self, item: &'tcx hir::Item) { diff --git a/src/librustc_tsan/Cargo.toml b/src/librustc_tsan/Cargo.toml index baadb64511a..f0618275f2f 100644 --- a/src/librustc_tsan/Cargo.toml +++ b/src/librustc_tsan/Cargo.toml @@ -16,4 +16,4 @@ cmake = "0.1.18" [dependencies] alloc = { path = "../liballoc" } core = { path = "../libcore" } -compiler_builtins = { path = "../rustc/compiler_builtins_shim" } +compiler_builtins = "0.1.0" diff --git a/src/librustc_typeck/Cargo.toml b/src/librustc_typeck/Cargo.toml index 881fa2604bc..87f11b01a1d 100644 --- a/src/librustc_typeck/Cargo.toml +++ b/src/librustc_typeck/Cargo.toml @@ -17,6 +17,6 @@ rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } rustc_platform_intrinsics = { path = "../librustc_platform_intrinsics" } rustc_target = { path = "../librustc_target" } -smallvec = { version = "0.6.5", features = ["union"] } +smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 4fbbe584452..ab1eeffc621 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -8,38 +8,38 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Conversion from AST representation of types to the `ty.rs` -//! representation. The main routine here is `ast_ty_to_ty()`: each use -//! is parameterized by an instance of `AstConv`. +//! Conversion from AST representation of types to the `ty.rs` representation. +//! The main routine here is `ast_ty_to_ty()`; each use is is parameterized by +//! an instance of `AstConv`. -use smallvec::SmallVec; +use errors::{Applicability, FatalError, DiagnosticId}; use hir::{self, GenericArg, GenericArgs}; use hir::def::Def; use hir::def_id::DefId; use hir::HirVec; +use lint; use middle::resolve_lifetime as rl; use namespace::Namespace; -use rustc::ty::subst::{Kind, Subst, Substs}; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable}; use rustc::ty::{GenericParamDef, GenericParamDefKind}; +use rustc::ty::subst::{Kind, Subst, Substs}; use rustc::ty::wf::object_region_bounds; use rustc_data_structures::sync::Lrc; use rustc_target::spec::abi; -use std::collections::BTreeSet; -use std::slice; use require_c_abi_if_variadic; -use util::common::ErrorReported; -use util::nodemap::FxHashMap; -use errors::{Applicability, FatalError, DiagnosticId}; -use lint; - -use std::iter; +use smallvec::SmallVec; use syntax::ast; use syntax::feature_gate::{GateIssue, emit_feature_err}; use syntax::ptr::P; use syntax::util::lev_distance::find_best_match_for_name; use syntax_pos::{DUMMY_SP, Span, MultiSpan}; +use util::common::ErrorReported; +use util::nodemap::FxHashMap; + +use std::collections::BTreeSet; +use std::iter; +use std::slice; pub trait AstConv<'gcx, 'tcx> { fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx>; @@ -80,7 +80,7 @@ pub trait AstConv<'gcx, 'tcx> { fn normalize_ty(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx>; /// Invoked when we encounter an error from some prior pass - /// (e.g. resolve) that is translated into a ty-error. This is + /// (e.g., resolve) that is translated into a ty-error. This is /// used to help suppress derived errors typeck might otherwise /// report. fn set_tainted_by_errors(&self); @@ -97,7 +97,7 @@ struct ConvertedBinding<'tcx> { #[derive(PartialEq)] enum GenericArgPosition { Type, - Value, // e.g. functions + Value, // e.g., functions MethodCall, } @@ -106,7 +106,7 @@ enum GenericArgPosition { /// This type must not appear anywhere in other converted types. const TRAIT_OBJECT_DUMMY_SELF: ty::TyKind<'static> = ty::Infer(ty::FreshTy(0)); -impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { +impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { pub fn ast_region_to_region(&self, lifetime: &hir::Lifetime, def: Option<&ty::GenericParamDef>) @@ -114,10 +114,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { { let tcx = self.tcx(); let lifetime_name = |def_id| { - tcx.hir.name(tcx.hir.as_local_node_id(def_id).unwrap()).as_interned_str() + tcx.hir().name(tcx.hir().as_local_node_id(def_id).unwrap()).as_interned_str() }; - let hir_id = tcx.hir.node_to_hir_id(lifetime.id); + let hir_id = tcx.hir().node_to_hir_id(lifetime.id); let r = match tcx.named_region(hir_id) { Some(rl::Region::Static) => { tcx.types.re_static @@ -321,8 +321,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { provided, offset| { // We enforce the following: `required` <= `provided` <= `permitted`. - // For kinds without defaults (i.e. lifetimes), `required == permitted`. - // For other kinds (i.e. types), `permitted` may be greater than `required`. + // For kinds without defaults (i.e., lifetimes), `required == permitted`. + // For other kinds (i.e., types), `permitted` may be greater than `required`. if required <= provided && provided <= permitted { return (false, None); } @@ -411,24 +411,24 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { /// creating the substitutions for, and a partial set of /// substitutions `parent_substs`. In general, the substitutions /// for an item begin with substitutions for all the "parents" of - /// that item -- so e.g. for a method it might include the + /// that item -- e.g., for a method it might include the /// parameters from the impl. /// /// Therefore, the method begins by walking down these parents, /// starting with the outermost parent and proceed inwards until - /// it reaches `def_id`. For each parent P, it will check `parent_substs` + /// it reaches `def_id`. For each parent `P`, it will check `parent_substs` /// first to see if the parent's substitutions are listed in there. If so, /// we can append those and move on. Otherwise, it invokes the /// three callback functions: /// - /// - `args_for_def_id`: given the def-id P, supplies back the + /// - `args_for_def_id`: given the def-id `P`, supplies back the /// generic arguments that were given to that parent from within - /// the path; so e.g. if you have `::Bar`, the def-id + /// the path; so e.g., if you have `::Bar`, the def-id /// might refer to the trait `Foo`, and the arguments might be /// `[T]`. The boolean value indicates whether to infer values /// for arguments whose values were not explicitly provided. /// - `provided_kind`: given the generic parameter and the value from `args_for_def_id`, - /// instantiate a `Kind` + /// instantiate a `Kind`. /// - `inferred_kind`: if no parameter was provided, and inference is enabled, then /// creates a suitable inference variable. pub fn create_substs_for_generic_args<'a, 'b>( @@ -441,7 +441,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { provided_kind: impl Fn(&GenericParamDef, &GenericArg) -> Kind<'tcx>, inferred_kind: impl Fn(Option<&[Kind<'tcx>]>, &GenericParamDef, bool) -> Kind<'tcx>, ) -> &'tcx Substs<'tcx> { - // Collect the segments of the path: we need to substitute arguments + // Collect the segments of the path; we need to substitute arguments // for parameters throughout the entire path (wherever there are // generic parameters). let mut parent_defs = tcx.generics_of(def_id); @@ -453,8 +453,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { } // We manually build up the substitution, rather than using convenience - // methods in `subst.rs` so that we can iterate over the arguments and - // parameters in lock-step linearly, rather than trying to match each pair. + // methods in `subst.rs`, so that we can iterate over the arguments and + // parameters in lock-step linearly, instead of trying to match each pair. let mut substs: SmallVec<[Kind<'tcx>; 8]> = SmallVec::with_capacity(count); // Iterate over each segment of the path. @@ -1013,6 +1013,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { let mut associated_types = BTreeSet::default(); for tr in traits::elaborate_trait_ref(tcx, principal) { + debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", tr); match tr { ty::Predicate::Trait(pred) => { associated_types.extend(tcx.associated_items(pred.def_id()) @@ -1020,8 +1021,31 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { .map(|item| item.def_id)); } ty::Predicate::Projection(pred) => { - // Include projections defined on supertraits. - projection_bounds.push((pred, DUMMY_SP)) + // A `Self` within the original bound will be substituted with a + // `TRAIT_OBJECT_DUMMY_SELF`, so check for that. + let references_self = + pred.skip_binder().ty.walk().any(|t| t == dummy_self); + + // If the projection output contains `Self`, force the user to + // elaborate it explicitly to avoid a bunch of complexity. + // + // The "classicaly useful" case is the following: + // ``` + // trait MyTrait: FnMut() -> ::MyOutput { + // type MyOutput; + // } + // ``` + // + // Here, the user could theoretically write `dyn MyTrait`, + // but actually supporting that would "expand" to an infinitely-long type + // `fix $ Ï„ → dyn MyTrait::MyOutput`. + // + // Instead, we force the user to write `dyn MyTrait`, + // which is uglier but works. See the discussion in #56288 for alternatives. + if !references_self { + // Include projections defined on supertraits, + projection_bounds.push((pred, DUMMY_SP)) + } } _ => () } @@ -1087,13 +1111,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { } } if !suggestions.is_empty() { - let msg = if suggestions.len() == 1 { - "if you meant to specify the associated type, write" - } else { - "if you meant to specify the associated types, write" - }; + let msg = format!("if you meant to specify the associated {}, write", + if suggestions.len() == 1 { "type" } else { "types" }); err.multipart_suggestion_with_applicability( - msg, + &msg, suggestions, Applicability::MaybeIncorrect, ); @@ -1135,7 +1156,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { self.ast_region_to_region(lifetime, None) } else { self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_else(|| { - let hir_id = tcx.hir.node_to_hir_id(lifetime.id); + let hir_id = tcx.hir().node_to_hir_id(lifetime.id); if tcx.named_region(hir_id).is_some() { self.ast_region_to_region(lifetime, None) } else { @@ -1190,8 +1211,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { let suitable_bounds = traits::transitive_bounds(tcx, bounds) .filter(|b| self.trait_defines_associated_type_named(b.def_id(), assoc_name)); - let param_node_id = tcx.hir.as_local_node_id(ty_param_def_id).unwrap(); - let param_name = tcx.hir.ty_param_name(param_node_id); + let param_node_id = tcx.hir().as_local_node_id(ty_param_def_id).unwrap(); + let param_name = tcx.hir().ty_param_name(param_node_id); self.one_bound_for_assoc_type(suitable_bounds, ¶m_name.as_str(), assoc_name, @@ -1235,7 +1256,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { item.kind == ty::AssociatedKind::Type && self.tcx().hygienic_eq(assoc_name, item.ident, bound.def_id()) }) - .and_then(|item| self.tcx().hir.span_if_local(item.def_id)); + .and_then(|item| self.tcx().hir().span_if_local(item.def_id)); if let Some(span) = bound_span { err.span_label(span, format!("ambiguous `{}` from `{}`", @@ -1279,7 +1300,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { // item is declared. let bound = match (&ty.sty, ty_path_def) { (_, Def::SelfTy(Some(_), Some(impl_def_id))) => { - // `Self` in an impl of a trait - we have a concrete `self` type and a + // `Self` in an impl of a trait -- we have a concrete `self` type and a // trait reference. let trait_ref = match tcx.impl_trait_ref(impl_def_id) { Some(trait_ref) => trait_ref, @@ -1485,12 +1506,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { assert_eq!(opt_self_ty, None); self.prohibit_generics(&path.segments); - let node_id = tcx.hir.as_local_node_id(did).unwrap(); - let item_id = tcx.hir.get_parent_node(node_id); - let item_def_id = tcx.hir.local_def_id(item_id); + let node_id = tcx.hir().as_local_node_id(did).unwrap(); + let item_id = tcx.hir().get_parent_node(node_id); + let item_def_id = tcx.hir().local_def_id(item_id); let generics = tcx.generics_of(item_def_id); - let index = generics.param_def_id_to_index[&tcx.hir.local_def_id(node_id)]; - tcx.mk_ty_param(index, tcx.hir.name(node_id).as_interned_str()) + let index = generics.param_def_id_to_index[&tcx.hir().local_def_id(node_id)]; + tcx.mk_ty_param(index, tcx.hir().name(node_id).as_interned_str()) } Def::SelfTy(_, Some(def_id)) => { // `Self` in impl (we know the concrete type) @@ -1579,7 +1600,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { self.def_to_ty(opt_self_ty, path, false) } hir::TyKind::Def(item_id, ref lifetimes) => { - let did = tcx.hir.local_def_id(item_id.id); + let did = tcx.hir().local_def_id(item_id.id); self.impl_trait_ty_to_ty(did, lifetimes) }, hir::TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => { @@ -1594,7 +1615,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { self.associated_path_def_to_ty(ast_ty.id, ast_ty.span, ty, def, segment).0 } hir::TyKind::Array(ref ty, ref length) => { - let length_def_id = tcx.hir.local_def_id(length.id); + let length_def_id = tcx.hir().local_def_id(length.id); let substs = Substs::identity_for_item(tcx, length_def_id); let length = ty::Const::unevaluated(tcx, length_def_id, substs, tcx.types.usize); let array_ty = tcx.mk_ty(ty::Array(self.ast_ty_to_ty(&ty), length)); @@ -1787,8 +1808,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { } } -/// Divides a list of general trait bounds into two groups: auto traits (e.g. Sync and Send) and the -/// remaining general trait bounds. +/// Divides a list of general trait bounds into two groups: auto traits (e.g., Sync and Send) and +/// the remaining general trait bounds. fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, trait_bounds: &'b [hir::PolyTraitRef]) -> (Vec, Vec<&'b hir::PolyTraitRef>) @@ -1828,7 +1849,7 @@ impl<'a, 'gcx, 'tcx> Bounds<'tcx> { pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, param_ty: Ty<'tcx>) -> Vec<(ty::Predicate<'tcx>, Span)> { - // If it could be sized, and is, add the sized predicate + // If it could be sized, and is, add the sized predicate. let sized_predicate = self.implicitly_sized.and_then(|span| { tcx.lang_items().sized_trait().map(|sized| { let trait_ref = ty::TraitRef { @@ -1841,8 +1862,8 @@ impl<'a, 'gcx, 'tcx> Bounds<'tcx> { sized_predicate.into_iter().chain( self.region_bounds.iter().map(|&(region_bound, span)| { - // account for the binder being introduced below; no need to shift `param_ty` - // because, at present at least, it can only refer to early-bound regions + // Account for the binder being introduced below; no need to shift `param_ty` + // because, at present at least, it can only refer to early-bound regions. let region_bound = ty::fold::shift_region(tcx, region_bound, 1); let outlives = ty::OutlivesPredicate(param_ty, region_bound); (ty::Binder::dummy(outlives).to_predicate(), span) diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index a477df6ae2d..87ee903cf43 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use check::{FnCtxt, Expectation, Diverges, Needs}; +use check::coercion::CoerceMany; use rustc::hir::{self, PatKind}; use rustc::hir::def::{Def, CtorKind}; use rustc::hir::pat_util::EnumerateAndAdjustIterator; @@ -15,17 +17,15 @@ use rustc::infer; use rustc::infer::type_variable::TypeVariableOrigin; use rustc::traits::ObligationCauseCode; use rustc::ty::{self, Ty, TypeFoldable}; -use check::{FnCtxt, Expectation, Diverges, Needs}; -use check::coercion::CoerceMany; -use util::nodemap::FxHashMap; - -use std::collections::hash_map::Entry::{Occupied, Vacant}; -use std::cmp; use syntax::ast; use syntax::source_map::Spanned; use syntax::ptr::P; use syntax::util::lev_distance::find_best_match_for_name; use syntax_pos::Span; +use util::nodemap::FxHashMap; + +use std::collections::hash_map::Entry::{Occupied, Vacant}; +use std::cmp; impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { /// The `is_arg` argument indicates whether this pattern is the @@ -545,7 +545,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); // the "discriminant type" (issue #23116). // // arielb1 [writes here in this comment thread][c] that there - // is certainly *some* potential danger, e.g. for an example + // is certainly *some* potential danger, e.g., for an example // like: // // [c]: https://github.com/rust-lang/rust/pull/43399#discussion_r130223956 @@ -729,10 +729,10 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); return self.tcx.types.err; }; - // Type check the path. + // Type-check the path. self.demand_eqtype(pat.span, expected, pat_ty); - // Type check subpatterns. + // Type-check subpatterns. if self.check_struct_pat_fields(pat_ty, pat.id, pat.span, variant, fields, etc, def_bm) { pat_ty } else { @@ -750,7 +750,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); span_err!(tcx.sess, pat.span, E0533, "expected unit struct/variant or constant, found {} `{}`", def.kind_name(), - hir::print::to_string(&tcx.hir, |s| s.print_qpath(qpath, false))); + hir::print::to_string(tcx.hir(), |s| s.print_qpath(qpath, false))); }; // Resolve the path and check the definition for errors. @@ -771,7 +771,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); _ => bug!("unexpected pattern definition: {:?}", def) } - // Type check the path. + // Type-check the path. let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id).0; self.demand_suptype(pat.span, expected, pat_ty); pat_ty @@ -794,7 +794,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); let report_unexpected_def = |def: Def| { let msg = format!("expected tuple struct/variant, found {} `{}`", def.kind_name(), - hir::print::to_string(&tcx.hir, |s| s.print_qpath(qpath, false))); + hir::print::to_string(tcx.hir(), |s| s.print_qpath(qpath, false))); struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg) .span_label(pat.span, "not a tuple variant or struct").emit(); on_error(); @@ -808,7 +808,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); return self.tcx.types.err; } - // Type check the path. + // Type-check the path. let (pat_ty, def) = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id); if !pat_ty.is_fn() { report_unexpected_def(def); @@ -838,7 +838,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); self.demand_eqtype(pat.span, expected, pat_ty); - // Type check subpatterns. + // Type-check subpatterns. if subpats.len() == variant.fields.len() || subpats.len() < variant.fields.len() && ddpos.is_some() { let substs = match pat_ty.sty { diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs index 2cd2bb50648..d240f45c7d9 100644 --- a/src/librustc_typeck/check/autoderef.rs +++ b/src/librustc_typeck/check/autoderef.rs @@ -8,20 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use astconv::AstConv; - use super::{FnCtxt, PlaceOp, Needs}; use super::method::MethodCallee; -use rustc::infer::InferOk; +use rustc::infer::{InferCtxt, InferOk}; use rustc::session::DiagnosticMessageId; -use rustc::traits; -use rustc::ty::{self, Ty, TraitRef}; +use rustc::traits::{self, TraitEngine}; +use rustc::ty::{self, Ty, TyCtxt, TraitRef}; use rustc::ty::{ToPredicate, TypeFoldable}; use rustc::ty::adjustment::{Adjustment, Adjust, OverloadedDeref}; use syntax_pos::Span; -use syntax::ast::Ident; +use syntax::ast::{self, Ident}; use std::iter; @@ -32,20 +30,24 @@ enum AutoderefKind { } pub struct Autoderef<'a, 'gcx: 'tcx, 'tcx: 'a> { - fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, + infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + body_id: ast::NodeId, + param_env: ty::ParamEnv<'tcx>, steps: Vec<(Ty<'tcx>, AutoderefKind)>, cur_ty: Ty<'tcx>, obligations: Vec>, at_start: bool, include_raw_pointers: bool, span: Span, + silence_errors: bool, + reached_recursion_limit: bool } impl<'a, 'gcx, 'tcx> Iterator for Autoderef<'a, 'gcx, 'tcx> { type Item = (Ty<'tcx>, usize); fn next(&mut self) -> Option { - let tcx = self.fcx.tcx; + let tcx = self.infcx.tcx; debug!("autoderef: steps={:?}, cur_ty={:?}", self.steps, @@ -57,24 +59,10 @@ impl<'a, 'gcx, 'tcx> Iterator for Autoderef<'a, 'gcx, 'tcx> { } if self.steps.len() >= *tcx.sess.recursion_limit.get() { - // We've reached the recursion limit, error gracefully. - let suggested_limit = *tcx.sess.recursion_limit.get() * 2; - let msg = format!("reached the recursion limit while auto-dereferencing `{:?}`", - self.cur_ty); - let error_id = (DiagnosticMessageId::ErrorId(55), Some(self.span), msg); - let fresh = tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id); - if fresh { - struct_span_err!(tcx.sess, - self.span, - E0055, - "reached the recursion limit while auto-dereferencing `{:?}`", - self.cur_ty) - .span_label(self.span, "deref recursion limit reached") - .help(&format!( - "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate", - suggested_limit)) - .emit(); + if !self.silence_errors { + report_autoderef_recursion_limit_error(tcx, self.span, self.cur_ty); } + self.reached_recursion_limit = true; return None; } @@ -107,10 +95,32 @@ impl<'a, 'gcx, 'tcx> Iterator for Autoderef<'a, 'gcx, 'tcx> { } impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> { + pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + body_id: ast::NodeId, + span: Span, + base_ty: Ty<'tcx>) + -> Autoderef<'a, 'gcx, 'tcx> + { + Autoderef { + infcx, + body_id, + param_env, + steps: vec![], + cur_ty: infcx.resolve_type_vars_if_possible(&base_ty), + obligations: vec![], + at_start: true, + include_raw_pointers: false, + silence_errors: false, + reached_recursion_limit: false, + span, + } + } + fn overloaded_deref_ty(&mut self, ty: Ty<'tcx>) -> Option> { debug!("overloaded_deref_ty({:?})", ty); - let tcx = self.fcx.tcx(); + let tcx = self.infcx.tcx; // let trait_ref = TraitRef { @@ -118,43 +128,52 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> { substs: tcx.mk_substs_trait(self.cur_ty, &[]), }; - let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id); + let cause = traits::ObligationCause::misc(self.span, self.body_id); let obligation = traits::Obligation::new(cause.clone(), - self.fcx.param_env, + self.param_env, trait_ref.to_predicate()); - if !self.fcx.predicate_may_hold(&obligation) { + if !self.infcx.predicate_may_hold(&obligation) { debug!("overloaded_deref_ty: cannot match obligation"); return None; } - let mut selcx = traits::SelectionContext::new(self.fcx); - let normalized_ty = traits::normalize_projection_type(&mut selcx, - self.fcx.param_env, - ty::ProjectionTy::from_ref_and_name( - tcx, - trait_ref, - Ident::from_str("Target"), - ), - cause, - 0, - &mut self.obligations); + let mut fulfillcx = traits::FulfillmentContext::new_in_snapshot(); + let normalized_ty = fulfillcx.normalize_projection_type( + &self.infcx, + self.param_env, + ty::ProjectionTy::from_ref_and_name( + tcx, + trait_ref, + Ident::from_str("Target"), + ), + cause); + if let Err(e) = fulfillcx.select_where_possible(&self.infcx) { + // This shouldn't happen, except for evaluate/fulfill mismatches, + // but that's not a reason for an ICE (`predicate_may_hold` is conservative + // by design). + debug!("overloaded_deref_ty: encountered errors {:?} while fulfilling", + e); + return None; + } + let obligations = fulfillcx.pending_obligations(); + debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", + ty, normalized_ty, obligations); + self.obligations.extend(obligations); - debug!("overloaded_deref_ty({:?}) = {:?}", ty, normalized_ty); - - Some(self.fcx.resolve_type_vars_if_possible(&normalized_ty)) + Some(self.infcx.resolve_type_vars_if_possible(&normalized_ty)) } /// Returns the final type, generating an error if it is an /// unresolved inference variable. - pub fn unambiguous_final_ty(&self) -> Ty<'tcx> { - self.fcx.structurally_resolved_type(self.span, self.cur_ty) + pub fn unambiguous_final_ty(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> { + fcx.structurally_resolved_type(self.span, self.cur_ty) } /// Returns the final type we ended up with, which may well be an /// inference variable (we will resolve it first, if possible). pub fn maybe_ambiguous_final_ty(&self) -> Ty<'tcx> { - self.fcx.resolve_type_vars_if_possible(&self.cur_ty) + self.infcx.resolve_type_vars_if_possible(&self.cur_ty) } pub fn step_count(&self) -> usize { @@ -162,19 +181,19 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> { } /// Returns the adjustment steps. - pub fn adjust_steps(&self, needs: Needs) + pub fn adjust_steps(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, needs: Needs) -> Vec> { - self.fcx.register_infer_ok_obligations(self.adjust_steps_as_infer_ok(needs)) + fcx.register_infer_ok_obligations(self.adjust_steps_as_infer_ok(fcx, needs)) } - pub fn adjust_steps_as_infer_ok(&self, needs: Needs) + pub fn adjust_steps_as_infer_ok(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, needs: Needs) -> InferOk<'tcx, Vec>> { let mut obligations = vec![]; let targets = self.steps.iter().skip(1).map(|&(ty, _)| ty) .chain(iter::once(self.cur_ty)); let steps: Vec<_> = self.steps.iter().map(|&(source, kind)| { if let AutoderefKind::Overloaded = kind { - self.fcx.try_overloaded_deref(self.span, source, needs) + fcx.try_overloaded_deref(self.span, source, needs) .and_then(|InferOk { value: method, obligations: o }| { obligations.extend(o); if let ty::Ref(region, _, mutbl) = method.sig.output().sty { @@ -203,7 +222,7 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> { } /// also dereference through raw pointer types - /// e.g. assuming ptr_to_Foo is the type `*const Foo` + /// e.g., assuming ptr_to_Foo is the type `*const Foo` /// fcx.autoderef(span, ptr_to_Foo) => [*const Foo] /// fcx.autoderef(span, ptr_to_Foo).include_raw_ptrs() => [*const Foo, Foo] pub fn include_raw_pointers(mut self) -> Self { @@ -211,8 +230,16 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> { self } - pub fn finalize(self) { - let fcx = self.fcx; + pub fn silence_errors(mut self) -> Self { + self.silence_errors = true; + self + } + + pub fn reached_recursion_limit(&self) -> bool { + self.reached_recursion_limit + } + + pub fn finalize(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) { fcx.register_predicates(self.into_obligations()); } @@ -221,17 +248,32 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> { } } +pub fn report_autoderef_recursion_limit_error<'a, 'gcx, 'tcx>( + tcx: TyCtxt<'a, 'gcx, 'tcx>, span: Span, ty: Ty<'tcx>) +{ + // We've reached the recursion limit, error gracefully. + let suggested_limit = *tcx.sess.recursion_limit.get() * 2; + let msg = format!("reached the recursion limit while auto-dereferencing `{:?}`", + ty); + let error_id = (DiagnosticMessageId::ErrorId(55), Some(span), msg); + let fresh = tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id); + if fresh { + struct_span_err!(tcx.sess, + span, + E0055, + "reached the recursion limit while auto-dereferencing `{:?}`", + ty) + .span_label(span, "deref recursion limit reached") + .help(&format!( + "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate", + suggested_limit)) + .emit(); + } +} + impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn autoderef(&'a self, span: Span, base_ty: Ty<'tcx>) -> Autoderef<'a, 'gcx, 'tcx> { - Autoderef { - fcx: self, - steps: vec![], - cur_ty: self.resolve_type_vars_if_possible(&base_ty), - obligations: vec![], - at_start: true, - include_raw_pointers: false, - span, - } + Autoderef::new(self, self.param_env, self.body_id, span, base_ty) } pub fn try_overloaded_deref(&self, diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 7a71cf57a2f..0ec181e59d0 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -38,7 +38,7 @@ pub fn check_legal_trait_for_method_call(tcx: TyCtxt, span: Span, trait_id: DefI enum CallStep<'tcx> { Builtin(Ty<'tcx>), DeferredClosure(ty::FnSig<'tcx>), - /// e.g. enum variant constructors + /// e.g., enum variant constructors Overloaded(MethodCallee<'tcx>), } @@ -57,7 +57,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { while result.is_none() && autoderef.next().is_some() { result = self.try_overloaded_call_step(call_expr, callee_expr, &autoderef); } - autoderef.finalize(); + autoderef.finalize(self); let output = match result { None => { @@ -89,7 +89,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { callee_expr: &'gcx hir::Expr, autoderef: &Autoderef<'a, 'gcx, 'tcx>) -> Option> { - let adjusted_ty = autoderef.unambiguous_final_ty(); + let adjusted_ty = autoderef.unambiguous_final_ty(self); debug!("try_overloaded_call_step(call_expr={:?}, adjusted_ty={:?})", call_expr, adjusted_ty); @@ -97,7 +97,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // If the callee is a bare function or a closure, then we're all set. match adjusted_ty.sty { ty::FnDef(..) | ty::FnPtr(_) => { - let adjustments = autoderef.adjust_steps(Needs::None); + let adjustments = autoderef.adjust_steps(self, Needs::None); self.apply_adjustments(callee_expr, adjustments); return Some(CallStep::Builtin(adjusted_ty)); } @@ -115,7 +115,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { infer::FnCall, &closure_ty ).0; - let adjustments = autoderef.adjust_steps(Needs::None); + let adjustments = autoderef.adjust_steps(self, Needs::None); self.record_deferred_call_resolution(def_id, DeferredCallResolution { call_expr, callee_expr, @@ -145,7 +145,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } self.try_overloaded_call_traits(call_expr, adjusted_ty).map(|(autoref, method)| { - let mut adjustments = autoderef.adjust_steps(Needs::None); + let mut adjustments = autoderef.adjust_steps(self, Needs::None); adjustments.extend(autoref); self.apply_adjustments(callee_expr, adjustments); CallStep::Overloaded(method) @@ -206,7 +206,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { -> Ty<'tcx> { let (fn_sig, def_span) = match callee_ty.sty { ty::FnDef(def_id, _) => { - (callee_ty.fn_sig(self.tcx), self.tcx.hir.span_if_local(def_id)) + (callee_ty.fn_sig(self.tcx), self.tcx.hir().span_if_local(def_id)) } ty::FnPtr(sig) => (sig, None), ref t => { @@ -214,7 +214,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let &ty::Adt(adt_def, ..) = t { if adt_def.is_enum() { if let hir::ExprKind::Call(ref expr, _) = call_expr.node { - unit_variant = Some(self.tcx.hir.node_to_pretty_string(expr.id)) + unit_variant = Some(self.tcx.hir().node_to_pretty_string(expr.id)) } } } @@ -278,9 +278,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let def_span = match def { Def::Err => None, Def::Local(id) | Def::Upvar(id, ..) => { - Some(self.tcx.hir.span(id)) + Some(self.tcx.hir().span(id)) } - _ => self.tcx.hir.span_if_local(def.def_id()) + _ => def.opt_def_id().and_then(|did| self.tcx.hir().span_if_local(did)), }; if let Some(span) = def_span { let label = match (unit_variant, inner_callee_path) { diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index c35aee7883f..51271f0f351 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -27,7 +27,7 @@ //! //! where `&.T` and `*T` are references of either mutability, //! and where pointer_kind(`T`) is the kind of the unsize info -//! in `T` - the vtable for a trait definition (e.g. `fmt::Display` or +//! in `T` - the vtable for a trait definition (e.g., `fmt::Display` or //! `Iterator`, not `Iterator`) or a length (or `()` if `T: Sized`). //! //! Note that lengths are not adjusted when casting raw slices - diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 10ac2448d00..f599a2b2ece 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -20,7 +20,7 @@ use rustc::infer::LateBoundRegionConversionTime; use rustc::infer::type_variable::TypeVariableOrigin; use rustc::traits::Obligation; use rustc::traits::error_reporting::ArgKind; -use rustc::ty::{self, ToPolyTraitRef, Ty, GenericParamDefKind}; +use rustc::ty::{self, Ty, GenericParamDefKind}; use rustc::ty::fold::TypeFoldable; use rustc::ty::subst::Substs; use std::cmp; @@ -64,7 +64,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Some(ty) => self.deduce_expectations_from_expected_type(ty), None => (None, None), }; - let body = self.tcx.hir.body(body_id); + let body = self.tcx.hir().body(body_id); self.check_closure(expr, expected_kind, decl, body, gen, expected_sig) } @@ -82,7 +82,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { opt_kind, expected_sig ); - let expr_def_id = self.tcx.hir.local_def_id(expr.id); + let expr_def_id = self.tcx.hir().local_def_id(expr.id); let ClosureSignatures { bound_sig, @@ -219,13 +219,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { &self, expected_vid: ty::TyVid, ) -> (Option>, Option) { - let fulfillment_cx = self.fulfillment_cx.borrow(); - // Here `expected_ty` is known to be a type inference variable. - - let expected_sig = fulfillment_cx - .pending_obligations() - .iter() - .filter_map(|obligation| { + let expected_sig = self.obligations_for_self_ty(expected_vid) + .find_map(|(_, obligation)| { debug!( "deduce_expectations_from_obligations: obligation.predicate={:?}", obligation.predicate @@ -234,52 +229,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let ty::Predicate::Projection(ref proj_predicate) = obligation.predicate { // Given a Projection predicate, we can potentially infer // the complete signature. - let trait_ref = proj_predicate.to_poly_trait_ref(self.tcx); - self.self_type_matches_expected_vid(trait_ref, expected_vid) - .and_then(|_| { - self.deduce_sig_from_projection( - Some(obligation.cause.span), - proj_predicate - ) - }) + self.deduce_sig_from_projection( + Some(obligation.cause.span), + proj_predicate + ) } else { None } - }) - .next(); + }); // Even if we can't infer the full signature, we may be able to // infer the kind. This can occur if there is a trait-reference // like `F : Fn`. Note that due to subtyping we could encounter // many viable options, so pick the most restrictive. - let expected_kind = fulfillment_cx - .pending_obligations() - .iter() - .filter_map(|obligation| { - let opt_trait_ref = match obligation.predicate { - ty::Predicate::Projection(ref data) => Some(data.to_poly_trait_ref(self.tcx)), - ty::Predicate::Trait(ref data) => Some(data.to_poly_trait_ref()), - ty::Predicate::Subtype(..) => None, - ty::Predicate::RegionOutlives(..) => None, - ty::Predicate::TypeOutlives(..) => None, - ty::Predicate::WellFormed(..) => None, - ty::Predicate::ObjectSafe(..) => None, - ty::Predicate::ConstEvaluatable(..) => None, - - // NB: This predicate is created by breaking down a - // `ClosureType: FnFoo()` predicate, where - // `ClosureType` represents some `Closure`. It can't - // possibly be referring to the current closure, - // because we haven't produced the `Closure` for - // this closure yet; this is exactly why the other - // code is looking for a self type of a unresolved - // inference variable. - ty::Predicate::ClosureKind(..) => None, - }; - opt_trait_ref - .and_then(|tr| self.self_type_matches_expected_vid(tr, expected_vid)) - .and_then(|tr| self.tcx.lang_items().fn_trait_kind(tr.def_id())) - }) + let expected_kind = self.obligations_for_self_ty(expected_vid) + .filter_map(|(tr, _)| self.tcx.lang_items().fn_trait_kind(tr.def_id())) .fold(None, |best, cur| { Some(best.map_or(cur, |best| cmp::min(best, cur))) }); @@ -339,22 +303,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Some(ExpectedSig { cause_span, sig }) } - fn self_type_matches_expected_vid( - &self, - trait_ref: ty::PolyTraitRef<'tcx>, - expected_vid: ty::TyVid, - ) -> Option> { - let self_ty = self.shallow_resolve(trait_ref.self_ty()); - debug!( - "self_type_matches_expected_vid(trait_ref={:?}, self_ty={:?})", - trait_ref, self_ty - ); - match self_ty.sty { - ty::Infer(ty::TyVar(v)) if expected_vid == v => Some(trait_ref), - _ => None, - } - } - fn sig_of_closure( &self, expr_def_id: DefId, @@ -496,7 +444,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { body: &hir::Body, expected_sig: ExpectedSig<'tcx>, ) -> ClosureSignatures<'tcx> { - let expr_map_node = self.tcx.hir.get_if_local(expr_def_id).unwrap(); + let expr_map_node = self.tcx.hir().get_if_local(expr_def_id).unwrap(); let expected_args: Vec<_> = expected_sig .sig .inputs() diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 3bdd038bff1..9a1f9784192 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -336,7 +336,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { // the decision to region inference (and regionck, which will add // some more edges to this variable). However, this can wind up // creating a crippling number of variables in some cases -- - // e.g. #32278 -- so we optimize one particular case [3]. + // e.g., #32278 -- so we optimize one particular case [3]. // Let me try to explain with some examples: // - The "running example" above represents the simple case, // where we have one `&` reference at the outer level and @@ -419,7 +419,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { let needs = Needs::maybe_mut_place(mt_b.mutbl); let InferOk { value: mut adjustments, obligations: o } - = autoderef.adjust_steps_as_infer_ok(needs); + = autoderef.adjust_steps_as_infer_ok(self, needs); obligations.extend(o); obligations.extend(autoderef.into_obligations()); @@ -579,7 +579,33 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { }; match selcx.select(&obligation.with(trait_ref)) { // Uncertain or unimplemented. - Ok(None) | + Ok(None) => { + if trait_ref.def_id() == unsize_did { + let trait_ref = self.resolve_type_vars_if_possible(&trait_ref); + let self_ty = trait_ref.skip_binder().self_ty(); + let unsize_ty = trait_ref.skip_binder().input_types().nth(1).unwrap(); + debug!("coerce_unsized: ambiguous unsize case for {:?}", trait_ref); + match (&self_ty.sty, &unsize_ty.sty) { + (ty::Infer(ty::TyVar(v)), + ty::Dynamic(..)) if self.type_var_is_sized(*v) => { + debug!("coerce_unsized: have sized infer {:?}", v); + coercion.obligations.push(obligation); + // `$0: Unsize` where we know that `$0: Sized`, try going + // for unsizing. + } + _ => { + // Some other case for `$0: Unsize`. Note that we + // hit this case even if `Something` is a sized type, so just + // don't do the coercion. + debug!("coerce_unsized: ambiguous unsize"); + return Err(TypeError::Mismatch); + } + } + } else { + debug!("coerce_unsized: early return - ambiguous"); + return Err(TypeError::Mismatch); + } + } Err(traits::Unimplemented) => { debug!("coerce_unsized: early return - can't prove obligation"); return Err(TypeError::Mismatch); @@ -696,7 +722,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { let b = self.shallow_resolve(b); - let node_id_a = self.tcx.hir.as_local_node_id(def_id_a).unwrap(); + let node_id_a = self.tcx.hir().as_local_node_id(def_id_a).unwrap(); match b.sty { ty::FnPtr(_) if self.tcx.with_freevars(node_id_a, |v| v.is_empty()) => { // We coerce the closure, which has fn type @@ -809,7 +835,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Special-case that coercion alone cannot handle: // Two function item types of differing IDs or Substs. if let (&ty::FnDef(..), &ty::FnDef(..)) = (&prev_ty.sty, &new_ty.sty) { - // Don't reify if the function types have a LUB, i.e. they + // Don't reify if the function types have a LUB, i.e., they // are the same function and their parameters have a LUB. let lub_ty = self.commit_if_ok(|_| { self.at(cause, self.param_env) diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index e30ebe07e54..984f1ca65ce 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -93,7 +93,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // This node-id should be used for the `body_id` field on each // `ObligationCause` (and the `FnCtxt`). This is what // `regionck_item` expects. - let impl_m_node_id = tcx.hir.as_local_node_id(impl_m.def_id).unwrap(); + let impl_m_node_id = tcx.hir().as_local_node_id(impl_m.def_id).unwrap(); let cause = ObligationCause { span: impl_m_span, @@ -391,7 +391,7 @@ fn check_region_bounds_on_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // the moment, give a kind of vague error message. if trait_params != impl_params { let def_span = tcx.sess.source_map().def_span(span); - let span = tcx.hir.get_generics_span(impl_m.def_id).unwrap_or(def_span); + let span = tcx.hir().get_generics_span(impl_m.def_id).unwrap_or(def_span); let mut err = struct_span_err!( tcx.sess, span, @@ -400,9 +400,9 @@ fn check_region_bounds_on_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_m.ident, ); err.span_label(span, "lifetimes do not match method in trait"); - if let Some(sp) = tcx.hir.span_if_local(trait_m.def_id) { + if let Some(sp) = tcx.hir().span_if_local(trait_m.def_id) { let def_sp = tcx.sess.source_map().def_span(sp); - let sp = tcx.hir.get_generics_span(trait_m.def_id).unwrap_or(def_sp); + let sp = tcx.hir().get_generics_span(trait_m.def_id).unwrap_or(def_sp); err.span_label(sp, "lifetimes in impl do not match this method in trait"); } err.emit(); @@ -422,8 +422,8 @@ fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a trait_sig: ty::FnSig<'tcx>) -> (Span, Option) { let tcx = infcx.tcx; - let impl_m_node_id = tcx.hir.as_local_node_id(impl_m.def_id).unwrap(); - let (impl_m_output, impl_m_iter) = match tcx.hir.expect_impl_item(impl_m_node_id).node { + let impl_m_node_id = tcx.hir().as_local_node_id(impl_m.def_id).unwrap(); + let (impl_m_output, impl_m_iter) = match tcx.hir().expect_impl_item(impl_m_node_id).node { ImplItemKind::Method(ref impl_m_sig, _) => { (&impl_m_sig.decl.output, impl_m_sig.decl.inputs.iter()) } @@ -432,8 +432,8 @@ fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a match *terr { TypeError::Mutability => { - if let Some(trait_m_node_id) = tcx.hir.as_local_node_id(trait_m.def_id) { - let trait_m_iter = match tcx.hir.expect_trait_item(trait_m_node_id).node { + if let Some(trait_m_node_id) = tcx.hir().as_local_node_id(trait_m.def_id) { + let trait_m_iter = match tcx.hir().expect_trait_item(trait_m_node_id).node { TraitItemKind::Method(ref trait_m_sig, _) => { trait_m_sig.decl.inputs.iter() } @@ -451,15 +451,15 @@ fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a }).map(|(ref impl_arg, ref trait_arg)| { (impl_arg.span, Some(trait_arg.span)) }) - .unwrap_or_else(|| (cause.span(&tcx), tcx.hir.span_if_local(trait_m.def_id))) + .unwrap_or_else(|| (cause.span(&tcx), tcx.hir().span_if_local(trait_m.def_id))) } else { - (cause.span(&tcx), tcx.hir.span_if_local(trait_m.def_id)) + (cause.span(&tcx), tcx.hir().span_if_local(trait_m.def_id)) } } TypeError::Sorts(ExpectedFound { .. }) => { - if let Some(trait_m_node_id) = tcx.hir.as_local_node_id(trait_m.def_id) { + if let Some(trait_m_node_id) = tcx.hir().as_local_node_id(trait_m.def_id) { let (trait_m_output, trait_m_iter) = - match tcx.hir.expect_trait_item(trait_m_node_id).node { + match tcx.hir().expect_trait_item(trait_m_node_id).node { TraitItemKind::Method(ref trait_m_sig, _) => { (&trait_m_sig.decl.output, trait_m_sig.decl.inputs.iter()) } @@ -486,14 +486,14 @@ fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a { (impl_m_output.span(), Some(trait_m_output.span())) } else { - (cause.span(&tcx), tcx.hir.span_if_local(trait_m.def_id)) + (cause.span(&tcx), tcx.hir().span_if_local(trait_m.def_id)) } ) } else { - (cause.span(&tcx), tcx.hir.span_if_local(trait_m.def_id)) + (cause.span(&tcx), tcx.hir().span_if_local(trait_m.def_id)) } } - _ => (cause.span(&tcx), tcx.hir.span_if_local(trait_m.def_id)), + _ => (cause.span(&tcx), tcx.hir().span_if_local(trait_m.def_id)), } } @@ -548,7 +548,7 @@ fn compare_self_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_m.ident, self_descr); err.span_label(impl_m_span, format!("`{}` used in impl", self_descr)); - if let Some(span) = tcx.hir.span_if_local(trait_m.def_id) { + if let Some(span) = tcx.hir().span_if_local(trait_m.def_id) { err.span_label(span, format!("trait method declared without `{}`", self_descr)); } else { err.note_trait_signature(trait_m.ident.to_string(), @@ -568,7 +568,7 @@ fn compare_self_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_m.ident, self_descr); err.span_label(impl_m_span, format!("expected `{}` in impl", self_descr)); - if let Some(span) = tcx.hir.span_if_local(trait_m.def_id) { + if let Some(span) = tcx.hir().span_if_local(trait_m.def_id) { err.span_label(span, format!("`{}` used in trait", self_descr)); } else { err.note_trait_signature(trait_m.ident.to_string(), @@ -594,8 +594,8 @@ fn compare_number_of_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let num_trait_m_type_params = trait_m_generics.own_counts().types; if num_impl_m_type_params != num_trait_m_type_params { - let impl_m_node_id = tcx.hir.as_local_node_id(impl_m.def_id).unwrap(); - let impl_m_item = tcx.hir.expect_impl_item(impl_m_node_id); + let impl_m_node_id = tcx.hir().as_local_node_id(impl_m.def_id).unwrap(); + let impl_m_item = tcx.hir().expect_impl_item(impl_m_node_id); let span = if impl_m_item.generics.params.is_empty() || impl_m_item.generics.span.is_dummy() // impl Trait in argument position (#55374) { @@ -644,16 +644,23 @@ fn compare_number_of_method_arguments<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let trait_number_args = trait_m_fty.inputs().skip_binder().len(); let impl_number_args = impl_m_fty.inputs().skip_binder().len(); if trait_number_args != impl_number_args { - let trait_m_node_id = tcx.hir.as_local_node_id(trait_m.def_id); + let trait_m_node_id = tcx.hir().as_local_node_id(trait_m.def_id); let trait_span = if let Some(trait_id) = trait_m_node_id { - match tcx.hir.expect_trait_item(trait_id).node { + match tcx.hir().expect_trait_item(trait_id).node { TraitItemKind::Method(ref trait_m_sig, _) => { - if let Some(arg) = trait_m_sig.decl.inputs.get(if trait_number_args > 0 { + let pos = if trait_number_args > 0 { trait_number_args - 1 } else { 0 - }) { - Some(arg.span) + }; + if let Some(arg) = trait_m_sig.decl.inputs.get(pos) { + Some(if pos == 0 { + arg.span + } else { + Span::new(trait_m_sig.decl.inputs[0].span.lo(), + arg.span.hi(), + arg.span.ctxt()) + }) } else { trait_item_span } @@ -663,15 +670,22 @@ fn compare_number_of_method_arguments<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } else { trait_item_span }; - let impl_m_node_id = tcx.hir.as_local_node_id(impl_m.def_id).unwrap(); - let impl_span = match tcx.hir.expect_impl_item(impl_m_node_id).node { + let impl_m_node_id = tcx.hir().as_local_node_id(impl_m.def_id).unwrap(); + let impl_span = match tcx.hir().expect_impl_item(impl_m_node_id).node { ImplItemKind::Method(ref impl_m_sig, _) => { - if let Some(arg) = impl_m_sig.decl.inputs.get(if impl_number_args > 0 { + let pos = if impl_number_args > 0 { impl_number_args - 1 } else { 0 - }) { - arg.span + }; + if let Some(arg) = impl_m_sig.decl.inputs.get(pos) { + if pos == 0 { + arg.span + } else { + Span::new(impl_m_sig.decl.inputs[0].span.lo(), + arg.span.hi(), + arg.span.ctxt()) + } } else { impl_m_span } @@ -729,8 +743,8 @@ fn compare_synthetic_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, in impl_m_type_params.zip(trait_m_type_params) { if impl_synthetic != trait_synthetic { - let impl_node_id = tcx.hir.as_local_node_id(impl_def_id).unwrap(); - let impl_span = tcx.hir.span(impl_node_id); + let impl_node_id = tcx.hir().as_local_node_id(impl_def_id).unwrap(); + let impl_span = tcx.hir().span(impl_node_id); let trait_span = tcx.def_span(trait_def_id); let mut err = struct_span_err!(tcx.sess, impl_span, @@ -752,11 +766,11 @@ fn compare_synthetic_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, .source_map() .span_to_snippet(trait_span) .ok()?; - let trait_m = tcx.hir.as_local_node_id(trait_m.def_id)?; - let trait_m = tcx.hir.trait_item(hir::TraitItemId { node_id: trait_m }); + let trait_m = tcx.hir().as_local_node_id(trait_m.def_id)?; + let trait_m = tcx.hir().trait_item(hir::TraitItemId { node_id: trait_m }); - let impl_m = tcx.hir.as_local_node_id(impl_m.def_id)?; - let impl_m = tcx.hir.impl_item(hir::ImplItemId { node_id: impl_m }); + let impl_m = tcx.hir().as_local_node_id(impl_m.def_id)?; + let impl_m = tcx.hir().impl_item(hir::ImplItemId { node_id: impl_m }); // in case there are no generics, take the spot between the function name // and the opening paren of the argument list @@ -797,8 +811,8 @@ fn compare_synthetic_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, (None, Some(hir::SyntheticTyParamKind::ImplTrait)) => { err.span_label(impl_span, "expected `impl Trait`, found generic parameter"); (|| { - let impl_m = tcx.hir.as_local_node_id(impl_m.def_id)?; - let impl_m = tcx.hir.impl_item(hir::ImplItemId { node_id: impl_m }); + let impl_m = tcx.hir().as_local_node_id(impl_m.def_id)?; + let impl_m = tcx.hir().impl_item(hir::ImplItemId { node_id: impl_m }); let input_tys = match impl_m.node { hir::ImplItemKind::Method(ref sig, _) => &sig.decl.inputs, _ => unreachable!(), @@ -895,7 +909,7 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Create a parameter environment that represents the implementation's // method. - let impl_c_node_id = tcx.hir.as_local_node_id(impl_c.def_id).unwrap(); + let impl_c_node_id = tcx.hir().as_local_node_id(impl_c.def_id).unwrap(); // Compute placeholder form of impl and trait const tys. let impl_ty = tcx.type_of(impl_c.def_id); @@ -927,7 +941,7 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_ty); // Locate the Span containing just the type of the offending impl - match tcx.hir.expect_impl_item(impl_c_node_id).node { + match tcx.hir().expect_impl_item(impl_c_node_id).node { ImplItemKind::Const(ref ty, _) => cause.span = ty.span, _ => bug!("{:?} is not a impl const", impl_c), } @@ -939,10 +953,10 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait", trait_c.ident); - let trait_c_node_id = tcx.hir.as_local_node_id(trait_c.def_id); + let trait_c_node_id = tcx.hir().as_local_node_id(trait_c.def_id); let trait_c_span = trait_c_node_id.map(|trait_c_node_id| { // Add a label to the Span containing just the type of the const - match tcx.hir.expect_trait_item(trait_c_node_id).node { + match tcx.hir().expect_trait_item(trait_c_node_id).node { TraitItemKind::Const(ref ty, _) => ty.span, _ => bug!("{:?} is not a trait const", trait_c), } diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 0a196834cb4..db4b68611c5 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -91,7 +91,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Checks that the type of `expr` can be coerced to `expected`. // - // NB: This code relies on `self.diverges` to be accurate. In + // N.B., this code relies on `self.diverges` to be accurate. In // particular, assignments to `!` will be permitted if the // diverges flag is currently "always". pub fn demand_coerce_diag(&self, @@ -123,7 +123,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let sole_field_ty = sole_field.ty(self.tcx, substs); if self.can_coerce(expr_ty, sole_field_ty) { let variant_path = self.tcx.item_path_str(variant.did); - Some(variant_path.trim_left_matches("std::prelude::v1::").to_string()) + Some(variant_path.trim_start_matches("std::prelude::v1::").to_string()) } else { None } @@ -203,17 +203,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn can_use_as_ref(&self, expr: &hir::Expr) -> Option<(Span, &'static str, String)> { if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = expr.node { if let hir::def::Def::Local(id) = path.def { - let parent = self.tcx.hir.get_parent_node(id); + let parent = self.tcx.hir().get_parent_node(id); if let Some(Node::Expr(hir::Expr { id, node: hir::ExprKind::Closure(_, decl, ..), .. - })) = self.tcx.hir.find(parent) { - let parent = self.tcx.hir.get_parent_node(*id); + })) = self.tcx.hir().find(parent) { + let parent = self.tcx.hir().get_parent_node(*id); if let (Some(Node::Expr(hir::Expr { node: hir::ExprKind::MethodCall(path, span, expr), .. - })), 1) = (self.tcx.hir.find(parent), decl.inputs.len()) { + })), 1) = (self.tcx.hir().find(parent), decl.inputs.len()) { let self_ty = self.tables.borrow().node_id_to_type(expr[0].hir_id); let self_ty = format!("{:?}", self_ty); let name = path.ident.as_str(); @@ -450,8 +450,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { checked_ty: Ty<'tcx>, expected_ty: Ty<'tcx>) -> bool { - let parent_id = self.tcx.hir.get_parent_node(expr.id); - if let Some(parent) = self.tcx.hir.find(parent_id) { + let parent_id = self.tcx.hir().get_parent_node(expr.id); + if let Some(parent) = self.tcx.hir().find(parent_id) { // Shouldn't suggest `.into()` on `const`s. if let Node::Item(Item { node: ItemKind::Const(_, _), .. }) = parent { // FIXME(estebank): modify once we decide to suggest `as` casts @@ -519,7 +519,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let suffix_suggestion = format!( "{}{}{}{}", if needs_paren { "(" } else { "" }, - src.trim_right_matches(&checked_ty.to_string()), + src.trim_end_matches(&checked_ty.to_string()), expected_ty, if needs_paren { ")" } else { "" }, ); diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index b8544177bbb..f59bc2d0c2d 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -32,7 +32,7 @@ use syntax_pos::Span; /// coherence), /// /// 2. The generic region/type parameters of the impl's self-type must -/// all be parameters of the Drop impl itself (i.e. no +/// all be parameters of the Drop impl itself (i.e., no /// specialization like `impl Drop for Foo`), and, /// /// 3. Any bounds on the generic parameters must be reflected in the @@ -80,7 +80,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>( drop_impl_ty: Ty<'tcx>, self_type_did: DefId, ) -> Result<(), ErrorReported> { - let drop_impl_node_id = tcx.hir.as_local_node_id(drop_impl_did).unwrap(); + let drop_impl_node_id = tcx.hir().as_local_node_id(drop_impl_did).unwrap(); // check that the impl type can be made to match the trait type. @@ -180,7 +180,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'a, 'tcx>( // // self_to_impl_substs = {'c => 'z, 'b => 'y, 'a => 'x} // - // Applying this to the predicates (i.e. assumptions) provided by the item + // Applying this to the predicates (i.e., assumptions) provided by the item // definition yields the instantiated assumptions: // // ['y : 'z] @@ -194,7 +194,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'a, 'tcx>( // absent. So we report an error that the Drop impl injected a // predicate that is not present on the struct definition. - let self_type_node_id = tcx.hir.as_local_node_id(self_type_did).unwrap(); + let self_type_node_id = tcx.hir().as_local_node_id(self_type_did).unwrap(); let drop_impl_span = tcx.def_span(drop_impl_did); @@ -226,7 +226,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'a, 'tcx>( // repeated `contains` calls. if !assumptions_in_impl_context.contains(&predicate) { - let item_span = tcx.hir.span(self_type_node_id); + let item_span = tcx.hir().span(self_type_node_id); struct_span_err!( tcx.sess, drop_impl_span, diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs index b4ad9cfbc6d..55fceda1a51 100644 --- a/src/librustc_typeck/check/generator_interior.rs +++ b/src/librustc_typeck/check/generator_interior.rs @@ -86,7 +86,7 @@ pub fn resolve_interior<'a, 'gcx, 'tcx>(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, def_id: DefId, body_id: hir::BodyId, interior: Ty<'tcx>) { - let body = fcx.tcx.hir.body(body_id); + let body = fcx.tcx.hir().body(body_id); let mut visitor = InteriorVisitor { fcx, types: FxHashMap::default(), diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 2af21f54744..a40e56d68ae 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -36,7 +36,7 @@ fn equate_intrinsic_type<'a, 'tcx>( inputs: Vec>, output: Ty<'tcx>, ) { - let def_id = tcx.hir.local_def_id(it.id); + let def_id = tcx.hir().local_def_id(it.id); match it.node { hir::ForeignItemKind::Fn(..) => {} @@ -401,7 +401,7 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx.mk_ty_param(n, name) }; - let def_id = tcx.hir.local_def_id(it.id); + let def_id = tcx.hir().local_def_id(it.id); let i_n_tps = tcx.generics_of(def_id).own_counts().types; let name = it.name.as_str(); @@ -435,7 +435,8 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, "simd_insert" => (2, vec![param(0), tcx.types.u32, param(1)], param(0)), "simd_extract" => (2, vec![param(0), tcx.types.u32], param(1)), "simd_cast" => (2, vec![param(0)], param(1)), - "simd_select" => (2, vec![param(0), param(1), param(1)], param(1)), + "simd_select" | + "simd_select_bitmask" => (2, vec![param(0), param(1), param(1)], param(1)), "simd_reduce_all" | "simd_reduce_any" => (1, vec![param(0)], tcx.types.bool), "simd_reduce_add_ordered" | "simd_reduce_mul_ordered" => (2, vec![param(0), param(1)], param(1)), @@ -505,7 +506,7 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } // walk the expected type and the actual type in lock step, checking they're -// the same, in a kinda-structural way, i.e. `Vector`s have to be simd structs with +// the same, in a kinda-structural way, i.e., `Vector`s have to be simd structs with // exactly the right element type fn match_intrinsic_type_to_type<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 5144f3e41d4..3902dddd0d4 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -161,9 +161,9 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { let (_, n) = autoderef.nth(pick.autoderefs).unwrap(); assert_eq!(n, pick.autoderefs); - let mut adjustments = autoderef.adjust_steps(Needs::None); + let mut adjustments = autoderef.adjust_steps(self, Needs::None); - let mut target = autoderef.unambiguous_final_ty(); + let mut target = autoderef.unambiguous_final_ty(self); if let Some(mutbl) = pick.autoref { let region = self.next_region_var(infer::Autoref(self.span)); @@ -202,7 +202,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { assert!(pick.unsize.is_none()); } - autoderef.finalize(); + autoderef.finalize(self); // Write out the final adjustments. self.apply_adjustments(self.self_expr, adjustments); @@ -395,7 +395,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // Instantiate late-bound regions and substitute the trait // parameters into the method type to get the actual method type. // - // NB: Instantiate late-bound regions first so that + // N.B., instantiate late-bound regions first so that // `instantiate_type_scheme` can normalize associated types that // may reference those regions. let method_sig = self.replace_bound_vars_with_fresh_vars(&sig); diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 37f4ae56779..5ecbfcd132c 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -12,36 +12,34 @@ //! //! [rustc guide]: https://rust-lang.github.io/rustc-guide/method-lookup.html -use check::FnCtxt; -use hir::def::Def; -use hir::def_id::DefId; -use namespace::Namespace; -use rustc::ty::subst::Substs; -use rustc::traits; -use rustc::ty::{self, Ty, ToPredicate, ToPolyTraitRef, TraitRef, TypeFoldable}; -use rustc::ty::GenericParamDefKind; -use rustc::ty::subst::Subst; -use rustc::infer::{self, InferOk}; - -use syntax::ast; -use syntax_pos::Span; - -use rustc::hir; - -use rustc_data_structures::sync::Lrc; +mod confirm; +pub mod probe; +mod suggest; pub use self::MethodError::*; pub use self::CandidateSource::*; pub use self::suggest::TraitInfo; -mod confirm; -pub mod probe; -mod suggest; +use check::FnCtxt; +use namespace::Namespace; +use rustc_data_structures::sync::Lrc; +use rustc::hir; +use rustc::hir::def::Def; +use rustc::hir::def_id::DefId; +use rustc::traits; +use rustc::ty::subst::Substs; +use rustc::ty::{self, Ty, ToPredicate, ToPolyTraitRef, TraitRef, TypeFoldable}; +use rustc::ty::GenericParamDefKind; +use rustc::ty::subst::Subst; +use rustc::infer::{self, InferOk}; +use syntax::ast; +use syntax_pos::Span; use self::probe::{IsSuggestion, ProbeScope}; pub fn provide(providers: &mut ty::query::Providers) { suggest::provide(providers); + probe::provide(providers); } #[derive(Clone, Copy, Debug)] @@ -50,7 +48,7 @@ pub struct MethodCallee<'tcx> { pub def_id: DefId, pub substs: &'tcx Substs<'tcx>, - /// Instantiated method signature, i.e. it has been + /// Instantiated method signature, i.e., it has been /// substituted, normalized, and has had late-bound /// lifetimes replaced with inference variables. pub sig: ty::FnSig<'tcx>, @@ -107,8 +105,7 @@ impl<'tcx> NoMatchData<'tcx> { #[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] pub enum CandidateSource { ImplSource(DefId), - TraitSource(// trait id - DefId), + TraitSource(DefId /* trait id */), } impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { @@ -171,10 +168,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { )?; if let Some(import_id) = pick.import_id { - let import_def_id = self.tcx.hir.local_def_id(import_id); + let import_def_id = self.tcx.hir().local_def_id(import_id); debug!("used_trait_import: {:?}", import_def_id); Lrc::get_mut(&mut self.tables.borrow_mut().used_trait_imports) - .unwrap().insert(import_def_id); + .unwrap().insert(import_def_id); } self.tcx.check_stability(pick.item.def_id, Some(call_expr.id), span); @@ -239,7 +236,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { /// an obligation for a particular trait with the given self-type and checks /// whether that trait is implemented. /// - /// FIXME(#18741) -- It seems likely that we can consolidate some of this + /// FIXME(#18741): it seems likely that we can consolidate some of this /// code with the other method-lookup code. In particular, the second half /// of this method is basically the same as confirmation. pub fn lookup_method_in_trait(&self, @@ -307,7 +304,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Instantiate late-bound regions and substitute the trait // parameters into the method type to get the actual method type. // - // NB: Instantiate late-bound regions first so that + // N.B., instantiate late-bound regions first so that // `instantiate_type_scheme` can normalize associated types that // may reference those regions. let fn_sig = tcx.fn_sig(def_id); @@ -324,7 +321,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } }; - // Register obligations for the parameters. This will include the + // Register obligations for the parameters. This will include the // `Self` parameter, which in turn has a bound of the main trait, // so this also effectively registers `obligation` as well. (We // used to register `obligation` explicitly, but that resulted in @@ -380,7 +377,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self_ty, expr_id, ProbeScope::TraitsInScope)?; if let Some(import_id) = pick.import_id { - let import_def_id = self.tcx.hir.local_def_id(import_id); + let import_def_id = self.tcx.hir().local_def_id(import_id); debug!("used_trait_import: {:?}", import_def_id); Lrc::get_mut(&mut self.tables.borrow_mut().used_trait_imports) .unwrap().insert(import_def_id); diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 5b67116cb51..190419048b4 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -13,35 +13,42 @@ use super::NoMatchData; use super::{CandidateSource, ImplSource, TraitSource}; use super::suggest; +use check::autoderef::{self, Autoderef}; use check::FnCtxt; use hir::def_id::DefId; use hir::def::Def; use namespace::Namespace; + +use rustc_data_structures::sync::Lrc; use rustc::hir; use rustc::lint; use rustc::session::config::nightly_options; use rustc::ty::subst::{Subst, Substs}; use rustc::traits::{self, ObligationCause}; -use rustc::ty::{self, Ty, ToPolyTraitRef, ToPredicate, TraitRef, TypeFoldable}; +use rustc::traits::query::{CanonicalTyGoal}; +use rustc::traits::query::method_autoderef::{CandidateStep, MethodAutoderefStepsResult}; +use rustc::traits::query::method_autoderef::{MethodAutoderefBadTy}; +use rustc::ty::{self, ParamEnvAnd, Ty, TyCtxt, ToPolyTraitRef, ToPredicate, TraitRef, TypeFoldable}; use rustc::ty::GenericParamDefKind; use rustc::infer::type_variable::TypeVariableOrigin; use rustc::util::nodemap::FxHashSet; use rustc::infer::{self, InferOk}; +use rustc::infer::canonical::{Canonical, QueryResponse}; +use rustc::infer::canonical::{OriginalQueryValues}; use rustc::middle::stability; use syntax::ast; use syntax::util::lev_distance::{lev_distance, find_best_match_for_name}; -use syntax_pos::{Span, symbol::Symbol}; +use syntax_pos::{DUMMY_SP, Span, symbol::Symbol}; use std::iter; use std::mem; use std::ops::Deref; -use std::rc::Rc; use std::cmp::max; use self::CandidateKind::*; pub use self::PickKind::*; /// Boolean flag used to indicate if this search is for a suggestion -/// or not. If true, we can allow ambiguity and so forth. +/// or not. If true, we can allow ambiguity and so forth. #[derive(Clone, Copy)] pub struct IsSuggestion(pub bool); @@ -51,7 +58,12 @@ struct ProbeContext<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { mode: Mode, method_name: Option, return_type: Option>, - steps: Rc>>, + + /// This is the OriginalQueryValues for the steps queries + /// that are answered in steps. + orig_steps_var_values: OriginalQueryValues<'tcx>, + steps: Lrc>>, + inherent_candidates: Vec>, extension_candidates: Vec>, impl_dups: FxHashSet, @@ -81,19 +93,6 @@ impl<'a, 'gcx, 'tcx> Deref for ProbeContext<'a, 'gcx, 'tcx> { } } -#[derive(Debug)] -struct CandidateStep<'tcx> { - self_ty: Ty<'tcx>, - autoderefs: usize, - // true if the type results from a dereference of a raw pointer. - // when assembling candidates, we include these steps, but not when - // picking methods. This so that if we have `foo: *const Foo` and `Foo` has methods - // `fn by_raw_ptr(self: *const Self)` and `fn by_ref(&self)`, then - // `foo.by_raw_ptr()` will work and `foo.by_ref()` won't. - from_unsafe_deref: bool, - unsize: bool, -} - #[derive(Debug)] struct Candidate<'tcx> { xform_self_ty: Ty<'tcx>, @@ -249,42 +248,111 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { -> Result> where OP: FnOnce(ProbeContext<'a, 'gcx, 'tcx>) -> Result> { - // FIXME(#18741) -- right now, creating the steps involves evaluating the - // `*` operator, which registers obligations that then escape into - // the global fulfillment context and thus has global - // side-effects. This is a bit of a pain to refactor. So just let - // it ride, although it's really not great, and in fact could I - // think cause spurious errors. Really though this part should - // take place in the `self.probe` below. + let mut orig_values = OriginalQueryValues::default(); + let param_env_and_self_ty = + self.infcx.canonicalize_query( + &ParamEnvAnd { + param_env: self.param_env, + value: self_ty + }, &mut orig_values); + let steps = if mode == Mode::MethodCall { - match self.create_steps(span, scope_expr_id, self_ty, is_suggestion) { - Some(steps) => steps, - None => { - return Err(MethodError::NoMatch(NoMatchData::new(Vec::new(), - Vec::new(), - Vec::new(), - None, - mode))) - } - } + self.tcx.method_autoderef_steps(param_env_and_self_ty) } else { - vec![CandidateStep { - self_ty, - autoderefs: 0, - from_unsafe_deref: false, - unsize: false, - }] + self.infcx.probe(|_| { + // Mode::Path - the deref steps is "trivial". This turns + // our CanonicalQuery into a "trivial" QueryResponse. This + // is a bit inefficient, but I don't think that writing + // special handling for this "trivial case" is a good idea. + + let infcx = &self.infcx; + let (ParamEnvAnd { + param_env: _, + value: self_ty + }, canonical_inference_vars) = + infcx.instantiate_canonical_with_fresh_inference_vars( + span, ¶m_env_and_self_ty); + debug!("probe_op: Mode::Path, param_env_and_self_ty={:?} self_ty={:?}", + param_env_and_self_ty, self_ty); + MethodAutoderefStepsResult { + steps: Lrc::new(vec![CandidateStep { + self_ty: self.make_query_response_ignoring_pending_obligations( + canonical_inference_vars, self_ty), + autoderefs: 0, + from_unsafe_deref: false, + unsize: false, + }]), + opt_bad_ty: None, + reached_recursion_limit: false + } + }) }; + // If our autoderef loop had reached the recursion limit, + // report an overflow error, but continue going on with + // the truncated autoderef list. + if steps.reached_recursion_limit { + self.probe(|_| { + let ty = &steps.steps.last().unwrap_or_else(|| { + span_bug!(span, "reached the recursion limit in 0 steps?") + }).self_ty; + let ty = self.probe_instantiate_query_response(span, &orig_values, ty) + .unwrap_or_else(|_| span_bug!(span, "instantiating {:?} failed?", ty)); + autoderef::report_autoderef_recursion_limit_error(self.tcx, span, + ty.value); + }); + } + + + // If we encountered an `_` type or an error type during autoderef, this is + // ambiguous. + if let Some(bad_ty) = &steps.opt_bad_ty { + if is_suggestion.0 { + // Ambiguity was encountered during a suggestion. Just keep going. + debug!("ProbeContext: encountered ambiguity in suggestion"); + } else if bad_ty.reached_raw_pointer && !self.tcx.features().arbitrary_self_types { + // this case used to be allowed by the compiler, + // so we do a future-compat lint here for the 2015 edition + // (see https://github.com/rust-lang/rust/issues/46906) + if self.tcx.sess.rust_2018() { + span_err!(self.tcx.sess, span, E0699, + "the type of this value must be known \ + to call a method on a raw pointer on it"); + } else { + self.tcx.lint_node( + lint::builtin::TYVAR_BEHIND_RAW_POINTER, + scope_expr_id, + span, + "type annotations needed"); + } + } else { + // Encountered a real ambiguity, so abort the lookup. If `ty` is not + // an `Err`, report the right "type annotations needed" error pointing + // to it. + let ty = &bad_ty.ty; + let ty = self.probe_instantiate_query_response(span, &orig_values, ty) + .unwrap_or_else(|_| span_bug!(span, "instantiating {:?} failed?", ty)); + let ty = self.structurally_resolved_type(span, ty.value); + assert_eq!(ty, self.tcx.types.err); + return Err(MethodError::NoMatch(NoMatchData::new(Vec::new(), + Vec::new(), + Vec::new(), + None, + mode))); + } + } + debug!("ProbeContext: steps for self_ty={:?} are {:?}", self_ty, steps); + // this creates one big transaction so that all type variables etc // that we create during the probe process are removed later self.probe(|_| { let mut probe_cx = ProbeContext::new( - self, span, mode, method_name, return_type, Rc::new(steps), is_suggestion, + self, span, mode, method_name, return_type, orig_values, + steps.steps, is_suggestion, ); probe_cx.assemble_inherent_candidates(); @@ -297,21 +365,30 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { op(probe_cx) }) } +} - fn create_steps(&self, - span: Span, - scope_expr_id: ast::NodeId, - self_ty: Ty<'tcx>, - is_suggestion: IsSuggestion) - -> Option>> { - // FIXME: we don't need to create the entire steps in one pass +pub fn provide(providers: &mut ty::query::Providers) { + providers.method_autoderef_steps = method_autoderef_steps; +} - let mut autoderef = self.autoderef(span, self_ty).include_raw_pointers(); +fn method_autoderef_steps<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, + goal: CanonicalTyGoal<'tcx>) + -> MethodAutoderefStepsResult<'gcx> +{ + debug!("method_autoderef_steps({:?})", goal); + + tcx.infer_ctxt().enter_with_canonical(DUMMY_SP, &goal, |ref infcx, goal, inference_vars| { + let ParamEnvAnd { param_env, value: self_ty } = goal; + + let mut autoderef = Autoderef::new(infcx, param_env, ast::DUMMY_NODE_ID, DUMMY_SP, self_ty) + .include_raw_pointers() + .silence_errors(); let mut reached_raw_pointer = false; let mut steps: Vec<_> = autoderef.by_ref() .map(|(ty, d)| { let step = CandidateStep { - self_ty: ty, + self_ty: infcx.make_query_response_ignoring_pending_obligations( + inference_vars.clone(), ty), autoderefs: d, from_unsafe_deref: reached_raw_pointer, unsize: false, @@ -325,68 +402,52 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { .collect(); let final_ty = autoderef.maybe_ambiguous_final_ty(); - match final_ty.sty { - ty::Infer(ty::TyVar(_)) => { - // Ended in an inference variable. If we are doing - // a real method lookup, this is a hard error because it's - // possible that there will be multiple applicable methods. - if !is_suggestion.0 { - if reached_raw_pointer - && !self.tcx.features().arbitrary_self_types { - // this case used to be allowed by the compiler, - // so we do a future-compat lint here for the 2015 edition - // (see https://github.com/rust-lang/rust/issues/46906) - if self.tcx.sess.rust_2018() { - span_err!(self.tcx.sess, span, E0699, - "the type of this value must be known \ - to call a method on a raw pointer on it"); - } else { - self.tcx.lint_node( - lint::builtin::TYVAR_BEHIND_RAW_POINTER, - scope_expr_id, - span, - "type annotations needed"); - } - } else { - let t = self.structurally_resolved_type(span, final_ty); - assert_eq!(t, self.tcx.types.err); - return None - } - } else { - // If we're just looking for suggestions, - // though, ambiguity is no big thing, we can - // just ignore it. - } + let opt_bad_ty = match final_ty.sty { + ty::Infer(ty::TyVar(_)) | + ty::Error => { + Some(MethodAutoderefBadTy { + reached_raw_pointer, + ty: infcx.make_query_response_ignoring_pending_obligations( + inference_vars, final_ty) + }) } ty::Array(elem_ty, _) => { let dereferences = steps.len() - 1; steps.push(CandidateStep { - self_ty: self.tcx.mk_slice(elem_ty), + self_ty: infcx.make_query_response_ignoring_pending_obligations( + inference_vars, infcx.tcx.mk_slice(elem_ty)), autoderefs: dereferences, // this could be from an unsafe deref if we had // a *mut/const [T; N] from_unsafe_deref: reached_raw_pointer, unsize: true, }); + + None } - ty::Error => return None, - _ => (), + _ => None + }; + + debug!("method_autoderef_steps: steps={:?} opt_bad_ty={:?}", steps, opt_bad_ty); + + MethodAutoderefStepsResult { + steps: Lrc::new(steps), + opt_bad_ty: opt_bad_ty.map(Lrc::new), + reached_recursion_limit: autoderef.reached_recursion_limit() } - - debug!("create_steps: steps={:?}", steps); - - Some(steps) - } + }) } + impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { fn new(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, span: Span, mode: Mode, method_name: Option, return_type: Option>, - steps: Rc>>, + orig_steps_var_values: OriginalQueryValues<'tcx>, + steps: Lrc>>, is_suggestion: IsSuggestion) -> ProbeContext<'a, 'gcx, 'tcx> { ProbeContext { @@ -398,7 +459,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { inherent_candidates: Vec::new(), extension_candidates: Vec::new(), impl_dups: FxHashSet::default(), - steps: steps, + orig_steps_var_values, + steps, static_candidates: Vec::new(), allow_similar_names: false, private_candidate: None, @@ -443,18 +505,26 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { fn assemble_inherent_candidates(&mut self) { let steps = self.steps.clone(); for step in steps.iter() { - self.assemble_probe(step.self_ty); + self.assemble_probe(&step.self_ty); } } - fn assemble_probe(&mut self, self_ty: Ty<'tcx>) { + fn assemble_probe(&mut self, self_ty: &Canonical<'gcx, QueryResponse<'gcx, Ty<'gcx>>>) { debug!("assemble_probe: self_ty={:?}", self_ty); let lang_items = self.tcx.lang_items(); - match self_ty.sty { + match self_ty.value.value.sty { ty::Dynamic(ref data, ..) => { let p = data.principal(); - self.assemble_inherent_candidates_from_object(self_ty, p); + self.fcx.probe(|_| { + let InferOk { value: self_ty, obligations: _ } = + self.fcx.probe_instantiate_query_response( + self.span, &self.orig_steps_var_values, self_ty) + .unwrap_or_else(|_| { + span_bug!(self.span, "{:?} was applicable but now isn't?", self_ty) + }); + self.assemble_inherent_candidates_from_object(self_ty); + }); self.assemble_inherent_impl_candidates_for_type(p.def_id()); } ty::Adt(def, _) => { @@ -464,7 +534,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { self.assemble_inherent_impl_candidates_for_type(did); } ty::Param(p) => { - self.assemble_inherent_candidates_from_param(self_ty, p); + self.assemble_inherent_candidates_from_param(p); } ty::Char => { let lang_def_id = lang_items.char_impl(); @@ -615,11 +685,16 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { } fn assemble_inherent_candidates_from_object(&mut self, - self_ty: Ty<'tcx>, - principal: ty::PolyExistentialTraitRef<'tcx>) { + self_ty: Ty<'tcx>) { debug!("assemble_inherent_candidates_from_object(self_ty={:?})", self_ty); + let principal = match self_ty.sty { + ty::Dynamic(ref data, ..) => data.principal(), + _ => span_bug!(self.span, "non-object {:?} in assemble_inherent_candidates_from_object", + self_ty) + }; + // It is illegal to invoke a method on a trait instance that // refers to the `Self` type. An error will be reported by // `enforce_object_limitations()` if the method refers to the @@ -642,7 +717,6 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { } fn assemble_inherent_candidates_from_param(&mut self, - _rcvr_ty: Ty<'tcx>, param_ty: ty::ParamTy) { // FIXME -- Do we want to commit to this behavior for param bounds? @@ -720,7 +794,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { return Ok(()) } let mut duplicates = FxHashSet::default(); - let expr_hir_id = self.tcx.hir.node_to_hir_id(expr_id); + let expr_hir_id = self.tcx.hir().node_to_hir_id(expr_id); let opt_applicable_traits = self.tcx.in_scope_traits(expr_hir_id); if let Some(applicable_traits) = opt_applicable_traits { for trait_candidate in applicable_traits.iter() { @@ -898,14 +972,22 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { // a raw pointer !step.self_ty.references_error() && !step.from_unsafe_deref }).flat_map(|step| { - self.pick_by_value_method(step).or_else(|| { - self.pick_autorefd_method(step, hir::MutImmutable).or_else(|| { - self.pick_autorefd_method(step, hir::MutMutable) + let InferOk { value: self_ty, obligations: _ } = + self.fcx.probe_instantiate_query_response( + self.span, &self.orig_steps_var_values, &step.self_ty + ).unwrap_or_else(|_| { + span_bug!(self.span, "{:?} was applicable but now isn't?", step.self_ty) + }); + self.pick_by_value_method(step, self_ty).or_else(|| { + self.pick_autorefd_method(step, self_ty, hir::MutImmutable).or_else(|| { + self.pick_autorefd_method(step, self_ty, hir::MutMutable) })})}) .next() } - fn pick_by_value_method(&mut self, step: &CandidateStep<'tcx>) -> Option> { + fn pick_by_value_method(&mut self, step: &CandidateStep<'gcx>, self_ty: Ty<'tcx>) + -> Option> + { //! For each type `T` in the step list, this attempts to find a //! method where the (transformed) self type is exactly `T`. We //! do however do one transformation on the adjustment: if we @@ -918,12 +1000,12 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { return None; } - self.pick_method(step.self_ty).map(|r| { + self.pick_method(self_ty).map(|r| { r.map(|mut pick| { pick.autoderefs = step.autoderefs; // Insert a `&*` or `&mut *` if this is a reference type: - if let ty::Ref(_, _, mutbl) = step.self_ty.sty { + if let ty::Ref(_, _, mutbl) = step.self_ty.value.value.sty { pick.autoderefs += 1; pick.autoref = Some(mutbl); } @@ -933,7 +1015,10 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { }) } - fn pick_autorefd_method(&mut self, step: &CandidateStep<'tcx>, mutbl: hir::Mutability) + fn pick_autorefd_method(&mut self, + step: &CandidateStep<'gcx>, + self_ty: Ty<'tcx>, + mutbl: hir::Mutability) -> Option> { let tcx = self.tcx; @@ -943,14 +1028,14 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { let autoref_ty = tcx.mk_ref(region, ty::TypeAndMut { - ty: step.self_ty, mutbl + ty: self_ty, mutbl }); self.pick_method(autoref_ty).map(|r| { r.map(|mut pick| { pick.autoderefs = step.autoderefs; pick.autoref = Some(mutbl); pick.unsize = if step.unsize { - Some(step.self_ty) + Some(self_ty) } else { None }; @@ -1288,7 +1373,9 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { let steps = self.steps.clone(); self.probe(|_| { let mut pcx = ProbeContext::new(self.fcx, self.span, self.mode, self.method_name, - self.return_type, steps, IsSuggestion(true)); + self.return_type, + self.orig_steps_var_values.clone(), + steps, IsSuggestion(true)); pcx.allow_similar_names = true; pcx.assemble_inherent_candidates(); pcx.assemble_extension_candidates_for_traits_in_scope(ast::DUMMY_NODE_ID)?; diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index cd243d41443..09063579c42 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -12,29 +12,23 @@ //! found or is otherwise invalid. use check::FnCtxt; -use rustc::hir::map as hir_map; -use hir::Node; -use rustc_data_structures::sync::Lrc; -use rustc::ty::{self, Ty, TyCtxt, ToPolyTraitRef, ToPredicate, TypeFoldable}; -use rustc::ty::item_path::with_crate_prefix; -use hir::def::Def; -use hir::def_id::{CRATE_DEF_INDEX, DefId}; +use errors::{Applicability, DiagnosticBuilder}; use middle::lang_items::FnOnceTraitLangItem; use namespace::Namespace; -use rustc::traits::Obligation; -use util::nodemap::FxHashSet; - -use syntax::ast; -use syntax::util::lev_distance::find_best_match_for_name; -use errors::{Applicability, DiagnosticBuilder}; -use syntax_pos::{Span, FileName}; - - -use rustc::hir::def_id::LOCAL_CRATE; -use rustc::hir; +use rustc_data_structures::sync::Lrc; +use rustc::hir::{self, Node}; +use rustc::hir::def::Def; +use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; +use rustc::hir::map as hir_map; use rustc::hir::print; use rustc::infer::type_variable::TypeVariableOrigin; -use rustc::ty::Adt; +use rustc::traits::Obligation; +use rustc::ty::{self, Adt, Ty, TyCtxt, ToPolyTraitRef, ToPredicate, TypeFoldable}; +use rustc::ty::item_path::with_crate_prefix; +use util::nodemap::FxHashSet; +use syntax_pos::{Span, FileName}; +use syntax::ast; +use syntax::util::lev_distance::find_best_match_for_name; use std::cmp::Ordering; @@ -45,12 +39,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn is_fn_ty(&self, ty: &Ty<'tcx>, span: Span) -> bool { let tcx = self.tcx; match ty.sty { - // Not all of these (e.g. unsafe fns) implement FnOnce - // so we look for these beforehand + // Not all of these (e.g., unsafe fns) implement `FnOnce`, + // so we look for these beforehand. ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(_) => true, - // If it's not a simple function, look for things which implement FnOnce + // If it's not a simple function, look for things which implement `FnOnce`. _ => { let fn_once = match tcx.lang_items().require(FnOnceTraitLangItem) { Ok(fn_once) => fn_once, @@ -83,7 +77,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { rcvr_expr: Option<&hir::Expr>, error: MethodError<'tcx>, args: Option<&'gcx [hir::Expr]>) { - // avoid suggestions when we don't know what's going on. + // Avoid suggestions when we don't know what's going on. if rcvr_ty.references_error() { return; } @@ -107,8 +101,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Namespace::Value, ) }).unwrap(); - let note_span = self.tcx.hir.span_if_local(item.def_id).or_else(|| { - self.tcx.hir.span_if_local(impl_did) + let note_span = self.tcx.hir().span_if_local(item.def_id).or_else(|| { + self.tcx.hir().span_if_local(impl_did) }); let impl_ty = self.impl_self_ty(span, impl_did).ty; @@ -194,7 +188,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let tcx = self.tcx; let actual = self.resolve_type_vars_if_possible(&rcvr_ty); - let ty_string = self.ty_to_string(actual); + let ty_str = self.ty_to_string(actual); let is_method = mode == Mode::MethodCall; let mut suggestion = None; let item_kind = if is_method { @@ -239,7 +233,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { "can't call {} `{}` on ambiguous numeric type `{}`", item_kind, item_name, - ty_string + ty_str ); let concrete_type = if actual.is_integral() { "i32" @@ -247,7 +241,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { "f32" }; match expr.node { - hir::ExprKind::Lit(ref lit) => { // numeric literal + hir::ExprKind::Lit(ref lit) => { + // numeric literal let snippet = tcx.sess.source_map().span_to_snippet(lit.span) .unwrap_or_else(|_| "".to_owned()); @@ -262,16 +257,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Applicability::MaybeIncorrect, ); } - hir::ExprKind::Path(ref qpath) => { // local binding + hir::ExprKind::Path(ref qpath) => { + // local binding if let &hir::QPath::Resolved(_, ref path) = &qpath { if let hir::def::Def::Local(node_id) = path.def { - let span = tcx.hir.span(node_id); + let span = tcx.hir().span(node_id); let snippet = tcx.sess.source_map().span_to_snippet(span) .unwrap(); let filename = tcx.sess.source_map().span_to_filename(span); - let parent_node = self.tcx.hir.get( - self.tcx.hir.get_parent_node(node_id), + let parent_node = self.tcx.hir().get( + self.tcx.hir().get_parent_node(node_id), ); let msg = format!( "you must specify a type for this binding, like `{}`", @@ -313,10 +309,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { "no {} named `{}` found for type `{}` in the current scope", item_kind, item_name, - ty_string + ty_str ); if let Some(suggestion) = suggestion { - err.note(&format!("did you mean `{}::{}`?", ty_string, suggestion)); + err.note(&format!("did you mean `{}::{}`?", ty_str, suggestion)); } err } @@ -325,7 +321,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; if let Some(def) = actual.ty_adt_def() { - if let Some(full_sp) = tcx.hir.span_if_local(def.did) { + if let Some(full_sp) = tcx.hir().span_if_local(def.did) { let def_sp = tcx.sess.source_map().def_span(full_sp); err.span_label(def_sp, format!("{} `{}` not found {}", item_kind, @@ -339,7 +335,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } // If the method name is the name of a field with a function or closure type, - // give a helping note that it has to be called as (x.f)(...). + // give a helping note that it has to be called as `(x.f)(...)`. if let Some(expr) = rcvr_expr { for (ty, _) in self.autoderef(span, rcvr_ty) { if let ty::Adt(def, substs) = ty.sty { @@ -351,12 +347,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let expr_string = match snippet { Ok(expr_string) => expr_string, _ => "s".into(), // Default to a generic placeholder for the - // expression when we can't generate a - // string snippet + // expression when we can't generate a + // string snippet. }; let field_ty = field.ty(tcx, substs); - let scope = self.tcx.hir.get_module_parent(self.body_id); + let scope = self.tcx.hir().get_module_parent(self.body_id); if field.vis.is_accessible_from(scope, self.tcx) { if self.is_fn_ty(&field_ty, span) { err.help(&format!("use `({0}.{1})(...)` if you \ @@ -380,7 +376,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } } else { - err.span_label(span, format!("{} not found in `{}`", item_kind, ty_string)); + err.span_label(span, format!("{} not found in `{}`", item_kind, ty_str)); } if self.is_fn_ty(&rcvr_ty, span) { @@ -424,15 +420,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { report_candidates(&mut err, static_sources); } else if static_sources.len() > 1 { - report_candidates(&mut err, static_sources); } if !unsatisfied_predicates.is_empty() { - let bound_list = unsatisfied_predicates.iter() + let mut bound_list = unsatisfied_predicates.iter() .map(|p| format!("`{} : {}`", p.self_ty(), p)) - .collect::>() - .join("\n"); + .collect::>(); + bound_list.sort(); + bound_list.dedup(); // #35677 + let bound_list = bound_list.join("\n"); err.note(&format!("the method `{}` exists but the following trait bounds \ were not satisfied:\n{}", item_name, @@ -503,13 +500,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { err: &mut DiagnosticBuilder, mut msg: String, candidates: Vec) { - let module_did = self.tcx.hir.get_module_parent(self.body_id); - let module_id = self.tcx.hir.as_local_node_id(module_did).unwrap(); - let krate = self.tcx.hir.krate(); + let module_did = self.tcx.hir().get_module_parent(self.body_id); + let module_id = self.tcx.hir().as_local_node_id(module_did).unwrap(); + let krate = self.tcx.hir().krate(); let (span, found_use) = UsePlacementFinder::check(self.tcx, krate, module_id); if let Some(span) = span { let path_strings = candidates.iter().map(|did| { - // produce an additional newline to separate the new use statement + // Produce an additional newline to separate the new use statement // from the directly following item. let additional_newline = if found_use { "" @@ -597,15 +594,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let type_is_local = self.type_derefs_to_local(span, rcvr_ty, rcvr_expr); - // there's no implemented traits, so lets suggest some traits to + // There are no traits implemented, so lets suggest some traits to // implement, by finding ones that have the item name, and are // legal to implement. let mut candidates = all_traits(self.tcx) .into_iter() .filter(|info| { - // we approximate the coherence rules to only suggest + // We approximate the coherence rules to only suggest // traits that are legal to implement by requiring that - // either the type or trait is local. Multidispatch means + // either the type or trait is local. Multi-dispatch means // this isn't perfect (that is, there are cases when // implementing a trait would be legal but is rejected // here). @@ -620,11 +617,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { .collect::>(); if !candidates.is_empty() { - // sort from most relevant to least relevant + // Sort from most relevant to least relevant. candidates.sort_by(|a, b| a.cmp(b).reverse()); candidates.dedup(); - // FIXME #21673 this help message could be tuned to the case + // FIXME #21673: this help message could be tuned to the case // of a type parameter: suggest adding a trait bound rather // than implementing. err.help("items from traits can only be used if the trait is implemented and in scope"); @@ -656,8 +653,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn type_derefs_to_local(&self, span: Span, rcvr_ty: Ty<'tcx>, - rcvr_expr: Option<&hir::Expr>) - -> bool { + rcvr_expr: Option<&hir::Expr>) -> bool { fn is_local(ty: Ty) -> bool { match ty.sty { ty::Adt(def, _) => def.did.is_local(), @@ -667,8 +663,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty::Param(_) => true, - // everything else (primitive types etc.) is effectively - // non-local (there are "edge" cases, e.g. (LocalType,), but + // Everything else (primitive types, etc.) is effectively + // non-local (there are "edge" cases, e.g., `(LocalType,)`, but // the noise from these sort of types is usually just really // annoying, rather than any sort of help). _ => false, @@ -703,8 +699,8 @@ impl PartialOrd for TraitInfo { } impl Ord for TraitInfo { fn cmp(&self, other: &TraitInfo) -> Ordering { - // local crates are more important than remote ones (local: - // cnum == 0), and otherwise we throw in the defid for totality + // Local crates are more important than remote ones (local: + // `cnum == 0`), and otherwise we throw in the defid for totality. let lhs = (other.def_id.krate, other.def_id); let rhs = (self.def_id.krate, self.def_id); @@ -719,65 +715,65 @@ pub fn all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Vec /// Compute all traits in this crate and any dependent crates. fn compute_all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Vec { - use rustc::hir::itemlikevisit; + use hir::itemlikevisit; - let mut traits = vec![]; + let mut traits = vec![]; - // Crate-local: - // - // meh. - struct Visitor<'a, 'tcx: 'a> { - map: &'a hir_map::Map<'tcx>, - traits: &'a mut Vec, + // Crate-local: + + struct Visitor<'a, 'tcx: 'a> { + map: &'a hir_map::Map<'tcx>, + traits: &'a mut Vec, + } + + impl<'v, 'a, 'tcx> itemlikevisit::ItemLikeVisitor<'v> for Visitor<'a, 'tcx> { + fn visit_item(&mut self, i: &'v hir::Item) { + if let hir::ItemKind::Trait(..) = i.node { + let def_id = self.map.local_def_id(i.id); + self.traits.push(def_id); + } } - impl<'v, 'a, 'tcx> itemlikevisit::ItemLikeVisitor<'v> for Visitor<'a, 'tcx> { - fn visit_item(&mut self, i: &'v hir::Item) { - if let hir::ItemKind::Trait(..) = i.node { - let def_id = self.map.local_def_id(i.id); - self.traits.push(def_id); + + fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {} + + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {} + } + + tcx.hir().krate().visit_all_item_likes(&mut Visitor { + map: &tcx.hir(), + traits: &mut traits, + }); + + // Cross-crate: + + let mut external_mods = FxHashSet::default(); + fn handle_external_def(tcx: TyCtxt, + traits: &mut Vec, + external_mods: &mut FxHashSet, + def: Def) { + let def_id = def.def_id(); + match def { + Def::Trait(..) => { + traits.push(def_id); + } + Def::Mod(..) => { + if !external_mods.insert(def_id) { + return; + } + for child in tcx.item_children(def_id).iter() { + handle_external_def(tcx, traits, external_mods, child.def) } } - - fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { - } - - fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { - } - } - tcx.hir.krate().visit_all_item_likes(&mut Visitor { - map: &tcx.hir, - traits: &mut traits, - }); - - // Cross-crate: - let mut external_mods = FxHashSet::default(); - fn handle_external_def(tcx: TyCtxt, - traits: &mut Vec, - external_mods: &mut FxHashSet, - def: Def) { - let def_id = def.def_id(); - match def { - Def::Trait(..) => { - traits.push(def_id); - } - Def::Mod(..) => { - if !external_mods.insert(def_id) { - return; - } - for child in tcx.item_children(def_id).iter() { - handle_external_def(tcx, traits, external_mods, child.def) - } - } - _ => {} - } - } - for &cnum in tcx.crates().iter() { - let def_id = DefId { - krate: cnum, - index: CRATE_DEF_INDEX, - }; - handle_external_def(tcx, &mut traits, &mut external_mods, Def::Mod(def_id)); + _ => {} } + } + for &cnum in tcx.crates().iter() { + let def_id = DefId { + krate: cnum, + index: CRATE_DEF_INDEX, + }; + handle_external_def(tcx, &mut traits, &mut external_mods, Def::Mod(def_id)); + } traits } @@ -827,29 +823,29 @@ impl<'a, 'tcx, 'gcx> hir::intravisit::Visitor<'tcx> for UsePlacementFinder<'a, ' hir::intravisit::walk_mod(self, module, node_id); return; } - // find a use statement + // Find a `use` statement. for item_id in &module.item_ids { - let item = self.tcx.hir.expect_item(item_id.id); + let item = self.tcx.hir().expect_item(item_id.id); match item.node { hir::ItemKind::Use(..) => { - // don't suggest placing a use before the prelude - // import or other generated ones + // Don't suggest placing a `use` before the prelude + // import or other generated ones. if item.span.ctxt().outer().expn_info().is_none() { self.span = Some(item.span.shrink_to_lo()); self.found_use = true; return; } }, - // don't place use before extern crate + // Don't place `use` before `extern crate`... hir::ItemKind::ExternCrate(_) => {} - // but place them before the first other item + // ...but do place them before the first other item. _ => if self.span.map_or(true, |span| item.span < span ) { if item.span.ctxt().outer().expn_info().is_none() { - // don't insert between attributes and an item + // Don't insert between attributes and an item. if item.attrs.is_empty() { self.span = Some(item.span.shrink_to_lo()); } else { - // find the first attribute on the item + // Find the first attribute on the item. for attr in &item.attrs { if self.span.map_or(true, |span| attr.span < span) { self.span = Some(attr.span.shrink_to_lo()); @@ -861,6 +857,7 @@ impl<'a, 'tcx, 'gcx> hir::intravisit::Visitor<'tcx> for UsePlacementFinder<'a, ' } } } + fn nested_visit_map<'this>( &'this mut self ) -> hir::intravisit::NestedVisitorMap<'this, 'tcx> { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index e30a79b25de..d45f8fd6de8 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -8,14 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/* +/*! # check.rs Within the check phase of type check, we check each item one at a time (bodies of function expressions are checked as part of the containing -function). Inference is used to supply types wherever they are -unknown. +function). Inference is used to supply types wherever they are unknown. By far the most complex case is checking the body of a function. This can be broken down into several distinct phases: @@ -65,7 +64,7 @@ nodes within the function. The types of top-level items, which never contain unbound type variables, are stored directly into the `tcx` tables. -N.B.: A type variable is not the same thing as a type parameter. A +N.B., a type variable is not the same thing as a type parameter. A type variable is rather an "instance" of a type parameter: that is, given a generic function `fn foo(t: T)`: while checking the function `foo`, the type `ty_param(0)` refers to the type `T`, which @@ -76,69 +75,6 @@ type parameter). */ -pub use self::Expectation::*; -use self::autoderef::Autoderef; -use self::callee::DeferredCallResolution; -use self::coercion::{CoerceMany, DynamicCoerceMany}; -pub use self::compare_method::{compare_impl_method, compare_const_impl}; -use self::method::MethodCallee; -use self::TupleArgumentsFlag::*; - -use astconv::AstConv; -use hir::GenericArg; -use hir::def::Def; -use hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; -use std::slice; -use namespace::Namespace; -use rustc::infer::{self, InferCtxt, InferOk, RegionVariableOrigin}; -use rustc::infer::opaque_types::OpaqueTypeDecl; -use rustc::infer::type_variable::{TypeVariableOrigin}; -use rustc::middle::region; -use rustc::mir::interpret::{ConstValue, GlobalId}; -use rustc::ty::subst::{CanonicalUserSubsts, UnpackedKind, Subst, Substs, - UserSelfTy, UserSubsts}; -use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine}; -use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind, Visibility, ToPredicate, RegionKind}; -use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; -use rustc::ty::fold::TypeFoldable; -use rustc::ty::query::Providers; -use rustc::ty::util::{Representability, IntTypeExt, Discr}; -use rustc::ty::layout::VariantIdx; -use rustc_data_structures::indexed_vec::Idx; -use errors::{Applicability, DiagnosticBuilder, DiagnosticId}; - -use require_c_abi_if_variadic; -use session::{CompileIncomplete, config, Session}; -use TypeAndSubsts; -use lint; -use util::common::{ErrorReported, indenter}; -use util::nodemap::{DefIdMap, DefIdSet, FxHashMap, FxHashSet, NodeMap}; - -use std::cell::{Cell, RefCell, Ref, RefMut}; -use rustc_data_structures::sync::Lrc; -use std::collections::hash_map::Entry; -use std::cmp; -use std::fmt::Display; -use std::iter; -use std::mem::replace; -use std::ops::{self, Deref}; -use rustc_target::spec::abi::Abi; -use syntax::ast; -use syntax::attr; -use syntax::source_map::DUMMY_SP; -use syntax::source_map::original_sp; -use syntax::feature_gate::{GateIssue, emit_feature_err}; -use syntax::ptr::P; -use syntax::symbol::{Symbol, LocalInternedString, keywords}; -use syntax::util::lev_distance::find_best_match_for_name; -use syntax_pos::{self, BytePos, Span, MultiSpan}; - -use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; -use rustc::hir::itemlikevisit::ItemLikeVisitor; -use rustc::hir::Node; -use rustc::hir::{self, PatKind, ItemKind}; -use rustc::middle::lang_items; - mod autoderef; pub mod dropck; pub mod _match; @@ -157,6 +93,68 @@ mod generator_interior; mod intrinsic; mod op; +use astconv::AstConv; +use errors::{Applicability, DiagnosticBuilder, DiagnosticId}; +use rustc::hir::{self, GenericArg, ItemKind, Node, PatKind}; +use rustc::hir::def::Def; +use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; +use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; +use rustc::hir::itemlikevisit::ItemLikeVisitor; +use middle::lang_items; +use namespace::Namespace; +use rustc::infer::{self, InferCtxt, InferOk, InferResult, RegionVariableOrigin}; +use rustc::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse}; +use rustc_data_structures::indexed_vec::Idx; +use rustc_data_structures::sync::Lrc; +use rustc_target::spec::abi::Abi; +use rustc::infer::opaque_types::OpaqueTypeDecl; +use rustc::infer::type_variable::{TypeVariableOrigin}; +use rustc::middle::region; +use rustc::mir::interpret::{ConstValue, GlobalId}; +use rustc::ty::subst::{CanonicalUserSubsts, UnpackedKind, Subst, Substs, + UserSelfTy, UserSubsts}; +use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine}; +use rustc::ty::{self, AdtKind, Ty, TyCtxt, GenericParamDefKind, RegionKind, Visibility, + ToPolyTraitRef, ToPredicate}; +use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; +use rustc::ty::fold::TypeFoldable; +use rustc::ty::query::Providers; +use rustc::ty::util::{Representability, IntTypeExt, Discr}; +use rustc::ty::layout::VariantIdx; +use syntax_pos::{self, BytePos, Span, MultiSpan}; +use syntax::ast; +use syntax::attr; +use syntax::feature_gate::{GateIssue, emit_feature_err}; +use syntax::ptr::P; +use syntax::source_map::{DUMMY_SP, original_sp}; +use syntax::symbol::{Symbol, LocalInternedString, keywords}; +use syntax::util::lev_distance::find_best_match_for_name; + +use std::cell::{Cell, RefCell, Ref, RefMut}; +use std::collections::hash_map::Entry; +use std::cmp; +use std::fmt::Display; +use std::iter; +use std::mem::replace; +use std::ops::{self, Deref}; +use std::slice; + +use require_c_abi_if_variadic; +use session::{CompileIncomplete, config, Session}; +use TypeAndSubsts; +use lint; +use util::captures::Captures; +use util::common::{ErrorReported, indenter}; +use util::nodemap::{DefIdMap, DefIdSet, FxHashMap, FxHashSet, NodeMap}; + +pub use self::Expectation::*; +use self::autoderef::Autoderef; +use self::callee::DeferredCallResolution; +use self::coercion::{CoerceMany, DynamicCoerceMany}; +pub use self::compare_method::{compare_impl_method, compare_const_impl}; +use self::method::MethodCallee; +use self::TupleArgumentsFlag::*; + /// The type of a local binding, including the revealed type for anon types. #[derive(Copy, Clone)] pub struct LocalTy<'tcx> { @@ -605,8 +603,8 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { pub fn build(tcx: TyCtxt<'a, 'gcx, 'gcx>, def_id: DefId) -> InheritedBuilder<'a, 'gcx, 'tcx> { let hir_id_root = if def_id.is_local() { - let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); - let hir_id = tcx.hir.definitions().node_to_hir_id(node_id); + let node_id = tcx.hir().as_local_node_id(def_id).unwrap(); + let hir_id = tcx.hir().definitions().node_to_hir_id(node_id); DefId::local(hir_id.owner) } else { def_id @@ -631,10 +629,10 @@ impl<'a, 'gcx, 'tcx> InheritedBuilder<'a, 'gcx, 'tcx> { impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>, def_id: DefId) -> Self { let tcx = infcx.tcx; - let item_id = tcx.hir.as_local_node_id(def_id); - let body_id = item_id.and_then(|id| tcx.hir.maybe_body_owned_by(id)); + let item_id = tcx.hir().as_local_node_id(def_id); + 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); + let body = tcx.hir().body(body_id); tcx.mk_region(ty::ReScope(region::Scope { id: body.value.hir_id.local_id, data: region::ScopeData::CallSite @@ -707,13 +705,13 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> { pub fn check_wf_new<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), ErrorReported> { tcx.sess.track_errors(|| { let mut visit = wfcheck::CheckTypeWellFormedVisitor::new(tcx); - tcx.hir.krate().visit_all_item_likes(&mut visit.as_deep_visitor()); + tcx.hir().krate().visit_all_item_likes(&mut visit.as_deep_visitor()); }) } pub fn check_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), ErrorReported> { tcx.sess.track_errors(|| { - tcx.hir.krate().visit_all_item_likes(&mut CheckItemTypesVisitor { tcx }); + tcx.hir().krate().visit_all_item_likes(&mut CheckItemTypesVisitor { tcx }); }) } @@ -778,7 +776,7 @@ fn primary_body_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: ast::NodeId) -> Option<(hir::BodyId, Option<&'tcx hir::FnDecl>)> { - match tcx.hir.get(id) { + match tcx.hir().get(id) { Node::Item(item) => { match item.node { hir::ItemKind::Const(_, body) | @@ -825,7 +823,7 @@ fn has_typeck_tables<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, return tcx.has_typeck_tables(outer_def_id); } - let id = tcx.hir.as_local_node_id(def_id).unwrap(); + let id = tcx.hir().as_local_node_id(def_id).unwrap(); primary_body_of(tcx, id).is_some() } @@ -845,14 +843,14 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, return tcx.typeck_tables_of(outer_def_id); } - let id = tcx.hir.as_local_node_id(def_id).unwrap(); - let span = tcx.hir.span(id); + let id = tcx.hir().as_local_node_id(def_id).unwrap(); + let span = tcx.hir().span(id); // Figure out what primary body this item has. let (body_id, fn_decl) = primary_body_of(tcx, id).unwrap_or_else(|| { span_bug!(span, "can't type-check body of {:?}", def_id); }); - let body = tcx.hir.body(body_id); + let body = tcx.hir().body(body_id); let tables = Inherited::build(tcx, def_id).enter(|inh| { let param_env = tcx.param_env(def_id); @@ -914,6 +912,7 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fcx.resolve_generator_interiors(def_id); for (ty, span, code) in fcx.deferred_sized_obligations.borrow_mut().drain(..) { + let ty = fcx.normalize_ty(span, ty); fcx.require_type_is_sized(ty, span, code); } fcx.select_all_obligations_or_error(); @@ -930,7 +929,7 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Consistency check our TypeckTables instance can hold all ItemLocalIds // it will need to hold. assert_eq!(tables.local_id_root, - Some(DefId::local(tcx.hir.definitions().node_to_hir_id(id).owner))); + Some(DefId::local(tcx.hir().definitions().node_to_hir_id(id).owner))); tables } @@ -1087,8 +1086,8 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, fcx.yield_ty = Some(yield_ty); } - let outer_def_id = fcx.tcx.closure_base_def_id(fcx.tcx.hir.local_def_id(fn_id)); - let outer_node_id = fcx.tcx.hir.as_local_node_id(outer_def_id).unwrap(); + let outer_def_id = fcx.tcx.closure_base_def_id(fcx.tcx.hir().local_def_id(fn_id)); + let outer_node_id = fcx.tcx.hir().as_local_node_id(outer_def_id).unwrap(); GatherLocalsVisitor { fcx: &fcx, parent_id: outer_node_id, }.visit_body(body); // Add formal parameters. @@ -1108,7 +1107,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, fcx.write_ty(arg.hir_id, arg_ty); } - let fn_hir_id = fcx.tcx.hir.node_to_hir_id(fn_id); + let fn_hir_id = fcx.tcx.hir().node_to_hir_id(fn_id); inherited.tables.borrow_mut().liberated_fn_sigs_mut().insert(fn_hir_id, fn_sig); fcx.check_return_expr(&body.value); @@ -1180,7 +1179,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, // Check that a function marked as `#[panic_handler]` has signature `fn(&PanicInfo) -> !` if let Some(panic_impl_did) = fcx.tcx.lang_items().panic_impl() { - if panic_impl_did == fcx.tcx.hir.local_def_id(fn_id) { + if panic_impl_did == fcx.tcx.hir().local_def_id(fn_id) { if let Some(panic_info_did) = fcx.tcx.lang_items().panic_info() { // at this point we don't care if there are duplicate handlers or if the handler has // the wrong signature as this value we'll be used when writing metadata and that @@ -1195,7 +1194,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, } let inputs = fn_sig.inputs(); - let span = fcx.tcx.hir.span(fn_id); + let span = fcx.tcx.hir().span(fn_id); if inputs.len() == 1 { let arg_is_panic_info = match inputs[0].sty { ty::Ref(region, ty, mutbl) => match ty.sty { @@ -1216,7 +1215,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, ); } - if let Node::Item(item) = fcx.tcx.hir.get(fn_id) { + if let Node::Item(item) = fcx.tcx.hir().get(fn_id) { if let ItemKind::Fn(_, _, ref generics, _) = item.node { if !generics.params.is_empty() { fcx.tcx.sess.span_err( @@ -1238,7 +1237,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, // Check that a function marked as `#[alloc_error_handler]` has signature `fn(Layout) -> !` if let Some(alloc_error_handler_did) = fcx.tcx.lang_items().oom() { - if alloc_error_handler_did == fcx.tcx.hir.local_def_id(fn_id) { + if alloc_error_handler_did == fcx.tcx.hir().local_def_id(fn_id) { if let Some(alloc_layout_did) = fcx.tcx.lang_items().alloc_layout() { if declared_ret_ty.sty != ty::Never { fcx.tcx.sess.span_err( @@ -1248,7 +1247,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, } let inputs = fn_sig.inputs(); - let span = fcx.tcx.hir.span(fn_id); + let span = fcx.tcx.hir().span(fn_id); if inputs.len() == 1 { let arg_is_alloc_layout = match inputs[0].sty { ty::Adt(ref adt, _) => { @@ -1264,7 +1263,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, ); } - if let Node::Item(item) = fcx.tcx.hir.get(fn_id) { + if let Node::Item(item) = fcx.tcx.hir().get(fn_id) { if let ItemKind::Fn(_, _, ref generics, _) = item.node { if !generics.params.is_empty() { fcx.tcx.sess.span_err( @@ -1291,7 +1290,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, fn check_struct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: ast::NodeId, span: Span) { - let def_id = tcx.hir.local_def_id(id); + let def_id = tcx.hir().local_def_id(id); let def = tcx.adt_def(def_id); def.destructor(tcx); // force the destructor to be evaluated check_representable(tcx, span, def_id); @@ -1307,7 +1306,7 @@ fn check_struct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn check_union<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: ast::NodeId, span: Span) { - let def_id = tcx.hir.local_def_id(id); + let def_id = tcx.hir().local_def_id(id); let def = tcx.adt_def(def_id); def.destructor(tcx); // force the destructor to be evaluated check_representable(tcx, span, def_id); @@ -1319,18 +1318,18 @@ pub fn check_item_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &'tcx hir::Ite debug!( "check_item_type(it.id={}, it.name={})", it.id, - tcx.item_path_str(tcx.hir.local_def_id(it.id)) + tcx.item_path_str(tcx.hir().local_def_id(it.id)) ); let _indenter = indenter(); match it.node { // Consts can play a role in type-checking, so they are included here. hir::ItemKind::Static(..) => { - let def_id = tcx.hir.local_def_id(it.id); + let def_id = tcx.hir().local_def_id(it.id); tcx.typeck_tables_of(def_id); maybe_check_static_with_link_section(tcx, def_id, it.span); } hir::ItemKind::Const(..) => { - tcx.typeck_tables_of(tcx.hir.local_def_id(it.id)); + tcx.typeck_tables_of(tcx.hir().local_def_id(it.id)); } hir::ItemKind::Enum(ref enum_definition, _) => { check_enum(tcx, it.span, &enum_definition.variants, it.id); @@ -1338,7 +1337,7 @@ pub fn check_item_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &'tcx hir::Ite hir::ItemKind::Fn(..) => {} // entirely within check_item_body hir::ItemKind::Impl(.., ref impl_item_refs) => { debug!("ItemKind::Impl {} with id {}", it.name, it.id); - let impl_def_id = tcx.hir.local_def_id(it.id); + let impl_def_id = tcx.hir().local_def_id(it.id); if let Some(impl_trait_ref) = tcx.impl_trait_ref(impl_def_id) { check_impl_items_against_trait( tcx, @@ -1352,7 +1351,7 @@ pub fn check_item_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &'tcx hir::Ite } } hir::ItemKind::Trait(..) => { - let def_id = tcx.hir.local_def_id(it.id); + let def_id = tcx.hir().local_def_id(it.id); check_on_unimplemented(tcx, def_id, it); } hir::ItemKind::Struct(..) => { @@ -1362,7 +1361,7 @@ pub fn check_item_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &'tcx hir::Ite check_union(tcx, it.id, it.span); } hir::ItemKind::Existential(..) | hir::ItemKind::Ty(..) => { - let def_id = tcx.hir.local_def_id(it.id); + let def_id = tcx.hir().local_def_id(it.id); let pty_ty = tcx.type_of(def_id); let generics = tcx.generics_of(def_id); check_bounds_are_used(tcx, &generics, pty_ty); @@ -1380,7 +1379,7 @@ pub fn check_item_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &'tcx hir::Ite } } else { for item in &m.items { - let generics = tcx.generics_of(tcx.hir.local_def_id(item.id)); + let generics = tcx.generics_of(tcx.hir().local_def_id(item.id)); if generics.params.len() - generics.own_counts().lifetimes != 0 { let mut err = struct_span_err!( tcx.sess, @@ -1449,7 +1448,7 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt, id: DefId, span: Span) { fn check_on_unimplemented<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_def_id: DefId, item: &hir::Item) { - let item_def_id = tcx.hir.local_def_id(item.id); + let item_def_id = tcx.hir().local_def_id(item.id); // an error would be reported if this fails. let _ = traits::OnUnimplementedDirective::of_item(tcx, trait_def_id, item_def_id); } @@ -1522,12 +1521,12 @@ fn check_impl_items_against_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let trait_def = tcx.trait_def(impl_trait_ref.def_id); let mut overridden_associated_type = None; - let impl_items = || impl_item_refs.iter().map(|iiref| tcx.hir.impl_item(iiref.id)); + let impl_items = || impl_item_refs.iter().map(|iiref| tcx.hir().impl_item(iiref.id)); // Check existing impl methods to see if they are both present in trait // and compatible with trait signature for impl_item in impl_items() { - let ty_impl_item = tcx.associated_item(tcx.hir.local_def_id(impl_item.id)); + let ty_impl_item = tcx.associated_item(tcx.hir().local_def_id(impl_item.id)); let ty_trait_item = tcx.associated_items(impl_trait_ref.def_id) .find(|ac| Namespace::from(&impl_item.node) == Namespace::from(ac.kind) && tcx.hygienic_eq(ty_impl_item.ident, ac.ident, impl_trait_ref.def_id)) @@ -1557,14 +1556,14 @@ fn check_impl_items_against_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, err.span_label(impl_item.span, "does not match trait"); // We can only get the spans from local trait definition // Same for E0324 and E0325 - if let Some(trait_span) = tcx.hir.span_if_local(ty_trait_item.def_id) { + if let Some(trait_span) = tcx.hir().span_if_local(ty_trait_item.def_id) { err.span_label(trait_span, "item in trait"); } err.emit() } } hir::ImplItemKind::Method(..) => { - let trait_span = tcx.hir.span_if_local(ty_trait_item.def_id); + let trait_span = tcx.hir().span_if_local(ty_trait_item.def_id); if ty_trait_item.kind == ty::AssociatedKind::Method { compare_impl_method(tcx, &ty_impl_item, @@ -1579,7 +1578,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty_impl_item.ident, impl_trait_ref); err.span_label(impl_item.span, "does not match trait"); - if let Some(trait_span) = tcx.hir.span_if_local(ty_trait_item.def_id) { + if let Some(trait_span) = tcx.hir().span_if_local(ty_trait_item.def_id) { err.span_label(trait_span, "item in trait"); } err.emit() @@ -1598,7 +1597,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty_impl_item.ident, impl_trait_ref); err.span_label(impl_item.span, "does not match trait"); - if let Some(trait_span) = tcx.hir.span_if_local(ty_trait_item.def_id) { + if let Some(trait_span) = tcx.hir().span_if_local(ty_trait_item.def_id) { err.span_label(trait_span, "item in trait"); } err.emit() @@ -1641,7 +1640,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, .map(|trait_item| trait_item.ident.to_string()) .collect::>().join("`, `"))); for trait_item in missing_items { - if let Some(span) = tcx.hir.span_if_local(trait_item.def_id) { + if let Some(span) = tcx.hir().span_if_local(trait_item.def_id) { err.span_label(span, format!("`{}` from trait", trait_item.ident)); } else { err.note_trait_signature(trait_item.ident.to_string(), @@ -1786,7 +1785,7 @@ fn check_transparent<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, def_id: De let param_env = tcx.param_env(field.did); let layout = tcx.layout_of(param_env.and(ty)); // We are currently checking the type this field came from, so it must be local - let span = tcx.hir.span_if_local(field.did).unwrap(); + let span = tcx.hir().span_if_local(field.did).unwrap(); let zst = layout.map(|layout| layout.is_zst()).unwrap_or(false); let align1 = layout.map(|layout| layout.align.abi.bytes() == 1).unwrap_or(false); (span, zst, align1) @@ -1815,7 +1814,7 @@ pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, vs: &'tcx [hir::Variant], id: ast::NodeId) { - let def_id = tcx.hir.local_def_id(id); + let def_id = tcx.hir().local_def_id(id); let def = tcx.adt_def(def_id); def.destructor(tcx); // force the destructor to be evaluated @@ -1843,7 +1842,7 @@ pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, for v in vs { if let Some(ref e) = v.node.disr_expr { - tcx.typeck_tables_of(tcx.hir.local_def_id(e.id)); + tcx.typeck_tables_of(tcx.hir().local_def_id(e.id)); } } @@ -1852,14 +1851,14 @@ pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Check for duplicate discriminant values if let Some(i) = disr_vals.iter().position(|&x| x.val == discr.val) { let variant_did = def.variants[VariantIdx::new(i)].did; - let variant_i_node_id = tcx.hir.as_local_node_id(variant_did).unwrap(); - let variant_i = tcx.hir.expect_variant(variant_i_node_id); + let variant_i_node_id = tcx.hir().as_local_node_id(variant_did).unwrap(); + let variant_i = tcx.hir().expect_variant(variant_i_node_id); let i_span = match variant_i.node.disr_expr { - Some(ref expr) => tcx.hir.span(expr.id), - None => tcx.hir.span(variant_i_node_id) + Some(ref expr) => tcx.hir().span(expr.id), + None => tcx.hir().span(variant_i_node_id) }; let span = match v.node.disr_expr { - Some(ref expr) => tcx.hir.span(expr.id), + Some(ref expr) => tcx.hir().span(expr.id), None => v.span }; struct_span_err!(tcx.sess, span, E0081, @@ -1881,9 +1880,9 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { -> Lrc> { let tcx = self.tcx; - let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); - let item_id = tcx.hir.ty_param_owner(node_id); - let item_def_id = tcx.hir.local_def_id(item_id); + let node_id = tcx.hir().as_local_node_id(def_id).unwrap(); + let item_id = tcx.hir().ty_param_owner(node_id); + let item_def_id = tcx.hir().local_def_id(item_id); let generics = tcx.generics_of(item_def_id); let index = generics.param_def_id_to_index[&def_id]; Lrc::new(ty::GenericPredicates { @@ -2089,7 +2088,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> LocalTy<'tcx> { self.locals.borrow().get(&nid).cloned().unwrap_or_else(|| span_bug!(span, "no type for local variable {}", - self.tcx.hir.node_to_string(nid)) + self.tcx.hir().node_to_string(nid)) ) } @@ -2106,7 +2105,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } pub fn write_field_index(&self, node_id: ast::NodeId, index: usize) { - let hir_id = self.tcx.hir.node_to_hir_id(node_id); + let hir_id = self.tcx.hir().node_to_hir_id(node_id); self.tables.borrow_mut().field_indices_mut().insert(hir_id, index); } @@ -2294,7 +2293,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { parent_id: ast::NodeId, value: &T, ) -> T { - let parent_def_id = self.tcx.hir.local_def_id(parent_id); + let parent_def_id = self.tcx.hir().local_def_id(parent_id); debug!("instantiate_opaque_types_from_value(parent_def_id={:?}, value={:?})", parent_def_id, value); @@ -2400,9 +2399,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Some(&t) => t, None if self.is_tainted_by_errors() => self.tcx.types.err, None => { - let node_id = self.tcx.hir.hir_to_node_id(id); + let node_id = self.tcx.hir().hir_to_node_id(id); bug!("no type for node {}: {} in fcx {}", - node_id, self.tcx.hir.node_to_string(node_id), + node_id, self.tcx.hir().node_to_string(node_id), self.tag()); } } @@ -2558,7 +2557,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { while result.is_none() && autoderef.next().is_some() { result = self.try_index_step(expr, base_expr, &autoderef, needs, idx_ty); } - autoderef.finalize(); + autoderef.finalize(self); result } @@ -2575,7 +2574,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { index_ty: Ty<'tcx>) -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)> { - let adjusted_ty = autoderef.unambiguous_final_ty(); + let adjusted_ty = autoderef.unambiguous_final_ty(self); debug!("try_index_step(expr={:?}, base_expr={:?}, adjusted_ty={:?}, \ index_ty={:?})", expr, @@ -2605,7 +2604,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { debug!("try_index_step: success, using overloaded indexing"); let method = self.register_infer_ok_obligations(ok); - let mut adjustments = autoderef.adjust_steps(needs); + let mut adjustments = autoderef.adjust_steps(self, needs); if let ty::Ref(region, _, r_mutbl) = method.sig.inputs()[0].sty { let mutbl = match r_mutbl { hir::MutImmutable => AutoBorrowMutability::Immutable, @@ -2730,10 +2729,76 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ); self.check_argument_types(sp, expr_sp, &method.sig.inputs()[1..], &expected_arg_tys[..], args_no_rcvr, method.sig.variadic, tuple_arguments, - self.tcx.hir.span_if_local(method.def_id)); + self.tcx.hir().span_if_local(method.def_id)); method.sig.output() } + fn self_type_matches_expected_vid( + &self, + trait_ref: ty::PolyTraitRef<'tcx>, + expected_vid: ty::TyVid, + ) -> bool { + let self_ty = self.shallow_resolve(trait_ref.self_ty()); + debug!( + "self_type_matches_expected_vid(trait_ref={:?}, self_ty={:?}, expected_vid={:?})", + trait_ref, self_ty, expected_vid + ); + match self_ty.sty { + ty::Infer(ty::TyVar(found_vid)) => { + // FIXME: consider using `sub_root_var` here so we + // can see through subtyping. + let found_vid = self.root_var(found_vid); + debug!("self_type_matches_expected_vid - found_vid={:?}", found_vid); + expected_vid == found_vid + } + _ => false + } + } + + fn obligations_for_self_ty<'b>(&'b self, self_ty: ty::TyVid) + -> impl Iterator, traits::PredicateObligation<'tcx>)> + + Captures<'gcx> + 'b + { + // FIXME: consider using `sub_root_var` here so we + // can see through subtyping. + let ty_var_root = self.root_var(self_ty); + debug!("obligations_for_self_ty: self_ty={:?} ty_var_root={:?} pending_obligations={:?}", + self_ty, ty_var_root, + self.fulfillment_cx.borrow().pending_obligations()); + + self.fulfillment_cx + .borrow() + .pending_obligations() + .into_iter() + .filter_map(move |obligation| match obligation.predicate { + ty::Predicate::Projection(ref data) => + Some((data.to_poly_trait_ref(self.tcx), obligation)), + ty::Predicate::Trait(ref data) => + Some((data.to_poly_trait_ref(), obligation)), + ty::Predicate::Subtype(..) => None, + ty::Predicate::RegionOutlives(..) => None, + ty::Predicate::TypeOutlives(..) => None, + ty::Predicate::WellFormed(..) => None, + ty::Predicate::ObjectSafe(..) => None, + ty::Predicate::ConstEvaluatable(..) => None, + // N.B., this predicate is created by breaking down a + // `ClosureType: FnFoo()` predicate, where + // `ClosureType` represents some `Closure`. It can't + // possibly be referring to the current closure, + // because we haven't produced the `Closure` for + // this closure yet; this is exactly why the other + // code is looking for a self type of a unresolved + // inference variable. + ty::Predicate::ClosureKind(..) => None, + }).filter(move |(tr, _)| self.self_type_matches_expected_vid(*tr, ty_var_root)) + } + + fn type_var_is_sized(&self, self_ty: ty::TyVid) -> bool { + self.obligations_for_self_ty(self_ty).any(|(tr, _)| { + Some(tr.def_id()) == self.tcx.lang_items().sized_trait() + }) + } + /// Generic function that factors out common logic from function calls, /// method calls and overloaded operators. fn check_argument_types(&self, @@ -2857,10 +2922,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { formal_tys.iter().map(|t| self.ty_to_string(*t)).collect::>()); // Check the arguments. - // We do this in a pretty awful way: first we typecheck any arguments - // that are not closures, then we typecheck the closures. This is so + // We do this in a pretty awful way: first we type-check any arguments + // that are not closures, then we type-check the closures. This is so // that we have more information about the types of arguments when we - // typecheck the functions. This isn't really the right way to do this. + // type-check the functions. This isn't really the right way to do this. for &check_closures in &[false, true] { debug!("check_closures={}", check_closures); @@ -2884,7 +2949,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { for (i, arg) in args.iter().take(t).enumerate() { // Warn only for the first loop (the "no closures" one). // Closure arguments themselves can't be diverging, but - // a previous argument can, e.g. `foo(panic!(), || {})`. + // a previous argument can, e.g., `foo(panic!(), || {})`. if !check_closures { self.warn_if_unreachable(arg.id, arg.span, "expression"); } @@ -3091,9 +3156,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.check_expr_with_expectation_and_needs(expr, NoExpectation, needs) } - // determine the `self` type, using fresh variables for all variables + // Determine the `Self` type, using fresh variables for all variables // declared on the impl declaration e.g., `impl for Vec<(A,B)>` - // would return ($0, $1) where $0 and $1 are freshly instantiated type + // would return `($0, $1)` where `$0` and `$1` are freshly instantiated type // variables. pub fn impl_self_ty(&self, span: Span, // (potential) receiver for this impl @@ -3221,8 +3286,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { return_expr_ty); } - // A generic function for checking the then and else in an if - // or if-else. + // A generic function for checking the 'then' and 'else' clauses in an 'if' + // or 'if-else' expression. fn check_then_else(&self, cond_expr: &'gcx hir::Expr, then_expr: &'gcx hir::Expr, @@ -3299,9 +3364,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // of error recovery. self.write_field_index(expr.id, index); if field.vis.is_accessible_from(def_scope, self.tcx) { - let adjustments = autoderef.adjust_steps(needs); + let adjustments = autoderef.adjust_steps(self, needs); self.apply_adjustments(base, adjustments); - autoderef.finalize(); + autoderef.finalize(self); self.tcx.check_stability(field.did, Some(expr.id), expr.span); return field_ty; @@ -3314,9 +3379,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Ok(index) = fstr.parse::() { if fstr == index.to_string() { if let Some(field_ty) = tys.get(index) { - let adjustments = autoderef.adjust_steps(needs); + let adjustments = autoderef.adjust_steps(self, needs); self.apply_adjustments(base, adjustments); - autoderef.finalize(); + autoderef.finalize(self); self.write_field_index(expr.id, index); return field_ty; @@ -3327,7 +3392,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { _ => {} } } - autoderef.unambiguous_final_ty(); + autoderef.unambiguous_final_ty(self); if let Some((did, field_ty)) = private_candidate { let struct_path = self.tcx().item_path_str(did); @@ -3375,7 +3440,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { len.assert_usize(self.tcx), field.as_str().parse::() ) { - let base = self.tcx.hir.node_to_pretty_string(base.id); + 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 { @@ -3389,7 +3454,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } ty::RawPtr(..) => { - let base = self.tcx.hir.node_to_pretty_string(base.id); + 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_with_applicability( @@ -3538,17 +3603,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut error_happened = false; - // Typecheck each field. + // Type-check each field. for field in ast_fields { let ident = tcx.adjust_ident(field.ident, variant.did, self.body_id).0; let field_type = if let Some((i, v_field)) = remaining_fields.remove(&ident) { seen_fields.insert(ident, field.span); self.write_field_index(field.id, i); - // we don't look at stability attributes on + // We don't look at stability attributes on // struct-like enums (yet...), but it's definitely not - // a bug to have construct one. - if adt_kind != ty::AdtKind::Enum { + // a bug to have constructed one. + if adt_kind != AdtKind::Enum { tcx.check_stability(v_field.did, Some(expr_id), field.span); } @@ -3574,7 +3639,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; // Make sure to give a type to the field even if there's - // an error, so we can continue typechecking + // an error, so we can continue type-checking. self.check_expr_coercable_to_type(&field.expr, field_type); } @@ -3665,7 +3730,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some((variant, did, substs)) = variant { debug!("check_struct_path: did={:?} substs={:?}", did, substs); - let hir_id = self.tcx.hir.node_to_hir_id(node_id); + let hir_id = self.tcx.hir().node_to_hir_id(node_id); self.write_user_substs_from_substs(hir_id, substs, None); // Check bounds on type arguments used in the path. @@ -3706,7 +3771,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { hir::QPath::TypeRelative(ref qself, _) => qself.span }; - // Prohibit struct expressions when non exhaustive flag is set. + // Prohibit struct expressions when non-exhaustive flag is set. let adt = adt_ty.ty_adt_def().expect("`check_struct_path` returned non-ADT type"); if !adt.did.is_local() && variant.is_field_list_non_exhaustive() { span_err!(self.tcx.sess, expr.span, E0639, @@ -3759,7 +3824,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { expr: &'gcx hir::Expr, expected: Expectation<'tcx>, needs: Needs) -> Ty<'tcx> { - debug!(">> typechecking: expr={:?} expected={:?}", + debug!(">> type-checking: expr={:?} expected={:?}", expr, expected); // Warn for expressions after diverging siblings. @@ -3796,7 +3861,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.diverges.set(self.diverges.get() | old_diverges); self.has_errors.set(self.has_errors.get() | old_has_errors); - debug!("type of {} is...", self.tcx.hir.node_to_string(expr.id)); + debug!("type of {} is...", self.tcx.hir().node_to_string(expr.id)); debug!("... {:?}, expected is {:?}", ty, expected); ty @@ -3961,7 +4026,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if !tcx.features().unsized_locals { // We want to remove some Sized bounds from std functions, // but don't want to expose the removal to stable Rust. - // i.e. we don't want to allow + // i.e., we don't want to allow // // ```rust // drop as fn(str); @@ -3969,7 +4034,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // // to work in stable even if the Sized bound on `drop` is relaxed. for i in 0..fn_sig.inputs().skip_binder().len() { - let input = tcx.erase_late_bound_regions(&fn_sig.input(i)); + // We just want to check sizedness, so instead of introducing + // placeholder lifetimes with probing, we just replace higher lifetimes + // with fresh vars. + let input = self.replace_bound_vars_with_fresh_vars( + expr.span, + infer::LateBoundRegionConversionTime::FnCall, + &fn_sig.input(i)).0; self.require_type_is_sized_deferred(input, expr.span, traits::SizedArgumentType); } @@ -3977,7 +4048,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Here we want to prevent struct constructors from returning unsized types. // There were two cases this happened: fn pointer coercion in stable // and usual function call in presense of unsized_locals. - let output = tcx.erase_late_bound_regions(&fn_sig.output()); + // Also, as we just want to check sizedness, instead of introducing + // placeholder lifetimes with probing, we just replace higher lifetimes + // with fresh vars. + let output = self.replace_bound_vars_with_fresh_vars( + expr.span, + infer::LateBoundRegionConversionTime::FnCall, + &fn_sig.output()).0; self.require_type_is_sized_deferred(output, expr.span, traits::SizedReturnType); } @@ -4073,7 +4150,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } } - // There was an error, make typecheck fail + // There was an error; make type-check fail. tcx.types.err } @@ -4082,7 +4159,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if destination.target_id.is_ok() { tcx.types.never } else { - // There was an error, make typecheck fail + // There was an error; make type-check fail. tcx.types.err } } @@ -4267,7 +4344,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { tcx.mk_array(element_ty, args.len() as u64) } hir::ExprKind::Repeat(ref element, ref count) => { - let count_def_id = tcx.hir.local_def_id(count.id); + let count_def_id = tcx.hir().local_def_id(count.id); let param_env = ty::ParamEnv::empty(); let substs = Substs::identity_for_item(tcx.global_tcx(), count_def_id); let instance = ty::Instance::resolve( @@ -4400,7 +4477,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } if needs_note { err.help("to access tuple elements, use tuple indexing \ - syntax (e.g. `tuple.0`)"); + syntax (e.g., `tuple.0`)"); } } err.emit(); @@ -4450,7 +4527,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty, def, segment); // Write back the new resolution. - let hir_id = self.tcx.hir.node_to_hir_id(node_id); + let hir_id = self.tcx.hir().node_to_hir_id(node_id); self.tables.borrow_mut().type_dependent_defs_mut().insert(hir_id, def); (def, ty) @@ -4476,7 +4553,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { (self.to_ty(qself), segment) } }; - let hir_id = self.tcx.hir.node_to_hir_id(node_id); + let hir_id = self.tcx.hir().node_to_hir_id(node_id); if let Some(cached_def) = self.tables.borrow().type_dependent_defs().get(hir_id) { // Return directly on cache hit. This is useful to avoid doubly reporting // errors with default match binding modes. See #44614. @@ -4717,8 +4794,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn get_fn_decl(&self, blk_id: ast::NodeId) -> Option<(hir::FnDecl, bool)> { // Get enclosing Fn, if it is a function or a trait method, unless there's a `loop` or // `while` before reaching it, as block tail returns are not available in them. - if let Some(fn_id) = self.tcx.hir.get_return_block(blk_id) { - let parent = self.tcx.hir.get(fn_id); + if let Some(fn_id) = self.tcx.hir().get_return_block(blk_id) { + let parent = self.tcx.hir().get(fn_id); if let Node::Item(&hir::Item { name, node: hir::ItemKind::Fn(ref decl, ..), .. @@ -5109,7 +5186,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Def::Local(nid) | Def::Upvar(nid, ..) => { let ty = self.local_ty(span, nid).decl_ty; let ty = self.normalize_associated_types_in(span, &ty); - self.write_ty(self.tcx.hir.node_to_hir_id(node_id), ty); + self.write_ty(self.tcx.hir().node_to_hir_id(node_id), ty); return (ty, def); } _ => {} @@ -5148,26 +5225,48 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }).unwrap_or(false); let mut new_def = def; - let (def_id, ty) = if let Def::SelfCtor(impl_def_id) = def { - let ty = self.impl_self_ty(span, impl_def_id).ty; + let (def_id, ty) = match def { + Def::SelfCtor(impl_def_id) => { + let ty = self.impl_self_ty(span, impl_def_id).ty; + let adt_def = ty.ty_adt_def(); - match ty.ty_adt_def() { - Some(adt_def) if adt_def.is_struct() => { - let variant = adt_def.non_enum_variant(); - new_def = Def::StructCtor(variant.did, variant.ctor_kind); - (variant.did, self.tcx.type_of(variant.did)) - } - _ => { - (impl_def_id, self.tcx.types.err) + match adt_def { + Some(adt_def) if adt_def.has_ctor() => { + let variant = adt_def.non_enum_variant(); + new_def = Def::StructCtor(variant.did, variant.ctor_kind); + (variant.did, self.tcx.type_of(variant.did)) + } + _ => { + let mut err = self.tcx.sess.struct_span_err(span, + "the `Self` constructor can only be used with tuple or unit structs"); + if let Some(adt_def) = adt_def { + match adt_def.adt_kind() { + AdtKind::Enum => { + err.note("did you mean to use one of the enum's variants?"); + }, + AdtKind::Struct | + AdtKind::Union => { + err.span_label( + span, + format!("did you mean `Self {{ /* fields */ }}`?"), + ); + } + } + } + err.emit(); + + (impl_def_id, self.tcx.types.err) + } } } - } else { - let def_id = def.def_id(); + _ => { + let def_id = def.def_id(); - // The things we are substituting into the type should not contain - // escaping late-bound regions, and nor should the base type scheme. - let ty = self.tcx.type_of(def_id); - (def_id, ty) + // The things we are substituting into the type should not contain + // escaping late-bound regions, and nor should the base type scheme. + let ty = self.tcx.type_of(def_id); + (def_id, ty) + } }; let substs = AstConv::create_substs_for_generic_args( @@ -5236,8 +5335,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { assert!(!substs.has_escaping_bound_vars()); assert!(!ty.has_escaping_bound_vars()); - // Write the "user substs" down first thing for later. - let hir_id = self.tcx.hir.node_to_hir_id(node_id); + // First, store the "user substs" for later. + let hir_id = self.tcx.hir().node_to_hir_id(node_id); self.write_user_substs_from_substs(hir_id, substs, user_self_ty); // Add all the obligations that are required, substituting and @@ -5292,7 +5391,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // If our calling expression is indeed the function itself, we're good! // If not, generate an error that this can only be called directly. - if let Node::Expr(expr) = self.tcx.hir.get(self.tcx.hir.get_parent_node(node_id)) { + if let Node::Expr(expr) = self.tcx.hir().get(self.tcx.hir().get_parent_node(node_id)) { if let hir::ExprKind::Call(ref callee, ..) = expr.node { if callee.id == node_id { return @@ -5341,6 +5440,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; (ctxt, result) } + + /// Instantiate a QueryResponse in a probe context, without a + /// good ObligationCause. + fn probe_instantiate_query_response( + &self, + span: Span, + original_values: &OriginalQueryValues<'tcx>, + query_result: &Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>, + ) -> InferResult<'tcx, Ty<'tcx>> + { + self.instantiate_query_response_and_region_obligations( + &traits::ObligationCause::misc(span, self.body_id), + self.param_env, + original_values, + query_result) + } } pub fn check_bounds_are_used<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -5373,8 +5488,8 @@ pub fn check_bounds_are_used<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }); for (&used, param) in types_used.iter().zip(types) { if !used { - let id = tcx.hir.as_local_node_id(param.def_id).unwrap(); - let span = tcx.hir.span(id); + let id = tcx.hir().as_local_node_id(param.def_id).unwrap(); + let span = tcx.hir().span(id); struct_span_err!(tcx.sess, span, E0091, "type parameter `{}` is unused", param.name) .span_label(span, "unused type parameter") .emit(); diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index 54f4406b4af..c40789ce8ba 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -170,7 +170,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Find a suitable supertype of the LHS expression's type, by coercing to // a type variable, to pass as the `Self` to the trait, avoiding invariant // trait matching creating lifetime constraints that are too strict. - // E.g. adding `&'a T` and `&'b T`, given `&'x T: Add<&'x T>`, will result + // e.g., adding `&'a T` and `&'b T`, given `&'x T: Add<&'x T>`, will result // in `&'a T <: &'x T` and `&'b T <: &'x T`, instead of `'a = 'b = 'x`. let lhs_ty = self.check_expr_with_needs(lhs_expr, Needs::None); let fresh_var = self.next_ty_var(TypeVariableOrigin::MiscVariable(lhs_expr.span)); @@ -186,7 +186,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; let lhs_ty = self.resolve_type_vars_with_obligations(lhs_ty); - // NB: As we have not yet type-checked the RHS, we don't have the + // N.B., as we have not yet type-checked the RHS, we don't have the // type at hand. Make a variable to represent it. The whole reason // for this indirection is so that, below, we can check the expr // using this variable as the expected type, which sometimes lets @@ -318,7 +318,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.check_str_addition(expr, lhs_expr, rhs_expr, lhs_ty, rhs_ty, &mut err, true) { // This has nothing here because it means we did string - // concatenation (e.g. "Hello " += "World!"). This means + // concatenation (e.g., "Hello " += "World!"). This means // we don't want the note in the else clause to be emitted } else if let ty::Param(_) = lhs_ty.sty { // FIXME: point to span of param @@ -392,7 +392,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.check_str_addition(expr, lhs_expr, rhs_expr, lhs_ty, rhs_ty, &mut err, false) { // This has nothing here because it means we did string - // concatenation (e.g. "Hello " + "World!"). This means + // concatenation (e.g., "Hello " + "World!"). This means // we don't want the note in the else clause to be emitted } else if let ty::Param(_) = lhs_ty.sty { // FIXME: point to span of param @@ -682,7 +682,7 @@ enum Op { Unary(hir::UnOp, Span), } -/// Returns true if this is a built-in arithmetic operation (e.g. u32 +/// Returns true if this is a built-in arithmetic operation (e.g., u32 /// + u32, i16x4 == i16x4) and false if these types would have to be /// overloaded to be legal. There are two reasons that we distinguish /// builtin operations from overloaded ones (vs trying to drive diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 212ee2698e0..7960d743de5 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -121,7 +121,7 @@ macro_rules! ignore_err { impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn regionck_expr(&self, body: &'gcx hir::Body) { - let subject = self.tcx.hir.body_owner_def_id(body.id()); + let subject = self.tcx.hir().body_owner_def_id(body.id()); let id = body.value.id; let mut rcx = RegionCtxt::new( self, @@ -150,7 +150,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { /// types from which we should derive implied bounds, if any. pub fn regionck_item(&self, item_id: ast::NodeId, span: Span, wf_tys: &[Ty<'tcx>]) { debug!("regionck_item(item.id={:?}, wf_tys={:?})", item_id, wf_tys); - let subject = self.tcx.hir.local_def_id(item_id); + let subject = self.tcx.hir().local_def_id(item_id); let mut rcx = RegionCtxt::new( self, RepeatingScope(item_id), @@ -175,7 +175,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { /// constraints to add. pub fn regionck_fn(&self, fn_id: ast::NodeId, body: &'gcx hir::Body) { debug!("regionck_fn(id={})", fn_id); - let subject = self.tcx.hir.body_owner_def_id(body.id()); + let subject = self.tcx.hir().body_owner_def_id(body.id()); let node_id = body.value.id; let mut rcx = RegionCtxt::new( self, @@ -187,7 +187,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if self.err_count_since_creation() == 0 { // regionck assumes typeck succeeded - rcx.visit_fn_body(fn_id, body, self.tcx.hir.span(fn_id)); + rcx.visit_fn_body(fn_id, body, self.tcx.hir().span(fn_id)); } rcx.resolve_regions_and_report_errors(SuppressRegionErrors::when_nll_is_enabled(self.tcx)); @@ -328,7 +328,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { self.call_site_scope = Some(call_site); let fn_sig = { - let fn_hir_id = self.tcx.hir.node_to_hir_id(id); + let fn_hir_id = self.tcx.hir().node_to_hir_id(id); match self.tables.borrow().liberated_fn_sigs().get(fn_hir_id) { Some(f) => f.clone(), None => { @@ -375,7 +375,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { ); let call_site_region = self.tcx.mk_region(ty::ReScope(call_site_scope)); - let body_hir_id = self.tcx.hir.node_to_hir_id(body_id.node_id); + let body_hir_id = self.tcx.hir().node_to_hir_id(body_id.node_id); self.type_of_node_must_outlive(infer::CallReturn(span), body_hir_id, call_site_region); self.constrain_opaque_types( @@ -483,7 +483,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> { let old_call_site_scope = self.call_site_scope; let env_snapshot = self.outlives_environment.push_snapshot_pre_closure(); - let body = self.tcx.hir.body(body_id); + let body = self.tcx.hir().body(body_id); self.visit_fn_body(id, body, span); // Restore state from previous function. diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 312ce402775..562022cefa8 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -74,7 +74,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for InferBorrowKindVisitor<'a, 'gcx, 'tcx> { fn visit_expr(&mut self, expr: &'gcx hir::Expr) { if let hir::ExprKind::Closure(cc, _, body_id, _, _) = expr.node { - let body = self.fcx.tcx.hir.body(body_id); + let body = self.fcx.tcx.hir().body(body_id); self.visit_body(body); self.fcx .analyze_closure(expr.id, expr.hir_id, expr.span, body, cc); @@ -135,7 +135,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { for freevar in freevars { let upvar_id = ty::UpvarId { var_path: ty::UpvarPath { - hir_id : self.tcx.hir.node_to_hir_id(freevar.var_id()), + hir_id : self.tcx.hir().node_to_hir_id(freevar.var_id()), }, closure_expr_id: LocalDefId::from_def_id(closure_def_id), }; @@ -161,7 +161,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } }); - let body_owner_def_id = self.tcx.hir.body_owner_def_id(body.id()); + let body_owner_def_id = self.tcx.hir().body_owner_def_id(body.id()); let region_scope_tree = &self.tcx.region_scope_tree(body_owner_def_id); let mut delegate = InferBorrowKind { fcx: self, @@ -240,14 +240,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // This may change if abstract return types of some sort are // implemented. let tcx = self.tcx; - let closure_def_index = tcx.hir.local_def_id(closure_id); + let closure_def_index = tcx.hir().local_def_id(closure_id); tcx.with_freevars(closure_id, |freevars| { freevars .iter() .map(|freevar| { let var_node_id = freevar.var_id(); - let var_hir_id = tcx.hir.node_to_hir_id(var_node_id); + let var_hir_id = tcx.hir().node_to_hir_id(var_node_id); let freevar_ty = self.node_ty(var_hir_id); let upvar_id = ty::UpvarId { var_path: ty::UpvarPath { @@ -647,6 +647,6 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'gcx, 'tcx> { } fn var_name(tcx: TyCtxt, var_hir_id: hir::HirId) -> ast::Name { - let var_node_id = tcx.hir.hir_to_node_id(var_hir_id); - tcx.hir.name(var_node_id) + let var_node_id = tcx.hir().hir_to_node_id(var_hir_id); + tcx.hir().name(var_node_id) } diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index e5fe74f2305..e74b1ae47e3 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -13,9 +13,8 @@ use constrained_type_params::{identify_constrained_type_params, Parameter}; use hir::def_id::DefId; use rustc::traits::{self, ObligationCauseCode}; -use rustc::ty::{self, Lift, Ty, TyCtxt, TyKind, GenericParamDefKind, TypeFoldable}; +use rustc::ty::{self, Lift, Ty, TyCtxt, TyKind, GenericParamDefKind, TypeFoldable, ToPredicate}; use rustc::ty::subst::{Subst, Substs}; -use rustc::ty::util::ExplicitSelf; use rustc::util::nodemap::{FxHashSet, FxHashMap}; use rustc::middle::lang_items; use rustc::infer::opaque_types::may_define_existential_type; @@ -73,8 +72,8 @@ impl<'a, 'gcx, 'tcx> CheckWfFcxBuilder<'a, 'gcx, 'tcx> { /// not included it frequently leads to confusing errors in fn bodies. So it's better to check /// the types first. pub fn check_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { - let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); - let item = tcx.hir.expect_item(node_id); + let node_id = tcx.hir().as_local_node_id(def_id).unwrap(); + let item = tcx.hir().expect_item(node_id); debug!("check_item_well_formed(it.id={}, it.name={})", item.id, @@ -99,7 +98,7 @@ pub fn check_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: Def // won't be allowed unless there's an *explicit* implementation of `Send` // for `T` hir::ItemKind::Impl(_, polarity, defaultness, _, ref trait_ref, ref self_ty, _) => { - let is_auto = tcx.impl_trait_ref(tcx.hir.local_def_id(item.id)) + let is_auto = tcx.impl_trait_ref(tcx.hir().local_def_id(item.id)) .map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.def_id)); if let (hir::Defaultness::Default { .. }, true) = (defaultness, is_auto) { tcx.sess.span_err(item.span, "impls of auto traits cannot be default"); @@ -161,8 +160,8 @@ pub fn check_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: Def } pub fn check_trait_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { - let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); - let trait_item = tcx.hir.expect_trait_item(node_id); + let node_id = tcx.hir().as_local_node_id(def_id).unwrap(); + let trait_item = tcx.hir().expect_trait_item(node_id); let method_sig = match trait_item.node { hir::TraitItemKind::Method(ref sig, _) => Some(sig), @@ -172,8 +171,8 @@ pub fn check_trait_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { } pub fn check_impl_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { - let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); - let impl_item = tcx.hir.expect_impl_item(node_id); + let node_id = tcx.hir().as_local_node_id(def_id).unwrap(); + let impl_item = tcx.hir().expect_impl_item(node_id); let method_sig = match impl_item.node { hir::ImplItemKind::Method(ref sig, _) => Some(sig), @@ -190,7 +189,7 @@ fn check_associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let code = ObligationCauseCode::MiscObligation; for_id(tcx, item_id, span).with_fcx(|fcx, tcx| { - let item = fcx.tcx.associated_item(fcx.tcx.hir.local_def_id(item_id)); + let item = fcx.tcx.associated_item(fcx.tcx.hir().local_def_id(item_id)); let (mut implied_bounds, self_ty) = match item.container { ty::TraitContainer(_) => (vec![], fcx.tcx.mk_self_type()), @@ -236,7 +235,7 @@ fn for_item<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, item: &hir::Item) fn for_id<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, id: ast::NodeId, span: Span) -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> { - let def_id = tcx.hir.local_def_id(id); + let def_id = tcx.hir().local_def_id(id); CheckWfFcxBuilder { inherited: Inherited::build(tcx, def_id), id, @@ -252,7 +251,7 @@ fn check_type_defn<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>, { for_item(tcx, item).with_fcx(|fcx, fcx_tcx| { let variants = lookup_fields(fcx); - let def_id = fcx.tcx.hir.local_def_id(item.id); + let def_id = fcx.tcx.hir().local_def_id(item.id); let packed = fcx.tcx.adt_def(def_id).repr.packed(); for variant in &variants { @@ -315,7 +314,7 @@ fn check_type_defn<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn check_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item) { debug!("check_trait: {:?}", item.id); - let trait_def_id = tcx.hir.local_def_id(item.id); + let trait_def_id = tcx.hir().local_def_id(item.id); let trait_def = tcx.trait_def(trait_def_id); if trait_def.is_marker { @@ -337,7 +336,7 @@ fn check_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item) { fn check_item_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item) { for_item(tcx, item).with_fcx(|fcx, tcx| { - let def_id = fcx.tcx.hir.local_def_id(item.id); + let def_id = fcx.tcx.hir().local_def_id(item.id); let sig = fcx.tcx.fn_sig(def_id); let sig = fcx.normalize_associated_types_in(item.span, &sig); let mut implied_bounds = vec![]; @@ -356,7 +355,7 @@ fn check_item_type<'a, 'tcx>( debug!("check_item_type: {:?}", item_id); for_id(tcx, item_id, ty_span).with_fcx(|fcx, gcx| { - let ty = gcx.type_of(gcx.hir.local_def_id(item_id)); + let ty = gcx.type_of(gcx.hir().local_def_id(item_id)); let item_ty = fcx.normalize_associated_types_in(ty_span, &ty); let mut forbid_unsized = true; @@ -387,7 +386,7 @@ fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, debug!("check_impl: {:?}", item); for_item(tcx, item).with_fcx(|fcx, tcx| { - let item_def_id = fcx.tcx.hir.local_def_id(item.id); + let item_def_id = fcx.tcx.hir().local_def_id(item.id); match *ast_trait_ref { Some(ref ast_trait_ref) => { @@ -621,7 +620,7 @@ fn check_existential_types<'a, 'fcx, 'gcx, 'tcx>( let generics = tcx.generics_of(def_id); // only check named existential types if generics.parent.is_none() { - let opaque_node_id = tcx.hir.as_local_node_id(def_id).unwrap(); + let opaque_node_id = tcx.hir().as_local_node_id(def_id).unwrap(); if may_define_existential_type(tcx, fn_def_id, opaque_node_id) { trace!("check_existential_types may define. Generics: {:#?}", generics); let mut seen: FxHashMap<_, Vec<_>> = FxHashMap::default(); @@ -749,79 +748,156 @@ fn check_method_receiver<'fcx, 'gcx, 'tcx>(fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, &ty::Binder::bind(self_ty) ); - let self_arg_ty = sig.inputs()[0]; + let receiver_ty = sig.inputs()[0]; - let cause = fcx.cause(span, ObligationCauseCode::MethodReceiver); - let self_arg_ty = fcx.normalize_associated_types_in(span, &self_arg_ty); - let self_arg_ty = fcx.tcx.liberate_late_bound_regions( + let receiver_ty = fcx.normalize_associated_types_in(span, &receiver_ty); + let receiver_ty = fcx.tcx.liberate_late_bound_regions( method.def_id, - &ty::Binder::bind(self_arg_ty) + &ty::Binder::bind(receiver_ty) ); - let mut autoderef = fcx.autoderef(span, self_arg_ty).include_raw_pointers(); - - loop { - if let Some((potential_self_ty, _)) = autoderef.next() { - debug!("check_method_receiver: potential self type `{:?}` to match `{:?}`", - potential_self_ty, self_ty); - - if fcx.infcx.can_eq(fcx.param_env, self_ty, potential_self_ty).is_ok() { - autoderef.finalize(); - if let Some(mut err) = fcx.demand_eqtype_with_origin( - &cause, self_ty, potential_self_ty) { - err.emit(); - } - break - } - } else { + if fcx.tcx.features().arbitrary_self_types { + if !receiver_is_valid(fcx, span, receiver_ty, self_ty, true) { + // report error, arbitrary_self_types was enabled fcx.tcx.sess.diagnostic().mut_span_err( - span, &format!("invalid `self` type: {:?}", self_arg_ty)) - .note(&format!("type must be `{:?}` or a type that dereferences to it", self_ty)) + span, &format!("invalid method receiver type: {:?}", receiver_ty) + ).note("type of `self` must be `Self` or a type that dereferences to it") .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box`") .code(DiagnosticId::Error("E0307".into())) .emit(); - return } - } - - let is_self_ty = |ty| fcx.infcx.can_eq(fcx.param_env, self_ty, ty).is_ok(); - let self_kind = ExplicitSelf::determine(self_arg_ty, is_self_ty); - - if !fcx.tcx.features().arbitrary_self_types { - match self_kind { - ExplicitSelf::ByValue | - ExplicitSelf::ByReference(_, _) | - ExplicitSelf::ByBox => (), - - ExplicitSelf::ByRawPointer(_) => { + } else { + if !receiver_is_valid(fcx, span, receiver_ty, self_ty, false) { + if receiver_is_valid(fcx, span, receiver_ty, self_ty, true) { + // report error, would have worked with arbitrary_self_types feature_gate::feature_err( &fcx.tcx.sess.parse_sess, "arbitrary_self_types", span, GateIssue::Language, - "raw pointer `self` is unstable") - .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box`") + &format!( + "`{}` cannot be used as the type of `self` without \ + the `arbitrary_self_types` feature", + receiver_ty, + ), + ).help("consider changing to `self`, `&self`, `&mut self`, or `self: Box`") .emit(); - } - - ExplicitSelf::Other => { - feature_gate::feature_err( - &fcx.tcx.sess.parse_sess, - "arbitrary_self_types", - span, - GateIssue::Language,"arbitrary `self` types are unstable") + } else { + // report error, would not have worked with arbitrary_self_types + fcx.tcx.sess.diagnostic().mut_span_err( + span, &format!("invalid method receiver type: {:?}", receiver_ty) + ).note("type must be `Self` or a type that dereferences to it") .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box`") + .code(DiagnosticId::Error("E0307".into())) .emit(); } } } } +/// returns true if `receiver_ty` would be considered a valid receiver type for `self_ty`. If +/// `arbitrary_self_types` is enabled, `receiver_ty` must transitively deref to `self_ty`, possibly +/// through a `*const/mut T` raw pointer. If the feature is not enabled, the requirements are more +/// strict: `receiver_ty` must implement `Receiver` and directly implement `Deref`. +/// +/// NB: there are cases this function returns `true` but causes an error to be emitted, +/// particularly when `receiver_ty` derefs to a type that is the same as `self_ty` but has the +/// wrong lifetime. Be careful of this if you are calling this function speculatively. +fn receiver_is_valid<'fcx, 'tcx, 'gcx>( + fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, + span: Span, + receiver_ty: Ty<'tcx>, + self_ty: Ty<'tcx>, + arbitrary_self_types_enabled: bool, +) -> bool { + let cause = fcx.cause(span, traits::ObligationCauseCode::MethodReceiver); + + let can_eq_self = |ty| fcx.infcx.can_eq(fcx.param_env, self_ty, ty).is_ok(); + + // `self: Self` is always valid + if can_eq_self(receiver_ty) { + if let Some(mut err) = fcx.demand_eqtype_with_origin(&cause, self_ty, receiver_ty) { + err.emit(); + } + return true + } + + let mut autoderef = fcx.autoderef(span, receiver_ty); + + // the `arbitrary_self_types` feature allows raw pointer receivers like `self: *const Self` + if arbitrary_self_types_enabled { + autoderef = autoderef.include_raw_pointers(); + } + + // the first type is `receiver_ty`, which we know its not equal to `self_ty`. skip it. + autoderef.next(); + + // keep dereferencing `receiver_ty` until we get to `self_ty` + loop { + if let Some((potential_self_ty, _)) = autoderef.next() { + debug!("receiver_is_valid: potential self type `{:?}` to match `{:?}`", + potential_self_ty, self_ty); + + if can_eq_self(potential_self_ty) { + autoderef.finalize(fcx); + + if let Some(mut err) = fcx.demand_eqtype_with_origin( + &cause, self_ty, potential_self_ty + ) { + err.emit(); + } + + break + } + } else { + debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`", + receiver_ty, self_ty); + return false + } + + // without the `arbitrary_self_types` feature, `receiver_ty` must directly deref to + // `self_ty`. Enforce this by only doing one iteration of the loop + if !arbitrary_self_types_enabled { + return false + } + } + + // without `feature(arbitrary_self_types)`, we require that `receiver_ty` implements `Receiver` + if !arbitrary_self_types_enabled { + let trait_def_id = match fcx.tcx.lang_items().receiver_trait() { + Some(did) => did, + None => { + debug!("receiver_is_valid: missing Receiver trait"); + return false + } + }; + + let trait_ref = ty::TraitRef{ + def_id: trait_def_id, + substs: fcx.tcx.mk_substs_trait(receiver_ty, &[]), + }; + + let obligation = traits::Obligation::new( + cause.clone(), + fcx.param_env, + trait_ref.to_predicate() + ); + + if !fcx.predicate_must_hold(&obligation) { + debug!("receiver_is_valid: type `{:?}` does not implement `Receiver` trait", + receiver_ty); + return false + } + } + + true +} + fn check_variances_for_type_defn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item, hir_generics: &hir::Generics) { - let item_def_id = tcx.hir.local_def_id(item.id); + let item_def_id = tcx.hir().local_def_id(item.id); let ty = tcx.type_of(item_def_id); if tcx.has_error_field(ty) { return; @@ -908,7 +984,7 @@ fn check_false_global_bounds<'a, 'gcx, 'tcx>( let empty_env = ty::ParamEnv::empty(); - let def_id = fcx.tcx.hir.local_def_id(id); + let def_id = fcx.tcx.hir().local_def_id(id); let predicates = fcx.tcx.predicates_of(def_id).predicates .iter() .map(|(p, _)| *p) @@ -956,21 +1032,21 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'a, 'tcx> { fn visit_item(&mut self, i: &hir::Item) { debug!("visit_item: {:?}", i); - let def_id = self.tcx.hir.local_def_id(i.id); + let def_id = self.tcx.hir().local_def_id(i.id); ty::query::queries::check_item_well_formed::ensure(self.tcx, def_id); intravisit::walk_item(self, i); } fn visit_trait_item(&mut self, trait_item: &'v hir::TraitItem) { debug!("visit_trait_item: {:?}", trait_item); - let def_id = self.tcx.hir.local_def_id(trait_item.id); + let def_id = self.tcx.hir().local_def_id(trait_item.id); ty::query::queries::check_trait_item_well_formed::ensure(self.tcx, def_id); intravisit::walk_trait_item(self, trait_item) } fn visit_impl_item(&mut self, impl_item: &'v hir::ImplItem) { debug!("visit_impl_item: {:?}", impl_item); - let def_id = self.tcx.hir.local_def_id(impl_item.id); + let def_id = self.tcx.hir().local_def_id(impl_item.id); ty::query::queries::check_impl_item_well_formed::ensure(self.tcx, def_id); intravisit::walk_impl_item(self, impl_item) } @@ -991,7 +1067,7 @@ struct AdtField<'tcx> { impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn non_enum_variant(&self, struct_def: &hir::VariantData) -> AdtVariant<'tcx> { let fields = struct_def.fields().iter().map(|field| { - let field_ty = self.tcx.type_of(self.tcx.hir.local_def_id(field.id)); + let field_ty = self.tcx.type_of(self.tcx.hir().local_def_id(field.id)); let field_ty = self.normalize_associated_types_in(field.span, &field_ty); AdtField { ty: field_ty, span: field.span } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 669f2bcb77c..8d7fc008fb0 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -32,8 +32,8 @@ use syntax_pos::Span; impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn resolve_type_vars_in_body(&self, body: &'gcx hir::Body) -> &'gcx ty::TypeckTables<'gcx> { - let item_id = self.tcx.hir.body_owner(body.id()); - let item_def_id = self.tcx.hir.local_def_id(item_id); + let item_id = self.tcx.hir().body_owner(body.id()); + let item_def_id = self.tcx.hir().local_def_id(item_id); // This attribute causes us to dump some writeback information // in the form of errors, which is used for unit tests. @@ -99,7 +99,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { body: &'gcx hir::Body, rustc_dump_user_substs: bool, ) -> WritebackCx<'cx, 'gcx, 'tcx> { - let owner = fcx.tcx.hir.definitions().node_to_hir_id(body.id().node_id); + let owner = fcx.tcx.hir().definitions().node_to_hir_id(body.id().node_id); WritebackCx { fcx, @@ -233,7 +233,7 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> { match e.node { hir::ExprKind::Closure(_, _, body, _, _) => { - let body = self.fcx.tcx.hir.body(body); + let body = self.fcx.tcx.hir().body(body); for arg in &body.arguments { self.visit_node_id(e.span, arg.hir_id); } @@ -398,7 +398,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { c_sig } else { span_bug!( - self.fcx.tcx.hir.span_if_local(def_id).unwrap(), + self.fcx.tcx.hir().span_if_local(def_id).unwrap(), "writeback: `{:?}` missing from the global type context", c_sig ); @@ -412,7 +412,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { fn visit_opaque_types(&mut self, span: Span) { for (&def_id, opaque_defn) in self.fcx.opaque_types.borrow().iter() { - let node_id = self.tcx().hir.as_local_node_id(def_id).unwrap(); + let node_id = self.tcx().hir().as_local_node_id(def_id).unwrap(); let instantiated_ty = self.resolve(&opaque_defn.concrete_ty, &node_id); let generics = self.tcx().generics_of(def_id); @@ -545,7 +545,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { } fn visit_field_id(&mut self, node_id: ast::NodeId) { - let hir_id = self.tcx().hir.node_to_hir_id(node_id); + let hir_id = self.tcx().hir().node_to_hir_id(node_id); if let Some(index) = self.fcx .tables .borrow_mut() @@ -591,8 +591,8 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { // Unit-testing mechanism: if self.rustc_dump_user_substs { - let node_id = self.tcx().hir.hir_to_node_id(hir_id); - let span = self.tcx().hir.span(node_id); + let node_id = self.tcx().hir().hir_to_node_id(hir_id); + let span = self.tcx().hir().span(node_id); self.tcx().sess.span_err( span, &format!("user substs: {:?}", user_substs), @@ -710,21 +710,21 @@ impl Locatable for Span { impl Locatable for ast::NodeId { fn to_span(&self, tcx: &TyCtxt) -> Span { - tcx.hir.span(*self) + tcx.hir().span(*self) } } impl Locatable for DefIndex { fn to_span(&self, tcx: &TyCtxt) -> Span { - let node_id = tcx.hir.def_index_to_node_id(*self); - tcx.hir.span(node_id) + let node_id = tcx.hir().def_index_to_node_id(*self); + tcx.hir().span(node_id) } } impl Locatable for hir::HirId { fn to_span(&self, tcx: &TyCtxt) -> Span { - let node_id = tcx.hir.hir_to_node_id(*self); - tcx.hir.span(node_id) + let node_id = tcx.hir().hir_to_node_id(*self); + tcx.hir().span(node_id) } } diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs index 9c1860fb82e..e6171e9da3b 100644 --- a/src/librustc_typeck/check_unused.rs +++ b/src/librustc_typeck/check_unused.rs @@ -25,15 +25,15 @@ use rustc_data_structures::fx::FxHashMap; pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let mut used_trait_imports = DefIdSet::default(); - for &body_id in tcx.hir.krate().bodies.keys() { - let item_def_id = tcx.hir.body_owner_def_id(body_id); + for &body_id in tcx.hir().krate().bodies.keys() { + let item_def_id = tcx.hir().body_owner_def_id(body_id); let imports = tcx.used_trait_imports(item_def_id); debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports); used_trait_imports.extend(imports.iter()); } let mut visitor = CheckVisitor { tcx, used_trait_imports }; - tcx.hir.krate().visit_all_item_likes(&mut visitor); + tcx.hir().krate().visit_all_item_likes(&mut visitor); unused_crates_lint(tcx); } @@ -62,12 +62,12 @@ struct CheckVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> CheckVisitor<'a, 'tcx> { fn check_import(&self, id: ast::NodeId, span: Span) { - let def_id = self.tcx.hir.local_def_id(id); + let def_id = self.tcx.hir().local_def_id(id); if !self.tcx.maybe_unused_trait_import(def_id) { return; } - let import_def_id = self.tcx.hir.local_def_id(id); + let import_def_id = self.tcx.hir().local_def_id(id); if self.used_trait_imports.contains(&import_def_id) { return; } @@ -105,8 +105,8 @@ fn unused_crates_lint<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) { // Note that if we carry through to the `extern_mod_stmt_cnum` query // below it'll cause a panic because `def_id` is actually bogus at this // point in time otherwise. - if let Some(id) = tcx.hir.as_local_node_id(def_id) { - if tcx.hir.find(id).is_none() { + if let Some(id) = tcx.hir().as_local_node_id(def_id) { + if tcx.hir().find(id).is_none() { return false; } } @@ -125,14 +125,14 @@ fn unused_crates_lint<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) { // Collect all the extern crates (in a reliable order). let mut crates_to_lint = vec![]; - tcx.hir.krate().visit_all_item_likes(&mut CollectExternCrateVisitor { + tcx.hir().krate().visit_all_item_likes(&mut CollectExternCrateVisitor { tcx, crates_to_lint: &mut crates_to_lint, }); for extern_crate in &crates_to_lint { - let id = tcx.hir.as_local_node_id(extern_crate.def_id).unwrap(); - let item = tcx.hir.expect_item(id); + let id = tcx.hir().as_local_node_id(extern_crate.def_id).unwrap(); + let item = tcx.hir().expect_item(id); // If the crate is fully unused, we suggest removing it altogether. // We do this in any edition. @@ -223,7 +223,7 @@ struct ExternCrateToLint { impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CollectExternCrateVisitor<'a, 'tcx> { fn visit_item(&mut self, item: &hir::Item) { if let hir::ItemKind::ExternCrate(orig_name) = item.node { - let extern_crate_def_id = self.tcx.hir.local_def_id(item.id); + let extern_crate_def_id = self.tcx.hir().local_def_id(item.id); self.crates_to_lint.push( ExternCrateToLint { def_id: extern_crate_def_id, diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index a5ad31e0b6b..2d5dcf0ec1b 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -46,8 +46,8 @@ impl<'a, 'tcx> Checker<'a, 'tcx> { where F: FnMut(TyCtxt<'a, 'tcx, 'tcx>, DefId) { if Some(self.trait_def_id) == trait_def_id { - for &impl_id in self.tcx.hir.trait_impls(self.trait_def_id) { - let impl_def_id = self.tcx.hir.local_def_id(impl_id); + for &impl_id in self.tcx.hir().trait_impls(self.trait_def_id) { + let impl_def_id = self.tcx.hir().local_def_id(impl_id); f(self.tcx, impl_def_id); } } @@ -60,8 +60,8 @@ fn visit_implementation_of_drop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_did: /* do nothing */ } else { // Destructors only work on nominal types. - if let Some(impl_node_id) = tcx.hir.as_local_node_id(impl_did) { - if let Some(Node::Item(item)) = tcx.hir.find(impl_node_id) { + if let Some(impl_node_id) = tcx.hir().as_local_node_id(impl_did) { + if let Some(Node::Item(item)) = tcx.hir().find(impl_node_id) { let span = match item.node { ItemKind::Impl(.., ref ty, _) => ty.span, _ => item.span, @@ -86,7 +86,7 @@ fn visit_implementation_of_drop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_did: fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_did: DefId) { debug!("visit_implementation_of_copy: impl_did={:?}", impl_did); - let impl_node_id = if let Some(n) = tcx.hir.as_local_node_id(impl_did) { + let impl_node_id = if let Some(n) = tcx.hir().as_local_node_id(impl_did) { n } else { debug!("visit_implementation_of_copy(): impl not in this crate"); @@ -97,7 +97,7 @@ fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_did: debug!("visit_implementation_of_copy: self_type={:?} (bound)", self_type); - let span = tcx.hir.span(impl_node_id); + let span = tcx.hir().span(impl_node_id); let param_env = tcx.param_env(impl_did); assert!(!self_type.has_escaping_bound_vars()); @@ -107,7 +107,7 @@ fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_did: match param_env.can_type_implement_copy(tcx, self_type) { Ok(()) => {} Err(CopyImplementationError::InfrigingFields(fields)) => { - let item = tcx.hir.expect_item(impl_node_id); + let item = tcx.hir().expect_item(impl_node_id); let span = if let ItemKind::Impl(.., Some(ref tr), _, _) = item.node { tr.path.span } else { @@ -124,7 +124,7 @@ fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_did: err.emit() } Err(CopyImplementationError::NotAnAdt) => { - let item = tcx.hir.expect_item(impl_node_id); + let item = tcx.hir().expect_item(impl_node_id); let span = if let ItemKind::Impl(.., ref ty, _) = item.node { ty.span } else { @@ -172,8 +172,8 @@ fn visit_implementation_of_dispatch_from_dyn<'a, 'tcx>( if impl_did.is_local() { let dispatch_from_dyn_trait = tcx.lang_items().dispatch_from_dyn_trait().unwrap(); - let impl_node_id = tcx.hir.as_local_node_id(impl_did).unwrap(); - let span = tcx.hir.span(impl_node_id); + let impl_node_id = tcx.hir().as_local_node_id(impl_did).unwrap(); + let span = tcx.hir().span(impl_node_id); let source = tcx.type_of(impl_did); assert!(!source.has_escaping_bound_vars()); @@ -342,7 +342,7 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>, }); // this provider should only get invoked for local def-ids - let impl_node_id = gcx.hir.as_local_node_id(impl_did).unwrap_or_else(|| { + let impl_node_id = gcx.hir().as_local_node_id(impl_did).unwrap_or_else(|| { bug!("coerce_unsized_info: invoked for non-local def-id {:?}", impl_did) }); @@ -354,7 +354,7 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>, source, target); - let span = gcx.hir.span(impl_node_id); + let span = gcx.hir().span(impl_node_id); let param_env = gcx.param_env(impl_did); assert!(!source.has_escaping_bound_vars()); @@ -469,7 +469,7 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>, // variance where possible. (This is because // we may have to evaluate constraint // expressions in the course of execution.) - // See e.g. #41936. + // See e.g., #41936. if let Ok(ok) = infcx.at(&cause, param_env).eq(a, b) { if ok.obligations.is_empty() { return None; @@ -477,7 +477,7 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>, } // Collect up all fields that were significantly changed - // i.e. those that contain T in coerce_unsized T -> U + // i.e., those that contain T in coerce_unsized T -> U Some((i, a, b)) }) .collect::>(); @@ -491,11 +491,11 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>, being coerced, none found"); return err_info; } else if diff_fields.len() > 1 { - let item = gcx.hir.expect_item(impl_node_id); + let item = gcx.hir().expect_item(impl_node_id); let span = if let ItemKind::Impl(.., Some(ref t), _, _) = item.node { t.path.span } else { - gcx.hir.span(impl_node_id) + gcx.hir().span(impl_node_id) }; let mut err = struct_span_err!(gcx.sess, diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs index d9dff144129..59989a65d4f 100644 --- a/src/librustc_typeck/coherence/inherent_impls.rs +++ b/src/librustc_typeck/coherence/inherent_impls.rs @@ -33,7 +33,7 @@ pub fn crate_inherent_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, -> Lrc { assert_eq!(crate_num, LOCAL_CRATE); - let krate = tcx.hir.krate(); + let krate = tcx.hir().krate(); let mut collect = InherentCollect { tcx, impls_map: Default::default(), @@ -95,7 +95,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { _ => return }; - let def_id = self.tcx.hir.local_def_id(item.id); + let def_id = self.tcx.hir().local_def_id(item.id); let self_ty = self.tcx.type_of(def_id); let lang_items = self.tcx.lang_items(); match self_ty.sty { @@ -298,7 +298,7 @@ impl<'a, 'tcx> InherentCollect<'a, 'tcx> { // Add the implementation to the mapping from implementation to base // type def ID, if there is a base type for this implementation and // the implementation does not have any associated traits. - let impl_def_id = self.tcx.hir.local_def_id(item.id); + let impl_def_id = self.tcx.hir().local_def_id(item.id); let mut rc_vec = self.impls_map.inherent_impls .entry(def_id) .or_default(); diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs index c0260d6714d..c273c8f6456 100644 --- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs +++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs @@ -12,15 +12,16 @@ use namespace::Namespace; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc::hir; use rustc::hir::itemlikevisit::ItemLikeVisitor; -use rustc::traits::{self, IntercrateMode}; +use rustc::traits::{self, IntercrateMode, FutureCompatOverlapErrorKind}; use rustc::ty::TyCtxt; +use rustc::ty::relate::TraitObjectMode; use lint; pub fn crate_inherent_impls_overlap_check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) { assert_eq!(crate_num, LOCAL_CRATE); - let krate = tcx.hir.krate(); + let krate = tcx.hir().krate(); krate.visit_all_item_likes(&mut InherentOverlapChecker { tcx }); } @@ -29,9 +30,11 @@ struct InherentOverlapChecker<'a, 'tcx: 'a> { } impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> { - fn check_for_common_items_in_impls(&self, impl1: DefId, impl2: DefId, - overlap: traits::OverlapResult, - used_to_be_allowed: bool) { + fn check_for_common_items_in_impls( + &self, impl1: DefId, impl2: DefId, + overlap: traits::OverlapResult, + used_to_be_allowed: Option) + { let name_and_namespace = |def_id| { let item = self.tcx.associated_item(def_id); @@ -46,20 +49,29 @@ impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> { for &item2 in &impl_items2[..] { if (name, namespace) == name_and_namespace(item2) { - let node_id = self.tcx.hir.as_local_node_id(impl1); - let mut err = if used_to_be_allowed && node_id.is_some() { - self.tcx.struct_span_lint_node( - lint::builtin::INCOHERENT_FUNDAMENTAL_IMPLS, - node_id.unwrap(), - self.tcx.span_of_impl(item1).unwrap(), - &format!("duplicate definitions with name `{}` (E0592)", name) - ) - } else { - struct_span_err!(self.tcx.sess, - self.tcx.span_of_impl(item1).unwrap(), - E0592, - "duplicate definitions with name `{}`", - name) + let node_id = self.tcx.hir().as_local_node_id(impl1); + let mut err = match used_to_be_allowed { + Some(kind) if node_id.is_some() => { + let lint = match kind { + FutureCompatOverlapErrorKind::Issue43355 => + lint::builtin::INCOHERENT_FUNDAMENTAL_IMPLS, + FutureCompatOverlapErrorKind::Issue33140 => + lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS, + }; + self.tcx.struct_span_lint_node( + lint, + node_id.unwrap(), + self.tcx.span_of_impl(item1).unwrap(), + &format!("duplicate definitions with name `{}` (E0592)", name) + ) + } + _ => { + struct_span_err!(self.tcx.sess, + self.tcx.span_of_impl(item1).unwrap(), + E0592, + "duplicate definitions with name `{}`", + name) + } }; err.span_label(self.tcx.span_of_impl(item1).unwrap(), @@ -82,38 +94,73 @@ impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> { for (i, &impl1_def_id) in impls.iter().enumerate() { for &impl2_def_id in &impls[(i + 1)..] { + // First, check if the impl was forbidden under the + // old rules. In that case, just have an error. let used_to_be_allowed = traits::overlapping_impls( self.tcx, impl1_def_id, impl2_def_id, IntercrateMode::Issue43355, + TraitObjectMode::NoSquash, |overlap| { self.check_for_common_items_in_impls( impl1_def_id, impl2_def_id, overlap, - false, + None, ); false }, || true, ); - if used_to_be_allowed { - traits::overlapping_impls( - self.tcx, - impl1_def_id, - impl2_def_id, - IntercrateMode::Fixed, - |overlap| self.check_for_common_items_in_impls( + if !used_to_be_allowed { + continue; + } + + // Then, check if the impl was forbidden under only + // #43355. In that case, emit an #43355 error. + let used_to_be_allowed = traits::overlapping_impls( + self.tcx, + impl1_def_id, + impl2_def_id, + IntercrateMode::Fixed, + TraitObjectMode::NoSquash, + |overlap| { + self.check_for_common_items_in_impls( impl1_def_id, impl2_def_id, overlap, - true, - ), - || (), - ); + Some(FutureCompatOverlapErrorKind::Issue43355), + ); + false + }, + || true, + ); + + if !used_to_be_allowed { + continue; } + + // Then, check if the impl was forbidden under + // #33140. In that case, emit a #33140 error. + traits::overlapping_impls( + self.tcx, + impl1_def_id, + impl2_def_id, + IntercrateMode::Fixed, + TraitObjectMode::SquashAutoTraitsIssue33140, + |overlap| { + self.check_for_common_items_in_impls( + impl1_def_id, + impl2_def_id, + overlap, + Some(FutureCompatOverlapErrorKind::Issue33140), + ); + false + }, + || true, + ); } } } @@ -126,7 +173,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentOverlapChecker<'a, 'tcx> { hir::ItemKind::Struct(..) | hir::ItemKind::Trait(..) | hir::ItemKind::Union(..) => { - let type_def_id = self.tcx.hir.local_def_id(item.id); + let type_def_id = self.tcx.hir().local_def_id(item.id); self.check_for_overlapping_inherent_impls(type_def_id); } _ => {} diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 9b17654d469..0360617be3c 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -29,7 +29,7 @@ mod orphan; mod unsafety; fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) { - let impl_def_id = tcx.hir.local_def_id(node_id); + let impl_def_id = tcx.hir().local_def_id(node_id); // If there are no traits, then this implementation must have a // base type. @@ -40,7 +40,7 @@ fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) { tcx.item_path_str(impl_def_id)); // Skip impls where one of the self type is an error type. - // This occurs with e.g. resolve failures (#30589). + // This occurs with e.g., resolve failures (#30589). if trait_ref.references_error() { return; } @@ -135,7 +135,7 @@ pub fn provide(providers: &mut Providers) { } fn coherent_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { - let impls = tcx.hir.trait_impls(def_id); + let impls = tcx.hir().trait_impls(def_id); for &impl_id in impls { check_impl(tcx, impl_id); } @@ -146,7 +146,7 @@ fn coherent_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { } pub fn check_coherence<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - for &trait_def_id in tcx.hir.krate().trait_impls.keys() { + for &trait_def_id in tcx.hir().krate().trait_impls.keys() { ty::query::queries::coherent_trait::ensure(tcx, trait_def_id); } @@ -162,7 +162,7 @@ pub fn check_coherence<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { /// same type. Likewise, no two inherent impls for a given type /// constructor provide a method with the same name. fn check_impl_overlap<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) { - let impl_def_id = tcx.hir.local_def_id(node_id); + let impl_def_id = tcx.hir().local_def_id(node_id); let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); let trait_def_id = trait_ref.def_id; diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index 14c6864434f..131413eb402 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -18,7 +18,7 @@ use rustc::hir; pub fn check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let mut orphan = OrphanChecker { tcx }; - tcx.hir.krate().visit_all_item_likes(&mut orphan); + tcx.hir().krate().visit_all_item_likes(&mut orphan); } struct OrphanChecker<'cx, 'tcx: 'cx> { @@ -32,11 +32,11 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> { /// to prevent inundating the user with a bunch of similar error /// reports. fn visit_item(&mut self, item: &hir::Item) { - let def_id = self.tcx.hir.local_def_id(item.id); + let def_id = self.tcx.hir().local_def_id(item.id); // "Trait" impl if let hir::ItemKind::Impl(.., Some(_), _, _) = item.node { debug!("coherence2::orphan check: trait impl {}", - self.tcx.hir.node_to_string(item.id)); + self.tcx.hir().node_to_string(item.id)); let trait_ref = self.tcx.impl_trait_ref(def_id).unwrap(); let trait_def_id = trait_ref.def_id; let cm = self.tcx.sess.source_map(); @@ -60,7 +60,7 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> { sp, E0210, "type parameter `{}` must be used as the type parameter \ - for some local type (e.g. `MyStruct<{}>`)", + for some local type (e.g., `MyStruct<{}>`)", param_ty, param_ty) .span_label(sp, diff --git a/src/librustc_typeck/coherence/unsafety.rs b/src/librustc_typeck/coherence/unsafety.rs index 0894c1d49e8..b4196b572b4 100644 --- a/src/librustc_typeck/coherence/unsafety.rs +++ b/src/librustc_typeck/coherence/unsafety.rs @@ -17,7 +17,7 @@ use rustc::hir::{self, Unsafety}; pub fn check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let mut unsafety = UnsafetyChecker { tcx }; - tcx.hir.krate().visit_all_item_likes(&mut unsafety); + tcx.hir().krate().visit_all_item_likes(&mut unsafety); } struct UnsafetyChecker<'cx, 'tcx: 'cx> { @@ -31,7 +31,7 @@ impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> { unsafety: hir::Unsafety, polarity: hir::ImplPolarity) { - if let Some(trait_ref) = self.tcx.impl_trait_ref(self.tcx.hir.local_def_id(item.id)) { + if let Some(trait_ref) = self.tcx.impl_trait_ref(self.tcx.hir().local_def_id(item.id)) { let trait_def = self.tcx.trait_def(trait_ref.def_id); let unsafe_attr = impl_generics.and_then(|generics| { generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle") diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index a1bb0b53f1f..a4eafee36d1 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -66,7 +66,7 @@ struct OnlySelfBounds(bool); pub fn collect_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let mut visitor = CollectItemTypesVisitor { tcx }; - tcx.hir + tcx.hir() .krate() .visit_all_item_likes(&mut visitor.as_deep_visitor()); } @@ -97,7 +97,7 @@ pub fn provide(providers: &mut Providers) { /// AstConv. It has information about the predicates that are defined /// on the trait. Unfortunately, this predicate information is /// available in various different forms at various points in the -/// process. So we can't just store a pointer to e.g. the AST or the +/// process. So we can't just store a pointer to e.g., the AST or the /// parsed ty form, we have to be more flexible. To this end, the /// `ItemCtxt` is parameterized by a `DefId` that it uses to satisfy /// `get_type_parameter_bounds` requests, drawing the information from @@ -115,7 +115,7 @@ struct CollectItemTypesVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir) + NestedVisitorMap::OnlyBodies(&self.tcx.hir()) } fn visit_item(&mut self, item: &'tcx hir::Item) { @@ -130,7 +130,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'a, 'tcx> { hir::GenericParamKind::Type { default: Some(_), .. } => { - let def_id = self.tcx.hir.local_def_id(param.id); + let def_id = self.tcx.hir().local_def_id(param.id); self.tcx.type_of(def_id); } hir::GenericParamKind::Type { .. } => {} @@ -141,7 +141,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx hir::Expr) { if let hir::ExprKind::Closure(..) = expr.node { - let def_id = self.tcx.hir.local_def_id(expr.id); + let def_id = self.tcx.hir().local_def_id(expr.id); self.tcx.generics_of(def_id); self.tcx.type_of(def_id); } @@ -252,12 +252,12 @@ fn type_param_predicates<'a, 'tcx>( // written inline like `` or in a where clause like // `where T : Foo`. - let param_id = tcx.hir.as_local_node_id(def_id).unwrap(); - let param_owner = tcx.hir.ty_param_owner(param_id); - let param_owner_def_id = tcx.hir.local_def_id(param_owner); + let param_id = tcx.hir().as_local_node_id(def_id).unwrap(); + let param_owner = tcx.hir().ty_param_owner(param_id); + let param_owner_def_id = tcx.hir().local_def_id(param_owner); let generics = tcx.generics_of(param_owner_def_id); let index = generics.param_def_id_to_index[&def_id]; - let ty = tcx.mk_ty_param(index, tcx.hir.ty_param_name(param_id).as_interned_str()); + let ty = tcx.mk_ty_param(index, tcx.hir().ty_param_name(param_id).as_interned_str()); // Don't look for bounds where the type parameter isn't in scope. let parent = if item_def_id == param_owner_def_id { @@ -277,8 +277,8 @@ fn type_param_predicates<'a, 'tcx>( }, ); - let item_node_id = tcx.hir.as_local_node_id(item_def_id).unwrap(); - let ast_generics = match tcx.hir.get(item_node_id) { + let item_node_id = tcx.hir().as_local_node_id(item_def_id).unwrap(); + let ast_generics = match tcx.hir().get(item_node_id) { Node::TraitItem(item) => &item.generics, Node::ImplItem(item) => &item.generics, @@ -384,7 +384,7 @@ fn is_param<'a, 'tcx>( if let hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) = ast_ty.node { match path.def { Def::SelfTy(Some(def_id), None) | Def::TyParam(def_id) => { - def_id == tcx.hir.local_def_id(param_id) + def_id == tcx.hir().local_def_id(param_id) } _ => false, } @@ -394,9 +394,9 @@ fn is_param<'a, 'tcx>( } fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) { - let it = tcx.hir.expect_item(item_id); + let it = tcx.hir().expect_item(item_id); debug!("convert: item {} with id {}", it.name, it.id); - let def_id = tcx.hir.local_def_id(item_id); + let def_id = tcx.hir().local_def_id(item_id); match it.node { // These don't define types. hir::ItemKind::ExternCrate(_) @@ -405,7 +405,7 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) { | hir::ItemKind::GlobalAsm(_) => {} hir::ItemKind::ForeignMod(ref foreign_mod) => { for item in &foreign_mod.items { - let def_id = tcx.hir.local_def_id(item.id); + let def_id = tcx.hir().local_def_id(item.id); tcx.generics_of(def_id); tcx.type_of(def_id); tcx.predicates_of(def_id); @@ -443,7 +443,7 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) { tcx.predicates_of(def_id); for f in struct_def.fields() { - let def_id = tcx.hir.local_def_id(f.id); + let def_id = tcx.hir().local_def_id(f.id); tcx.generics_of(def_id); tcx.type_of(def_id); tcx.predicates_of(def_id); @@ -476,8 +476,8 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) { } fn convert_trait_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_item_id: ast::NodeId) { - let trait_item = tcx.hir.expect_trait_item(trait_item_id); - let def_id = tcx.hir.local_def_id(trait_item.id); + let trait_item = tcx.hir().expect_trait_item(trait_item_id); + let def_id = tcx.hir().local_def_id(trait_item.id); tcx.generics_of(def_id); match trait_item.node { @@ -497,17 +497,17 @@ fn convert_trait_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_item_id: ast: } fn convert_impl_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_item_id: ast::NodeId) { - let def_id = tcx.hir.local_def_id(impl_item_id); + let def_id = tcx.hir().local_def_id(impl_item_id); tcx.generics_of(def_id); tcx.type_of(def_id); tcx.predicates_of(def_id); - if let hir::ImplItemKind::Method(..) = tcx.hir.expect_impl_item(impl_item_id).node { + if let hir::ImplItemKind::Method(..) = tcx.hir().expect_impl_item(impl_item_id).node { tcx.fn_sig(def_id); } } fn convert_variant_ctor<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ctor_id: ast::NodeId) { - let def_id = tcx.hir.local_def_id(ctor_id); + let def_id = tcx.hir().local_def_id(ctor_id); tcx.generics_of(def_id); tcx.type_of(def_id); tcx.predicates_of(def_id); @@ -528,7 +528,7 @@ fn convert_enum_variant_types<'a, 'tcx>( let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx)); prev_discr = Some( if let Some(ref e) = variant.node.disr_expr { - let expr_did = tcx.hir.local_def_id(e.id); + let expr_did = tcx.hir().local_def_id(e.id); def.eval_explicit_discr(tcx, expr_did) } else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) { Some(discr) @@ -551,7 +551,7 @@ fn convert_enum_variant_types<'a, 'tcx>( ); for f in variant.node.data.fields() { - let def_id = tcx.hir.local_def_id(f.id); + let def_id = tcx.hir().local_def_id(f.id); tcx.generics_of(def_id); tcx.type_of(def_id); tcx.predicates_of(def_id); @@ -573,12 +573,12 @@ fn convert_variant<'a, 'tcx>( attribute_def_id: DefId ) -> ty::VariantDef { let mut seen_fields: FxHashMap = Default::default(); - let node_id = tcx.hir.as_local_node_id(did).unwrap(); + let node_id = tcx.hir().as_local_node_id(did).unwrap(); let fields = def .fields() .iter() .map(|f| { - let fid = tcx.hir.local_def_id(f.id); + let fid = tcx.hir().local_def_id(f.id); let dup_span = seen_fields.get(&f.ident.modern()).cloned(); if let Some(prev_span) = dup_span { struct_span_err!( @@ -614,8 +614,8 @@ fn convert_variant<'a, 'tcx>( fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::AdtDef { use rustc::hir::*; - let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); - let item = match tcx.hir.get(node_id) { + let node_id = tcx.hir().as_local_node_id(def_id).unwrap(); + let item = match tcx.hir().get(node_id) { Node::Item(item) => item, _ => bug!(), }; @@ -629,10 +629,10 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Ad def.variants .iter() .map(|v| { - let did = tcx.hir.local_def_id(v.node.data.id()); + let did = tcx.hir().local_def_id(v.node.data.id()); let discr = if let Some(ref e) = v.node.disr_expr { distance_from_explicit = 0; - ty::VariantDiscr::Explicit(tcx.hir.local_def_id(e.id)) + ty::VariantDiscr::Explicit(tcx.hir().local_def_id(e.id)) } else { ty::VariantDiscr::Relative(distance_from_explicit) }; @@ -647,7 +647,7 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Ad ItemKind::Struct(ref def, _) => { // Use separate constructor id for unit/tuple structs and reuse did for braced structs. let ctor_id = if !def.is_struct() { - Some(tcx.hir.local_def_id(def.id())) + Some(tcx.hir().local_def_id(def.id())) } else { None }; @@ -689,9 +689,9 @@ fn super_predicates_of<'a, 'tcx>( trait_def_id: DefId, ) -> Lrc> { debug!("super_predicates(trait_def_id={:?})", trait_def_id); - let trait_node_id = tcx.hir.as_local_node_id(trait_def_id).unwrap(); + let trait_node_id = tcx.hir().as_local_node_id(trait_def_id).unwrap(); - let item = match tcx.hir.get(trait_node_id) { + let item = match tcx.hir().get(trait_node_id) { Node::Item(item) => item, _ => bug!("trait_node_id {} is not an item", trait_node_id), }; @@ -704,16 +704,16 @@ fn super_predicates_of<'a, 'tcx>( let icx = ItemCtxt::new(tcx, trait_def_id); - // Convert the bounds that follow the colon, e.g. `Bar + Zed` in `trait Foo : Bar + Zed`. + // Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo : Bar + Zed`. let self_param_ty = tcx.mk_self_type(); let superbounds1 = compute_bounds(&icx, self_param_ty, bounds, SizedByDefault::No, item.span); let superbounds1 = superbounds1.predicates(tcx, self_param_ty); // Convert any explicit superbounds in the where clause, - // e.g. `trait Foo where Self : Bar`. + // e.g., `trait Foo where Self : Bar`. // In the case of trait aliases, however, we include all bounds in the where clause, - // so e.g. `trait Foo = where u32: PartialEq` would include `u32: PartialEq` + // so e.g., `trait Foo = where u32: PartialEq` would include `u32: PartialEq` // as one of its "superpredicates". let is_trait_alias = ty::is_trait_alias(tcx, trait_def_id); let superbounds2 = icx.type_parameter_bounds_in_generics( @@ -738,8 +738,8 @@ fn super_predicates_of<'a, 'tcx>( } fn trait_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::TraitDef { - let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); - let item = tcx.hir.expect_item(node_id); + let node_id = tcx.hir().as_local_node_id(def_id).unwrap(); + let item = tcx.hir().expect_item(node_id); let (is_auto, unsafety) = match item.node { hir::ItemKind::Trait(is_auto, unsafety, ..) => (is_auto == hir::IsAuto::Yes, unsafety), @@ -815,7 +815,7 @@ fn has_late_bound_regions<'a, 'tcx>( return; } - let hir_id = self.tcx.hir.node_to_hir_id(lt.id); + let hir_id = self.tcx.hir().node_to_hir_id(lt.id); match self.tcx.named_region(hir_id) { Some(rl::Region::Static) | Some(rl::Region::EarlyBound(..)) => {} Some(rl::Region::LateBound(debruijn, _, _)) @@ -842,7 +842,7 @@ fn has_late_bound_regions<'a, 'tcx>( }; for param in &generics.params { if let GenericParamKind::Lifetime { .. } = param.kind { - let hir_id = tcx.hir.node_to_hir_id(param.id); + let hir_id = tcx.hir().node_to_hir_id(param.id); if tcx.is_late_bound(hir_id) { return Some(param.span); } @@ -884,14 +884,14 @@ fn has_late_bound_regions<'a, 'tcx>( fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Generics { use rustc::hir::*; - let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); + let node_id = tcx.hir().as_local_node_id(def_id).unwrap(); - let node = tcx.hir.get(node_id); + let node = tcx.hir().get(node_id); let parent_def_id = match node { Node::ImplItem(_) | Node::TraitItem(_) | Node::Variant(_) | Node::StructCtor(_) | Node::Field(_) => { - let parent_id = tcx.hir.get_parent(node_id); - Some(tcx.hir.local_def_id(parent_id)) + let parent_id = tcx.hir().get_parent(node_id); + Some(tcx.hir().local_def_id(parent_id)) } Node::Expr(&hir::Expr { node: hir::ExprKind::Closure(..), @@ -938,8 +938,8 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty opt_self = Some(ty::GenericParamDef { index: 0, - name: keywords::SelfType.name().as_interned_str(), - def_id: tcx.hir.local_def_id(param_id), + name: keywords::SelfUpper.name().as_interned_str(), + def_id: tcx.hir().local_def_id(param_id), pure_wrt_drop: false, kind: ty::GenericParamDefKind::Type { has_default: false, @@ -985,13 +985,13 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty .map(|(i, param)| ty::GenericParamDef { name: param.name.ident().as_interned_str(), index: own_start + i as u32, - def_id: tcx.hir.local_def_id(param.id), + def_id: tcx.hir().local_def_id(param.id), pure_wrt_drop: param.pure_wrt_drop, kind: ty::GenericParamDefKind::Lifetime, }), ); - let hir_id = tcx.hir.node_to_hir_id(node_id); + let hir_id = tcx.hir().node_to_hir_id(node_id); let object_lifetime_defaults = tcx.object_lifetime_defaults(hir_id); // Now create the real type parameters. @@ -1007,7 +1007,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty synthetic, .. } => { - if param.name.ident().name == keywords::SelfType.name() { + if param.name.ident().name == keywords::SelfUpper.name() { span_bug!( param.span, "`Self` should not be the name of a regular parameter" @@ -1031,7 +1031,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty let ty_param = ty::GenericParamDef { index: type_start + i as u32, name: param.name.ident().as_interned_str(), - def_id: tcx.hir.local_def_id(param.id), + def_id: tcx.hir().local_def_id(param.id), pure_wrt_drop: param.pure_wrt_drop, kind: ty::GenericParamDefKind::Type { has_default: default.is_some(), @@ -1123,11 +1123,11 @@ fn report_assoc_ty_on_inherent_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> { use rustc::hir::*; - let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); + let node_id = tcx.hir().as_local_node_id(def_id).unwrap(); let icx = ItemCtxt::new(tcx, def_id); - match tcx.hir.get(node_id) { + match tcx.hir().get(node_id) { Node::TraitItem(item) => match item.node { TraitItemKind::Method(..) => { let substs = Substs::identity_for_item(tcx, def_id); @@ -1147,7 +1147,7 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> { ImplItemKind::Const(ref ty, _) => icx.to_ty(ty), ImplItemKind::Existential(_) => { if tcx - .impl_trait_ref(tcx.hir.get_parent_did(node_id)) + .impl_trait_ref(tcx.hir().get_parent_did(node_id)) .is_none() { report_assoc_ty_on_inherent_impl(tcx, item.span); @@ -1157,7 +1157,7 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> { } ImplItemKind::Type(ref ty) => { if tcx - .impl_trait_ref(tcx.hir.get_parent_did(node_id)) + .impl_trait_ref(tcx.hir().get_parent_did(node_id)) .is_none() { report_assoc_ty_on_inherent_impl(tcx, item.span); @@ -1240,7 +1240,7 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> { .. }) => match *def { VariantData::Unit(..) | VariantData::Struct(..) => { - tcx.type_of(tcx.hir.get_parent_did(node_id)) + tcx.type_of(tcx.hir().get_parent_did(node_id)) } VariantData::Tuple(..) => { let substs = Substs::identity_for_item(tcx, def_id); @@ -1255,7 +1255,7 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> { .. }) => { if gen.is_some() { - let hir_id = tcx.hir.node_to_hir_id(node_id); + let hir_id = tcx.hir().node_to_hir_id(node_id); return tcx.typeck_tables_of(def_id).node_id_to_type(hir_id); } @@ -1266,7 +1266,7 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> { tcx.mk_closure(def_id, substs) } - Node::AnonConst(_) => match tcx.hir.get(tcx.hir.get_parent_node(node_id)) { + Node::AnonConst(_) => match tcx.hir().get(tcx.hir().get_parent_node(node_id)) { Node::Ty(&hir::Ty { node: hir::TyKind::Array(_, ref constant), .. @@ -1292,7 +1292,7 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> { .. }) if e.id == node_id => { - tcx.adt_def(tcx.hir.get_parent_did(node_id)) + tcx.adt_def(tcx.hir().get_parent_did(node_id)) .repr .discr_type() .to_ty(tcx) @@ -1365,10 +1365,10 @@ fn find_existential_constraints<'a, 'tcx>( impl<'a, 'tcx> intravisit::Visitor<'tcx> for ConstraintLocator<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> { - intravisit::NestedVisitorMap::All(&self.tcx.hir) + intravisit::NestedVisitorMap::All(&self.tcx.hir()) } fn visit_item(&mut self, it: &'tcx Item) { - let def_id = self.tcx.hir.local_def_id(it.id); + let def_id = self.tcx.hir().local_def_id(it.id); // the existential type itself or its children are not within its reveal scope if def_id != self.def_id { self.check(def_id); @@ -1376,7 +1376,7 @@ fn find_existential_constraints<'a, 'tcx>( } } fn visit_impl_item(&mut self, it: &'tcx ImplItem) { - let def_id = self.tcx.hir.local_def_id(it.id); + let def_id = self.tcx.hir().local_def_id(it.id); // the existential type itself or its children are not within its reveal scope if def_id != self.def_id { self.check(def_id); @@ -1384,7 +1384,7 @@ fn find_existential_constraints<'a, 'tcx>( } } fn visit_trait_item(&mut self, it: &'tcx TraitItem) { - let def_id = self.tcx.hir.local_def_id(it.id); + let def_id = self.tcx.hir().local_def_id(it.id); self.check(def_id); intravisit::walk_trait_item(self, it); } @@ -1395,16 +1395,16 @@ fn find_existential_constraints<'a, 'tcx>( tcx, found: None, }; - let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); - let parent = tcx.hir.get_parent(node_id); + let node_id = tcx.hir().as_local_node_id(def_id).unwrap(); + let parent = tcx.hir().get_parent(node_id); trace!("parent_id: {:?}", parent); if parent == ast::CRATE_NODE_ID { - intravisit::walk_crate(&mut locator, tcx.hir.krate()); + intravisit::walk_crate(&mut locator, tcx.hir().krate()); } else { - trace!("parent: {:?}", tcx.hir.get(parent)); - match tcx.hir.get(parent) { + trace!("parent: {:?}", tcx.hir().get(parent)); + match tcx.hir().get(parent) { Node::Item(ref it) => intravisit::walk_item(&mut locator, it), Node::ImplItem(ref it) => intravisit::walk_impl_item(&mut locator, it), Node::TraitItem(ref it) => intravisit::walk_trait_item(&mut locator, it), @@ -1429,11 +1429,11 @@ fn fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::PolyFnSig use rustc::hir::*; use rustc::hir::Node::*; - let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); + let node_id = tcx.hir().as_local_node_id(def_id).unwrap(); let icx = ItemCtxt::new(tcx, def_id); - match tcx.hir.get(node_id) { + match tcx.hir().get(node_id) { TraitItem(hir::TraitItem { node: TraitItemKind::Method(sig, _), .. @@ -1452,7 +1452,7 @@ fn fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::PolyFnSig node: ForeignItemKind::Fn(ref fn_decl, _, _), .. }) => { - let abi = tcx.hir.get_foreign_abi(node_id); + let abi = tcx.hir().get_foreign_abi(node_id); compute_sig_of_foreign_fn_decl(tcx, def_id, fn_decl, abi) } @@ -1465,10 +1465,10 @@ fn fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::PolyFnSig }, .. }) => { - let ty = tcx.type_of(tcx.hir.get_parent_did(node_id)); + let ty = tcx.type_of(tcx.hir().get_parent_did(node_id)); let inputs = fields .iter() - .map(|f| tcx.type_of(tcx.hir.local_def_id(f.id))); + .map(|f| tcx.type_of(tcx.hir().local_def_id(f.id))); ty::Binder::bind(tcx.mk_fn_sig( inputs, ty, @@ -1512,8 +1512,8 @@ fn impl_trait_ref<'a, 'tcx>( ) -> Option> { let icx = ItemCtxt::new(tcx, def_id); - let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); - match tcx.hir.expect_item(node_id).node { + let node_id = tcx.hir().as_local_node_id(def_id).unwrap(); + match tcx.hir().expect_item(node_id).node { hir::ItemKind::Impl(.., ref opt_trait_ref, _, _) => { opt_trait_ref.as_ref().map(|ast_trait_ref| { let selfty = tcx.type_of(def_id); @@ -1525,8 +1525,8 @@ fn impl_trait_ref<'a, 'tcx>( } fn impl_polarity<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> hir::ImplPolarity { - let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); - match tcx.hir.expect_item(node_id).node { + let node_id = tcx.hir().as_local_node_id(def_id).unwrap(); + match tcx.hir().expect_item(node_id).node { hir::ItemKind::Impl(_, polarity, ..) => polarity, ref item => bug!("impl_polarity: {:?} not an impl", item), } @@ -1597,7 +1597,7 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx>( .iter() .filter(move |param| match param.kind { GenericParamKind::Lifetime { .. } => { - let hir_id = tcx.hir.node_to_hir_id(param.id); + let hir_id = tcx.hir().node_to_hir_id(param.id); !tcx.is_late_bound(hir_id) } _ => false, @@ -1695,8 +1695,8 @@ fn explicit_predicates_of<'a, 'tcx>( } } - let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); - let node = tcx.hir.get(node_id); + let node_id = tcx.hir().as_local_node_id(def_id).unwrap(); + let node = tcx.hir().get(node_id); let mut is_trait = None; let mut is_default_impl_trait = None; @@ -1715,7 +1715,7 @@ fn explicit_predicates_of<'a, 'tcx>( let substs = Substs::identity_for_item(tcx, def_id); let opaque_ty = tcx.mk_opaque(def_id, substs); - // Collect the bounds, i.e. the `A+B+'c` in `impl A+B+'c`. + // Collect the bounds, i.e., the `A+B+'c` in `impl A+B+'c`. let bounds = compute_bounds( &icx, opaque_ty, @@ -1760,7 +1760,7 @@ fn explicit_predicates_of<'a, 'tcx>( let substs = Substs::identity_for_item(tcx, def_id); let opaque_ty = tcx.mk_opaque(def_id, substs); - // Collect the bounds, i.e. the `A+B+'c` in `impl A+B+'c`. + // Collect the bounds, i.e., the `A+B+'c` in `impl A+B+'c`. let bounds = compute_bounds( &icx, opaque_ty, @@ -1825,7 +1825,7 @@ fn explicit_predicates_of<'a, 'tcx>( let mut index = parent_count + has_own_self as u32; for param in early_bound_lifetimes_from_generics(tcx, ast_generics) { let region = tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion { - def_id: tcx.hir.local_def_id(param.id), + def_id: tcx.hir().local_def_id(param.id), index, name: param.name.ident().as_interned_str(), })); @@ -1938,14 +1938,14 @@ fn explicit_predicates_of<'a, 'tcx>( // Add predicates from associated type bounds. if let Some((self_trait_ref, trait_items)) = is_trait { predicates.extend(trait_items.iter().flat_map(|trait_item_ref| { - let trait_item = tcx.hir.trait_item(trait_item_ref.id); + let trait_item = tcx.hir().trait_item(trait_item_ref.id); let bounds = match trait_item.node { hir::TraitItemKind::Type(ref bounds, _) => bounds, _ => return vec![].into_iter() }; let assoc_ty = - tcx.mk_projection(tcx.hir.local_def_id(trait_item.id), self_trait_ref.substs); + tcx.mk_projection(tcx.hir().local_def_id(trait_item.id), self_trait_ref.substs); let bounds = compute_bounds( &ItemCtxt::new(tcx, def_id), @@ -2108,7 +2108,7 @@ fn compute_sig_of_foreign_fn_decl<'a, 'tcx>( &format!( "use of SIMD type `{}` in FFI is highly experimental and \ may result in invalid code", - tcx.hir.node_to_pretty_string(ast_ty.id) + tcx.hir().node_to_pretty_string(ast_ty.id) ), ) .help("add #![feature(simd_ffi)] to the crate attributes to enable") @@ -2127,7 +2127,7 @@ fn compute_sig_of_foreign_fn_decl<'a, 'tcx>( } fn is_foreign_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> bool { - match tcx.hir.get_if_local(def_id) { + match tcx.hir().get_if_local(def_id) { Some(Node::ForeignItem(..)) => true, Some(_) => false, _ => bug!("is_foreign_item applied to non-local def-id {:?}", def_id), @@ -2207,6 +2207,8 @@ fn from_target_feature( Some("sse4a_target_feature") => rust_features.sse4a_target_feature, Some("tbm_target_feature") => rust_features.tbm_target_feature, Some("wasm_target_feature") => rust_features.wasm_target_feature, + Some("cmpxchg16b_target_feature") => rust_features.cmpxchg16b_target_feature, + Some("adx_target_feature") => rust_features.adx_target_feature, Some(name) => bug!("unknown target feature gate {}", name), None => true, }; @@ -2249,7 +2251,7 @@ fn linkage_by_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, name: & "weak" => WeakAny, "weak_odr" => WeakODR, _ => { - let span = tcx.hir.span_if_local(def_id); + let span = tcx.hir().span_if_local(def_id); if let Some(span) = span { tcx.sess.span_fatal(span, "invalid linkage specified") } else { diff --git a/src/librustc_typeck/constrained_type_params.rs b/src/librustc_typeck/constrained_type_params.rs index 9299e9b7b8f..25fa33ef9fa 100644 --- a/src/librustc_typeck/constrained_type_params.rs +++ b/src/librustc_typeck/constrained_type_params.rs @@ -37,7 +37,7 @@ pub fn parameters_for_impl<'tcx>(impl_self_ty: Ty<'tcx>, } /// If `include_projections` is false, returns the list of parameters that are -/// constrained by `t` - i.e. the value of each parameter in the list is +/// constrained by `t` - i.e., the value of each parameter in the list is /// uniquely determined by `t` (see RFC 447). If it is true, return the list /// of parameters whose values are needed in order to constrain `ty` - these /// differ, with the latter being a superset, in the presence of projections. diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 084951f4a2c..a0dbaf5ad50 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -655,7 +655,7 @@ For example, a function like: fn f(a: u16, b: &str) {} ``` -Must always be called with exactly two arguments, e.g. `f(2, "test")`. +Must always be called with exactly two arguments, e.g., `f(2, "test")`. Note that Rust does not have a notion of optional function arguments or variadic functions (except for its C-FFI). @@ -1610,7 +1610,7 @@ it has been disabled for now. E0185: r##" An associated function for a trait was defined to be static, but an -implementation of the trait declared the same function to be a method (i.e. to +implementation of the trait declared the same function to be a method (i.e., to take a `self` parameter). Here's an example of this error: @@ -1631,7 +1631,7 @@ impl Foo for Bar { "##, E0186: r##" -An associated function for a trait was defined to be a method (i.e. to take a +An associated function for a trait was defined to be a method (i.e., to take a `self` parameter), but an implementation of the trait declared the same function to be static. diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs index 74a53f7fca2..a2071fd6d47 100644 --- a/src/librustc_typeck/impl_wf_check.rs +++ b/src/librustc_typeck/impl_wf_check.rs @@ -62,7 +62,7 @@ pub fn impl_wf_check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { // We will tag this as part of the WF check -- logically, it is, // but it's one that we must perform earlier than the rest of // WfCheck. - tcx.hir.krate().visit_all_item_likes(&mut ImplWfCheck { tcx }); + tcx.hir().krate().visit_all_item_likes(&mut ImplWfCheck { tcx }); } struct ImplWfCheck<'a, 'tcx: 'a> { @@ -72,7 +72,7 @@ struct ImplWfCheck<'a, 'tcx: 'a> { impl<'a, 'tcx> ItemLikeVisitor<'tcx> for ImplWfCheck<'a, 'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item) { if let hir::ItemKind::Impl(.., ref impl_item_refs) = item.node { - let impl_def_id = self.tcx.hir.local_def_id(item.id); + let impl_def_id = self.tcx.hir().local_def_id(item.id); enforce_impl_params_are_constrained(self.tcx, impl_def_id, impl_item_refs); @@ -101,7 +101,7 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Disallow unconstrained lifetimes, but only if they appear in assoc types. let lifetimes_in_associated_types: FxHashSet<_> = impl_item_refs.iter() - .map(|item_ref| tcx.hir.local_def_id(item_ref.id.node_id)) + .map(|item_ref| tcx.hir().local_def_id(item_ref.id.node_id)) .filter(|&def_id| { let item = tcx.associated_item(def_id); item.kind == ty::AssociatedKind::Type && item.defaultness.has_value() @@ -176,7 +176,7 @@ fn enforce_impl_items_are_distinct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut seen_type_items = FxHashMap::default(); let mut seen_value_items = FxHashMap::default(); for impl_item_ref in impl_item_refs { - let impl_item = tcx.hir.impl_item(impl_item_ref.id); + let impl_item = tcx.hir().impl_item(impl_item_ref.id); let seen_items = match impl_item.node { hir::ImplItemKind::Type(_) => &mut seen_type_items, _ => &mut seen_value_items, diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 0fba311d7f7..fdc81a6ed1a 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -10,24 +10,24 @@ /*! -typeck.rs, an introduction +# typeck.rs The type checker is responsible for: -1. Determining the type of each expression -2. Resolving methods and traits -3. Guaranteeing that most type rules are met ("most?", you say, "why most?" +1. Determining the type of each expression. +2. Resolving methods and traits. +3. Guaranteeing that most type rules are met. ("Most?", you say, "why most?" Well, dear reader, read on) -The main entry point is `check_crate()`. Type checking operates in +The main entry point is `check_crate()`. Type checking operates in several major phases: 1. The collect phase first passes over all items and determines their type, without examining their "innards". -2. Variance inference then runs to compute the variance of each parameter +2. Variance inference then runs to compute the variance of each parameter. -3. Coherence checks for overlapping or orphaned impls +3. Coherence checks for overlapping or orphaned impls. 4. Finally, the check phase then checks function bodies and so forth. Within the check phase, we check each function body one at a time @@ -41,12 +41,12 @@ The type checker is defined into various submodules which are documented independently: - astconv: converts the AST representation of types - into the `ty` representation + into the `ty` representation. - collect: computes the types of each top-level item and enters them into - the `tcx.types` table for later use + the `tcx.types` table for later use. -- coherence: enforces coherence rules, builds some tables +- coherence: enforces coherence rules, builds some tables. - variance: variance inference @@ -59,7 +59,7 @@ independently: all subtyping and assignment constraints are met. In essence, the check module specifies the constraints, and the infer module solves them. -# Note +## Note This API is completely unstable and subject to change. @@ -90,6 +90,7 @@ This API is completely unstable and subject to change. extern crate syntax_pos; extern crate arena; + #[macro_use] extern crate rustc; extern crate rustc_platform_intrinsics as intrinsics; extern crate rustc_data_structures; @@ -97,29 +98,7 @@ extern crate rustc_errors as errors; extern crate rustc_target; extern crate smallvec; -use rustc::hir; -use rustc::lint; -use rustc::middle; -use rustc::session; -use rustc::util; - -use hir::Node; -use rustc::infer::InferOk; -use rustc::ty::subst::Substs; -use rustc::ty::{self, Ty, TyCtxt}; -use rustc::ty::query::Providers; -use rustc::traits::{ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt}; -use rustc::util::profiling::ProfileCategory; -use session::{CompileIncomplete, config}; -use util::common::time; - -use syntax::ast; -use rustc_target::spec::abi::Abi; -use syntax_pos::Span; - -use std::iter; - -// NB: This module needs to be declared first so diagnostics are +// N.B., this module needs to be declared first so diagnostics are // registered before they are used. mod diagnostics; @@ -135,6 +114,26 @@ mod namespace; mod outlives; mod variance; +use hir::Node; +use rustc_target::spec::abi::Abi; +use rustc::hir; +use rustc::infer::InferOk; +use rustc::lint; +use rustc::middle; +use rustc::session; +use rustc::traits::{ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt}; +use rustc::ty::subst::Substs; +use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::query::Providers; +use rustc::util; +use rustc::util::profiling::ProfileCategory; +use session::{CompileIncomplete, config}; +use syntax_pos::Span; +use syntax::ast; +use util::common::time; + +use std::iter; + pub struct TypeAndSubsts<'tcx> { substs: &'tcx Substs<'tcx>, ty: Ty<'tcx>, @@ -182,11 +181,11 @@ fn require_same_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, main_id: ast::NodeId, main_span: Span) { - let main_def_id = tcx.hir.local_def_id(main_id); + let main_def_id = tcx.hir().local_def_id(main_id); let main_t = tcx.type_of(main_def_id); match main_t.sty { ty::FnDef(..) => { - if let Some(Node::Item(it)) = tcx.hir.find(main_id) { + if let Some(Node::Item(it)) = tcx.hir().find(main_id) { if let hir::ItemKind::Fn(.., ref generics, _) = it.node { let mut error = false; if !generics.params.is_empty() { @@ -248,11 +247,11 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, start_id: ast::NodeId, start_span: Span) { - let start_def_id = tcx.hir.local_def_id(start_id); + let start_def_id = tcx.hir().local_def_id(start_id); let start_t = tcx.type_of(start_def_id); match start_t.sty { ty::FnDef(..) => { - if let Some(Node::Item(it)) = tcx.hir.find(start_id) { + if let Some(Node::Item(it)) = tcx.hir().find(start_id) { if let hir::ItemKind::Fn(.., ref generics, _) = it.node { let mut error = false; if !generics.params.is_empty() { @@ -373,8 +372,8 @@ pub fn hir_ty_to_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hir_ty: &hir::Ty) -> // In case there are any projections etc, find the "environment" // def-id that will be used to determine the traits/predicates in // scope. This is derived from the enclosing item-like thing. - let env_node_id = tcx.hir.get_parent(hir_ty.id); - let env_def_id = tcx.hir.local_def_id(env_node_id); + let env_node_id = tcx.hir().get_parent(hir_ty.id); + let env_def_id = tcx.hir().local_def_id(env_node_id); let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id); astconv::AstConv::ast_ty_to_ty(&item_cx, hir_ty) @@ -385,8 +384,8 @@ pub fn hir_trait_to_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hir_trait: // In case there are any projections etc, find the "environment" // def-id that will be used to determine the traits/predicates in // scope. This is derived from the enclosing item-like thing. - let env_node_id = tcx.hir.get_parent(hir_trait.ref_id); - let env_def_id = tcx.hir.local_def_id(env_node_id); + let env_node_id = tcx.hir().get_parent(hir_trait.ref_id); + let env_def_id = tcx.hir().local_def_id(env_node_id); let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id); let mut projections = Vec::new(); let (principal, _) = astconv::AstConv::instantiate_poly_trait_ref_inner( diff --git a/src/librustc_typeck/outlives/implicit_infer.rs b/src/librustc_typeck/outlives/implicit_infer.rs index 30e304375fe..315e5feea3f 100644 --- a/src/librustc_typeck/outlives/implicit_infer.rs +++ b/src/librustc_typeck/outlives/implicit_infer.rs @@ -48,7 +48,7 @@ pub fn infer_predicates<'tcx>( }; // Visit all the crates and infer predicates - tcx.hir.krate().visit_all_item_likes(&mut visitor); + tcx.hir().krate().visit_all_item_likes(&mut visitor); } global_inferred_outlives @@ -63,16 +63,16 @@ pub struct InferVisitor<'cx, 'tcx: 'cx> { impl<'cx, 'tcx> ItemLikeVisitor<'tcx> for InferVisitor<'cx, 'tcx> { fn visit_item(&mut self, item: &hir::Item) { - let item_did = self.tcx.hir.local_def_id(item.id); + let item_did = self.tcx.hir().local_def_id(item.id); debug!("InferVisitor::visit_item(item={:?})", item_did); let node_id = self .tcx - .hir + .hir() .as_local_node_id(item_did) .expect("expected local def-id"); - let item = match self.tcx.hir.get(node_id) { + let item = match self.tcx.hir().get(node_id) { Node::Item(item) => item, _ => bug!(), }; @@ -314,7 +314,7 @@ pub fn check_explicit_predicates<'tcx>( // case that `substs` come from a `dyn Trait` type, our caller will have // included `Self = usize` as the value for `Self`. If we were // to apply the substs, and not filter this predicate, we might then falsely - // conclude that e.g. `X: 'x` was a reasonable inferred requirement. + // conclude that e.g., `X: 'x` was a reasonable inferred requirement. // // Another similar case is where we have a inferred // requirement like `::Foo: 'b`. We presently diff --git a/src/librustc_typeck/outlives/mod.rs b/src/librustc_typeck/outlives/mod.rs index 1eb53ffc730..5796df2744b 100644 --- a/src/librustc_typeck/outlives/mod.rs +++ b/src/librustc_typeck/outlives/mod.rs @@ -35,11 +35,11 @@ fn inferred_outlives_of<'a, 'tcx>( item_def_id: DefId, ) -> Lrc>> { let id = tcx - .hir + .hir() .as_local_node_id(item_def_id) .expect("expected local def-id"); - match tcx.hir.get(id) { + match tcx.hir().get(id) { Node::Item(item) => match item.node { hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Union(..) => { let crate_map = tcx.inferred_outlives_crate(LOCAL_CRATE); diff --git a/src/librustc_typeck/outlives/test.rs b/src/librustc_typeck/outlives/test.rs index 48c495e1c93..d855675d390 100644 --- a/src/librustc_typeck/outlives/test.rs +++ b/src/librustc_typeck/outlives/test.rs @@ -13,7 +13,7 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::ty::TyCtxt; pub fn test_inferred_outlives<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - tcx.hir + tcx.hir() .krate() .visit_all_item_likes(&mut OutlivesTest { tcx }); } @@ -24,7 +24,7 @@ struct OutlivesTest<'a, 'tcx: 'a> { impl<'a, 'tcx> ItemLikeVisitor<'tcx> for OutlivesTest<'a, 'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item) { - let item_def_id = self.tcx.hir.local_def_id(item.id); + let item_def_id = self.tcx.hir().local_def_id(item.id); // For unit testing: check for a special "rustc_outlives" // attribute and report an error with various results if found. diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index ed32e5a8d9b..6ea919469e0 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -44,7 +44,7 @@ pub struct Constraint<'a> { } /// To build constraints, we visit one item (type, trait) at a time -/// and look at its contents. So e.g. if we have +/// and look at its contents. So e.g., if we have /// /// struct Foo { /// b: Bar @@ -72,7 +72,7 @@ pub fn add_constraints_from_crate<'a, 'tcx>(terms_cx: TermsContext<'a, 'tcx>) constraints: Vec::new(), }; - tcx.hir.krate().visit_all_item_likes(&mut constraint_cx); + tcx.hir().krate().visit_all_item_likes(&mut constraint_cx); constraint_cx } @@ -131,7 +131,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> { impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { fn visit_node_helper(&mut self, id: ast::NodeId) { let tcx = self.terms_cx.tcx; - let def_id = tcx.hir.local_def_id(id); + let def_id = tcx.hir().local_def_id(id); self.build_constraints_for_item(def_id); } @@ -148,7 +148,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { return; } - let id = tcx.hir.as_local_node_id(def_id).unwrap(); + let id = tcx.hir().as_local_node_id(def_id).unwrap(); let inferred_start = self.terms_cx.inferred_starts[&id]; let current_item = &CurrentItem { inferred_start }; match tcx.type_of(def_id).sty { @@ -365,7 +365,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { return; } - let (local, remote) = if let Some(id) = self.tcx().hir.as_local_node_id(def_id) { + let (local, remote) = if let Some(id) = self.tcx().hir().as_local_node_id(def_id) { (Some(self.terms_cx.inferred_starts[&id]), None) } else { (None, Some(self.tcx().variances_of(def_id))) diff --git a/src/librustc_typeck/variance/mod.rs b/src/librustc_typeck/variance/mod.rs index e3c82d50a8d..4039281ffb7 100644 --- a/src/librustc_typeck/variance/mod.rs +++ b/src/librustc_typeck/variance/mod.rs @@ -56,12 +56,12 @@ fn crate_variances<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) fn variances_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId) -> Lrc> { - let id = tcx.hir.as_local_node_id(item_def_id).expect("expected local def-id"); + let id = tcx.hir().as_local_node_id(item_def_id).expect("expected local def-id"); let unsupported = || { // Variance not relevant. - span_bug!(tcx.hir.span(id), "asked to compute variance for wrong kind of item") + span_bug!(tcx.hir().span(id), "asked to compute variance for wrong kind of item") }; - match tcx.hir.get(id) { + match tcx.hir().get(id) { Node::Item(item) => match item.node { hir::ItemKind::Enum(..) | hir::ItemKind::Struct(..) | diff --git a/src/librustc_typeck/variance/solve.rs b/src/librustc_typeck/variance/solve.rs index 7116a42cead..365c65bc048 100644 --- a/src/librustc_typeck/variance/solve.rs +++ b/src/librustc_typeck/variance/solve.rs @@ -93,7 +93,7 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { let solutions = &self.solutions; self.terms_cx.inferred_starts.iter().map(|(&id, &InferredIndex(start))| { - let def_id = tcx.hir.local_def_id(id); + let def_id = tcx.hir().local_def_id(id); let generics = tcx.generics_of(def_id); let mut variances = solutions[start..start+generics.count()].to_vec(); diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs index 3692221a3fc..75ff5bb0c54 100644 --- a/src/librustc_typeck/variance/terms.rs +++ b/src/librustc_typeck/variance/terms.rs @@ -91,7 +91,7 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx> // // - https://rust-lang.github.io/rustc-guide/query.html // - https://rust-lang.github.io/rustc-guide/variance.html - tcx.hir.krate().visit_all_item_likes(&mut terms_cx); + tcx.hir().krate().visit_all_item_likes(&mut terms_cx); terms_cx } @@ -106,14 +106,14 @@ fn lang_items(tcx: TyCtxt) -> Vec<(ast::NodeId, Vec)> { all.into_iter() // iterating over (Option, Variance) .filter(|&(ref d,_)| d.is_some()) .map(|(d, v)| (d.unwrap(), v)) // (DefId, Variance) - .filter_map(|(d, v)| tcx.hir.as_local_node_id(d).map(|n| (n, v))) // (NodeId, Variance) + .filter_map(|(d, v)| tcx.hir().as_local_node_id(d).map(|n| (n, v))) // (NodeId, Variance) .collect() } impl<'a, 'tcx> TermsContext<'a, 'tcx> { fn add_inferreds_for_item(&mut self, id: ast::NodeId) { let tcx = self.tcx; - let def_id = tcx.hir.local_def_id(id); + let def_id = tcx.hir().local_def_id(id); let count = tcx.generics_of(def_id).count(); if count == 0 { @@ -125,7 +125,7 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> { let newly_added = self.inferred_starts.insert(id, InferredIndex(start)).is_none(); assert!(newly_added); - // NB: In the code below for writing the results back into the + // N.B., in the code below for writing the results back into the // `CrateVariancesMap`, we rely on the fact that all inferreds // for a particular item are assigned continuous indices. @@ -139,7 +139,7 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> { impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> { fn visit_item(&mut self, item: &hir::Item) { debug!("add_inferreds for item {}", - self.tcx.hir.node_to_string(item.id)); + self.tcx.hir().node_to_string(item.id)); match item.node { hir::ItemKind::Struct(ref struct_def, _) | diff --git a/src/librustc_typeck/variance/test.rs b/src/librustc_typeck/variance/test.rs index 1acadb7e772..7ae90e953e4 100644 --- a/src/librustc_typeck/variance/test.rs +++ b/src/librustc_typeck/variance/test.rs @@ -13,7 +13,7 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::ty::TyCtxt; pub fn test_variance<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - tcx.hir.krate().visit_all_item_likes(&mut VarianceTest { tcx }); + tcx.hir().krate().visit_all_item_likes(&mut VarianceTest { tcx }); } struct VarianceTest<'a, 'tcx: 'a> { @@ -22,7 +22,7 @@ struct VarianceTest<'a, 'tcx: 'a> { impl<'a, 'tcx> ItemLikeVisitor<'tcx> for VarianceTest<'a, 'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item) { - let item_def_id = self.tcx.hir.local_def_id(item.id); + let item_def_id = self.tcx.hir().local_def_id(item.id); // For unit testing: check for a special "rustc_variance" // attribute and report an error with various results if found. diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index fde8648c0c4..2d879fc0f30 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -17,13 +17,13 @@ use self::def_ctor::{get_def_from_def_id, get_def_from_node_id}; use super::*; -pub struct AutoTraitFinder<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> { - pub cx: &'a core::DocContext<'a, 'tcx, 'rcx, 'cstore>, +pub struct AutoTraitFinder<'a, 'tcx: 'a, 'rcx: 'a> { + pub cx: &'a core::DocContext<'a, 'tcx, 'rcx>, pub f: auto::AutoTraitFinder<'a, 'tcx>, } -impl<'a, 'tcx, 'rcx, 'cstore> AutoTraitFinder<'a, 'tcx, 'rcx, 'cstore> { - pub fn new(cx: &'a core::DocContext<'a, 'tcx, 'rcx, 'cstore>) -> Self { +impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { + pub fn new(cx: &'a core::DocContext<'a, 'tcx, 'rcx>) -> Self { let f = auto::AutoTraitFinder::new(&cx.tcx); AutoTraitFinder { cx, f } @@ -37,7 +37,7 @@ impl<'a, 'tcx, 'rcx, 'cstore> AutoTraitFinder<'a, 'tcx, 'rcx, 'cstore> { pub fn get_with_node_id(&self, id: ast::NodeId, name: String) -> Vec { get_def_from_node_id(&self.cx, id, name, &|def_ctor, name| { - let did = self.cx.tcx.hir.local_def_id(id); + let did = self.cx.tcx.hir().local_def_id(id); self.get_auto_trait_impls(did, &def_ctor, Some(name)) }) } @@ -255,7 +255,7 @@ impl<'a, 'tcx, 'rcx, 'cstore> AutoTraitFinder<'a, 'tcx, 'rcx, 'cstore> { // handle_lifetimes determines what *needs be* true in order for an impl to hold. // lexical_region_resolve, along with much of the rest of the compiler, is concerned // with determining if a given set up constraints/predicates *are* met, given some - // starting conditions (e.g. user-provided code). For this reason, it's easier + // starting conditions (e.g., user-provided code). For this reason, it's easier // to perform the calculations we need on our own, rather than trying to make // existing inference/solver code do what we want. fn handle_lifetimes<'cx>( @@ -274,7 +274,7 @@ impl<'a, 'tcx, 'rcx, 'cstore> AutoTraitFinder<'a, 'tcx, 'rcx, 'cstore> { // Flattening is done in two parts. First, we insert all of the constraints // into a map. Each RegionTarget (either a RegionVid or a Region) maps // to its smaller and larger regions. Note that 'larger' regions correspond - // to sub-regions in Rust code (e.g. in 'a: 'b, 'a is the larger region). + // to sub-regions in Rust code (e.g., in 'a: 'b, 'a is the larger region). for constraint in regions.constraints.keys() { match constraint { &Constraint::VarSubVar(r1, r2) => { @@ -524,7 +524,7 @@ impl<'a, 'tcx, 'rcx, 'cstore> AutoTraitFinder<'a, 'tcx, 'rcx, 'cstore> { // display on the docs page. Cleaning the Predicates produces sub-optimal WherePredicate's, // so we fix them up: // - // * Multiple bounds for the same type are coalesced into one: e.g. 'T: Copy', 'T: Debug' + // * Multiple bounds for the same type are coalesced into one: e.g., 'T: Copy', 'T: Debug' // becomes 'T: Copy + Debug' // * Fn bounds are handled specially - instead of leaving it as 'T: Fn(), = // K', we use the dedicated syntax 'T: Fn() -> K' @@ -545,7 +545,7 @@ impl<'a, 'tcx, 'rcx, 'cstore> AutoTraitFinder<'a, 'tcx, 'rcx, 'cstore> { ); // The `Sized` trait must be handled specially, since we only only display it when - // it is *not* required (i.e. '?Sized') + // it is *not* required (i.e., '?Sized') let sized_trait = self.cx .tcx .require_lang_item(lang_items::SizedTraitLangItem); @@ -629,7 +629,7 @@ impl<'a, 'tcx, 'rcx, 'cstore> AutoTraitFinder<'a, 'tcx, 'rcx, 'cstore> { let is_fn = match &mut b { &mut GenericBound::TraitBound(ref mut p, _) => { // Insert regions into the for_generics hash map first, to ensure - // that we don't end up with duplicate bounds (e.g. for<'b, 'b>) + // that we don't end up with duplicate bounds (e.g., for<'b, 'b>) for_generics.extend(p.generic_params.clone()); p.generic_params = for_generics.into_iter().collect(); self.is_fn_ty(&tcx, &p.trait_) @@ -737,7 +737,7 @@ impl<'a, 'tcx, 'rcx, 'cstore> AutoTraitFinder<'a, 'tcx, 'rcx, 'cstore> { hir::TraitBoundModifier::None, )); - // Remove any existing 'plain' bound (e.g. 'T: Iterator`) so + // Remove any existing 'plain' bound (e.g., 'T: Iterator`) so // that we don't see a // duplicate bound like `T: Iterator + Iterator` // on the docs page. @@ -837,7 +837,7 @@ impl<'a, 'tcx, 'rcx, 'cstore> AutoTraitFinder<'a, 'tcx, 'rcx, 'cstore> { // auto-trait impls always render in exactly the same way. // // Using the Debug implementation for sorting prevents us from needing to - // write quite a bit of almost entirely useless code (e.g. how should two + // write quite a bit of almost entirely useless code (e.g., how should two // Types be sorted relative to each other). It also allows us to solve the // problem for both WherePredicates and GenericBounds at the same time. This // approach is probably somewhat slower, but the small number of items diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 8246c7bab27..ea8f892016c 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -21,12 +21,12 @@ use super::*; use self::def_ctor::{get_def_from_def_id, get_def_from_node_id}; -pub struct BlanketImplFinder<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> { - pub cx: &'a core::DocContext<'a, 'tcx, 'rcx, 'cstore>, +pub struct BlanketImplFinder<'a, 'tcx: 'a, 'rcx: 'a> { + pub cx: &'a core::DocContext<'a, 'tcx, 'rcx>, } -impl<'a, 'tcx, 'rcx, 'cstore> BlanketImplFinder <'a, 'tcx, 'rcx, 'cstore> { - pub fn new(cx: &'a core::DocContext<'a, 'tcx, 'rcx, 'cstore>) -> Self { +impl<'a, 'tcx, 'rcx> BlanketImplFinder <'a, 'tcx, 'rcx> { + pub fn new(cx: &'a core::DocContext<'a, 'tcx, 'rcx>) -> Self { BlanketImplFinder { cx } } @@ -38,7 +38,7 @@ impl<'a, 'tcx, 'rcx, 'cstore> BlanketImplFinder <'a, 'tcx, 'rcx, 'cstore> { pub fn get_with_node_id(&self, id: ast::NodeId, name: String) -> Vec { get_def_from_node_id(&self.cx, id, name, &|def_ctor, name| { - let did = self.cx.tcx.hir.local_def_id(id); + let did = self.cx.tcx.hir().local_def_id(id); self.get_blanket_impls(did, &def_ctor, Some(name)) }) } diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index f90f1e54da2..847786d123e 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -31,13 +31,13 @@ pub enum Cfg { True, /// Denies all configurations. False, - /// A generic configuration option, e.g. `test` or `target_os = "linux"`. + /// A generic configuration option, e.g., `test` or `target_os = "linux"`. Cfg(Symbol, Option), - /// Negate a configuration requirement, i.e. `not(x)`. + /// Negate a configuration requirement, i.e., `not(x)`. Not(Box), - /// Union of a list of configuration requirements, i.e. `any(...)`. + /// Union of a list of configuration requirements, i.e., `any(...)`. Any(Vec), - /// Intersection of a list of configuration requirements, i.e. `all(...)`. + /// Intersection of a list of configuration requirements, i.e., `all(...)`. All(Vec), } @@ -61,7 +61,7 @@ impl Cfg { /// Parses a `MetaItem` into a `Cfg`. /// - /// The `MetaItem` should be the content of the `#[cfg(...)]`, e.g. `unix` or + /// The `MetaItem` should be the content of the `#[cfg(...)]`, e.g., `unix` or /// `target_os = "redox"`. /// /// If the content is not properly formatted, it will return an error indicating what and where diff --git a/src/librustdoc/clean/def_ctor.rs b/src/librustdoc/clean/def_ctor.rs index cd9f4eb42df..b14c36a59e8 100644 --- a/src/librustdoc/clean/def_ctor.rs +++ b/src/librustdoc/clean/def_ctor.rs @@ -54,7 +54,7 @@ pub fn get_def_from_node_id(cx: &DocContext, callback: &F, ) -> Vec where F: Fn(& dyn Fn(DefId) -> Def, String) -> Vec { - let item = &cx.tcx.hir.expect_item(id).node; + let item = &cx.tcx.hir().expect_item(id).node; callback(&match *item { hir::ItemKind::Struct(_, _) => Def::Struct, diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 49cecd5b04b..4bd3c6a8455 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -207,7 +207,7 @@ pub fn build_external_trait(cx: &DocContext, did: DefId) -> clean::Trait { fn build_external_function(cx: &DocContext, did: DefId) -> clean::Function { let sig = cx.tcx.fn_sig(did); - let constness = if cx.tcx.is_const_fn(did) { + let constness = if cx.tcx.is_min_const_fn(did) { hir::Constness::Const } else { hir::Constness::NotConst @@ -303,8 +303,8 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec) { } } - let for_ = if let Some(nodeid) = tcx.hir.as_local_node_id(did) { - match tcx.hir.expect_item(nodeid).node { + 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) } @@ -325,12 +325,12 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec) { } let predicates = tcx.predicates_of(did); - let (trait_items, generics) = if let Some(nodeid) = tcx.hir.as_local_node_id(did) { - match tcx.hir.expect_item(nodeid).node { + 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)) + .map(|ii| tcx.hir().impl_item(ii.id).clean(cx)) .collect::>(), gen.clean(cx), ) @@ -420,8 +420,8 @@ fn build_module(cx: &DocContext, did: DefId, visited: &mut FxHashSet) -> } pub fn print_inlined_const(cx: &DocContext, did: DefId) -> String { - if let Some(node_id) = cx.tcx.hir.as_local_node_id(did) { - cx.tcx.hir.node_to_pretty_string(node_id) + 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) } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index fd8f70b19e7..01ead05999b 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -11,14 +11,31 @@ //! This module contains the "cleaned" pieces of the AST, and the functions //! that clean them. -pub use self::Type::*; -pub use self::Mutability::*; -pub use self::ItemEnum::*; -pub use self::SelfTy::*; -pub use self::FunctionRetTy::*; -pub use self::Visibility::{Public, Inherited}; +pub mod inline; +pub mod cfg; +mod simplify; +mod auto_trait; +mod blanket_impl; +pub mod def_ctor; +use rustc_data_structures::indexed_vec::{IndexVec, Idx}; +use rustc_data_structures::sync::Lrc; use rustc_target::spec::abi::Abi; +use rustc_typeck::hir_ty_to_ty; +use rustc::infer::region_constraints::{RegionConstraintData, Constraint}; +use rustc::mir::interpret::ConstValue; +use rustc::middle::resolve_lifetime as rl; +use rustc::middle::lang_items; +use rustc::middle::stability; +use rustc::mir::interpret::GlobalId; +use rustc::hir::{self, GenericArg, HirVec}; +use rustc::hir::def::{self, Def, CtorKind}; +use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc::ty::subst::Substs; +use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind}; +use rustc::ty::fold::TypeFolder; +use rustc::ty::layout::VariantIdx; +use rustc::util::nodemap::{FxHashMap, FxHashSet}; use syntax::ast::{self, AttrStyle, Ident}; use syntax::attr; use syntax::ext::base::MacroKind; @@ -28,30 +45,12 @@ use syntax::symbol::keywords::{self, Keyword}; use syntax::symbol::InternedString; use syntax_pos::{self, DUMMY_SP, Pos, FileName}; -use rustc::mir::interpret::ConstValue; -use rustc::middle::resolve_lifetime as rl; -use rustc::ty::fold::TypeFolder; -use rustc::middle::lang_items; -use rustc::mir::interpret::GlobalId; -use rustc::hir::{self, GenericArg, HirVec}; -use rustc::hir::def::{self, Def, CtorKind}; -use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; -use rustc::ty::subst::Substs; -use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind}; -use rustc::ty::layout::VariantIdx; -use rustc::middle::stability; -use rustc::util::nodemap::{FxHashMap, FxHashSet}; -use rustc_typeck::hir_ty_to_ty; -use rustc::infer::region_constraints::{RegionConstraintData, Constraint}; -use rustc_data_structures::indexed_vec::{IndexVec, Idx}; - use std::collections::hash_map::Entry; use std::fmt; use std::hash::{Hash, Hasher}; use std::default::Default; use std::{mem, slice, vec}; use std::iter::{FromIterator, once}; -use rustc_data_structures::sync::Lrc; use std::rc::Rc; use std::str::FromStr; use std::cell::RefCell; @@ -66,17 +65,17 @@ use visit_ast; use html::render::{cache, ExternalLocation}; use html::item_type::ItemType; -pub mod inline; -pub mod cfg; -mod simplify; -mod auto_trait; -mod blanket_impl; -pub mod def_ctor; - use self::cfg::Cfg; use self::auto_trait::AutoTraitFinder; use self::blanket_impl::BlanketImplFinder; +pub use self::Type::*; +pub use self::Mutability::*; +pub use self::ItemEnum::*; +pub use self::SelfTy::*; +pub use self::FunctionRetTy::*; +pub use self::Visibility::{Public, Inherited}; + thread_local!(pub static MAX_DEF_ID: RefCell> = Default::default()); const FN_OUTPUT_NAME: &'static str = "Output"; @@ -150,7 +149,7 @@ pub struct Crate { pub masked_crates: FxHashSet, } -impl<'a, 'tcx, 'rcx, 'cstore> Clean for visit_ast::RustdocVisitor<'a, 'tcx, 'rcx, 'cstore> { +impl<'a, 'tcx, 'rcx> Clean for visit_ast::RustdocVisitor<'a, 'tcx, 'rcx> { fn clean(&self, cx: &DocContext) -> Crate { use ::visit_lib::LibEmbargoVisitor; @@ -282,17 +281,17 @@ impl Clean for CrateNum { None }; let primitives = if root.is_local() { - cx.tcx.hir.krate().module.item_ids.iter().filter_map(|&id| { - let item = cx.tcx.hir.expect_item(id.id); + cx.tcx.hir().krate().module.item_ids.iter().filter_map(|&id| { + let item = cx.tcx.hir().expect_item(id.id); match item.node { hir::ItemKind::Mod(_) => { - as_primitive(Def::Mod(cx.tcx.hir.local_def_id(id.id))) + as_primitive(Def::Mod(cx.tcx.hir().local_def_id(id.id))) } hir::ItemKind::Use(ref path, hir::UseKind::Single) if item.vis.node.is_pub() => { as_primitive(path.def).map(|(_, prim, attrs)| { // Pretend the primitive is local. - (cx.tcx.hir.local_def_id(id.id), prim, attrs) + (cx.tcx.hir().local_def_id(id.id), prim, attrs) }) } _ => None @@ -324,16 +323,16 @@ impl Clean for CrateNum { None }; let keywords = if root.is_local() { - cx.tcx.hir.krate().module.item_ids.iter().filter_map(|&id| { - let item = cx.tcx.hir.expect_item(id.id); + cx.tcx.hir().krate().module.item_ids.iter().filter_map(|&id| { + let item = cx.tcx.hir().expect_item(id.id); match item.node { hir::ItemKind::Mod(_) => { - as_keyword(Def::Mod(cx.tcx.hir.local_def_id(id.id))) + as_keyword(Def::Mod(cx.tcx.hir().local_def_id(id.id))) } hir::ItemKind::Use(ref path, hir::UseKind::Single) if item.vis.node.is_pub() => { as_keyword(path.def).map(|(_, prim, attrs)| { - (cx.tcx.hir.local_def_id(id.id), prim, attrs) + (cx.tcx.hir().local_def_id(id.id), prim, attrs) }) } _ => None @@ -479,7 +478,7 @@ impl Item { classes.push("unstable"); } - if !s.deprecated_since.is_empty() { + if s.deprecation.is_some() { classes.push("deprecated"); } @@ -504,6 +503,15 @@ impl Item { pub fn type_(&self) -> ItemType { ItemType::from(self) } + + /// Returns the info in the item's `#[deprecated]` or `#[rustc_deprecated]` attributes. + /// + /// If the item is not deprecated, returns `None`. + pub fn deprecation(&self) -> Option<&Deprecation> { + self.deprecation + .as_ref() + .or_else(|| self.stability.as_ref().and_then(|s| s.deprecation.as_ref())) + } } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] @@ -629,7 +637,7 @@ impl Clean for doctree::Module { visibility: self.vis.clean(cx), stability: self.stab.clean(cx), deprecation: self.depr.clean(cx), - def_id: cx.tcx.hir.local_def_id(self.id), + def_id: cx.tcx.hir().local_def_id(self.id), inner: ModuleItem(Module { is_crate: self.is_crate, items, @@ -708,8 +716,6 @@ impl> NestedAttributesExt for I { /// kept separate because of issue #42760. #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)] pub enum DocFragment { - // FIXME #44229 (misdreavus): sugared and raw doc comments can be brought back together once - // hoedown is completely removed from rustdoc. /// A doc fragment created from a `///` or `//!` doc comment. SugaredDoc(usize, syntax_pos::Span, String), /// A doc fragment created from a "raw" `#[doc=""]` attribute. @@ -1215,7 +1221,7 @@ impl Lifetime { impl Clean for hir::Lifetime { fn clean(&self, cx: &DocContext) -> Lifetime { if self.id != ast::DUMMY_NODE_ID { - let hir_id = cx.tcx.hir.node_to_hir_id(self.id); + let hir_id = cx.tcx.hir().node_to_hir_id(self.id); let def = cx.tcx.named_region(hir_id); match def { Some(rl::Region::EarlyBound(_, node_id, _)) | @@ -1473,7 +1479,7 @@ impl Clean for hir::GenericParam { } hir::GenericParamKind::Type { ref default, synthetic, .. } => { (self.name.ident().name.clean(cx), GenericParamDefKind::Type { - did: cx.tcx.hir.local_def_id(self.id), + did: cx.tcx.hir().local_def_id(self.id), bounds: self.bounds.clean(cx), default: default.clean(cx), synthetic: synthetic, @@ -1575,7 +1581,7 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, let stripped_typarams = gens.params.iter().filter_map(|param| match param.kind { ty::GenericParamDefKind::Lifetime => None, ty::GenericParamDefKind::Type { .. } => { - if param.name == keywords::SelfType.name().as_str() { + if param.name == keywords::SelfUpper.name().as_str() { assert_eq!(param.index, 0); return None; } @@ -1621,7 +1627,7 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, } // It would be nice to collect all of the bounds on a type and recombine - // them if possible, to avoid e.g. `where T: Foo, T: Bar, T: Sized, T: 'a` + // them if possible, to avoid e.g., `where T: Foo, T: Bar, T: Sized, T: 'a` // and instead see `where T: Foo + Bar + Sized + 'a` Generics { @@ -1677,6 +1683,12 @@ impl Clean for doctree::Function { (self.generics.clean(cx), (&self.decl, self.body).clean(cx)) }); + let did = cx.tcx.hir().local_def_id(self.id); + let constness = if cx.tcx.is_min_const_fn(did) { + hir::Constness::Const + } else { + hir::Constness::NotConst + }; Item { name: Some(self.name.clean(cx)), attrs: self.attrs.clean(cx), @@ -1684,11 +1696,11 @@ impl Clean for doctree::Function { visibility: self.vis.clean(cx), stability: self.stab.clean(cx), deprecation: self.depr.clean(cx), - def_id: cx.tcx.hir.local_def_id(self.id), + def_id: did, inner: FunctionItem(Function { decl, generics, - header: self.header, + header: hir::FnHeader { constness, ..self.header }, }), } } @@ -1733,7 +1745,7 @@ impl<'a> Clean for (&'a [hir::Ty], &'a [ast::Ident]) { impl<'a> Clean for (&'a [hir::Ty], hir::BodyId) { fn clean(&self, cx: &DocContext) -> Arguments { - let body = cx.tcx.hir.body(self.1); + let body = cx.tcx.hir().body(self.1); Arguments { values: self.0.iter().enumerate().map(|(i, ty)| { @@ -1762,7 +1774,7 @@ impl<'a, A: Copy> Clean for (&'a hir::FnDecl, A) impl<'a, 'tcx> Clean for (DefId, ty::PolyFnSig<'tcx>) { fn clean(&self, cx: &DocContext) -> FnDecl { let (did, sig) = *self; - let mut names = if cx.tcx.hir.as_local_node_id(did).is_some() { + let mut names = if cx.tcx.hir().as_local_node_id(did).is_some() { vec![].into_iter() } else { cx.tcx.fn_arg_names(did).into_iter() @@ -1857,7 +1869,7 @@ impl Clean for doctree::Trait { name: Some(self.name.clean(cx)), attrs: attrs, source: self.whence.clean(cx), - def_id: cx.tcx.hir.local_def_id(self.id), + def_id: cx.tcx.hir().local_def_id(self.id), visibility: self.vis.clean(cx), stability: self.stab.clean(cx), deprecation: self.depr.clean(cx), @@ -1926,10 +1938,10 @@ impl Clean for hir::TraitItem { name: Some(self.ident.name.clean(cx)), attrs: self.attrs.clean(cx), source: self.span.clean(cx), - def_id: cx.tcx.hir.local_def_id(self.id), + def_id: cx.tcx.hir().local_def_id(self.id), visibility: None, - stability: get_stability(cx, cx.tcx.hir.local_def_id(self.id)), - deprecation: get_deprecation(cx, cx.tcx.hir.local_def_id(self.id)), + stability: get_stability(cx, cx.tcx.hir().local_def_id(self.id)), + deprecation: get_deprecation(cx, cx.tcx.hir().local_def_id(self.id)), inner, } } @@ -1958,10 +1970,10 @@ impl Clean for hir::ImplItem { name: Some(self.ident.name.clean(cx)), source: self.span.clean(cx), attrs: self.attrs.clean(cx), - def_id: cx.tcx.hir.local_def_id(self.id), + def_id: cx.tcx.hir().local_def_id(self.id), visibility: self.vis.clean(cx), - stability: get_stability(cx, cx.tcx.hir.local_def_id(self.id)), - deprecation: get_deprecation(cx, cx.tcx.hir.local_def_id(self.id)), + stability: get_stability(cx, cx.tcx.hir().local_def_id(self.id)), + deprecation: get_deprecation(cx, cx.tcx.hir().local_def_id(self.id)), inner, } } @@ -2012,7 +2024,7 @@ impl<'tcx> Clean for ty::AssociatedItem { ty::TraitContainer(_) => self.defaultness.has_value() }; if provided { - let constness = if cx.tcx.is_const_fn(self.def_id) { + let constness = if cx.tcx.is_min_const_fn(self.def_id) { hir::Constness::Const } else { hir::Constness::NotConst @@ -2411,7 +2423,7 @@ impl Clean for hir::Ty { } TyKind::Slice(ref ty) => Slice(box ty.clean(cx)), TyKind::Array(ref ty, ref length) => { - let def_id = cx.tcx.hir.local_def_id(length.id); + let def_id = cx.tcx.hir().local_def_id(length.id); let param_env = cx.tcx.param_env(def_id); let substs = Substs::identity_for_item(cx.tcx, def_id); let cid = GlobalId { @@ -2426,7 +2438,7 @@ impl Clean for hir::Ty { }, TyKind::Tup(ref tys) => Tuple(tys.clean(cx)), TyKind::Def(item_id, _) => { - let item = cx.tcx.hir.expect_item(item_id.id); + let item = cx.tcx.hir().expect_item(item_id.id); if let hir::ItemKind::Existential(ref ty) = item.node { ImplTrait(ty.bounds.clean(cx)) } else { @@ -2447,9 +2459,9 @@ impl Clean for hir::Ty { let mut alias = None; 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 let Some(node_id) = cx.tcx.hir().as_local_node_id(def_id) { if !cx.renderinfo.borrow().access_levels.is_exported(def_id) { - alias = Some(&cx.tcx.hir.expect_item(node_id).node); + alias = Some(&cx.tcx.hir().expect_item(node_id).node); } } }; @@ -2479,7 +2491,7 @@ impl Clean for hir::Ty { if let Some(lt) = lifetime.cloned() { if !lt.is_elided() { let lt_def_id = - cx.tcx.hir.local_def_id(param.id); + cx.tcx.hir().local_def_id(param.id); lt_substs.insert(lt_def_id, lt.clean(cx)); } } @@ -2487,7 +2499,7 @@ impl Clean for hir::Ty { } hir::GenericParamKind::Type { ref default, .. } => { let ty_param_def = - Def::TyParam(cx.tcx.hir.local_def_id(param.id)); + Def::TyParam(cx.tcx.hir().local_def_id(param.id)); let mut j = 0; let type_ = generic_args.args.iter().find_map(|arg| { match arg { @@ -2608,7 +2620,7 @@ impl<'tcx> Clean for Ty<'tcx> { BareFunction(box BareFunctionDecl { unsafety: sig.unsafety(), generic_params: Vec::new(), - decl: (cx.tcx.hir.local_def_id(ast::CRATE_NODE_ID), sig).clean(cx), + decl: (cx.tcx.hir().local_def_id(ast::CRATE_NODE_ID), sig).clean(cx), abi: sig.abi(), }) } @@ -2760,9 +2772,9 @@ impl Clean for hir::StructField { attrs: self.attrs.clean(cx), source: self.span.clean(cx), visibility: self.vis.clean(cx), - stability: get_stability(cx, cx.tcx.hir.local_def_id(self.id)), - deprecation: get_deprecation(cx, cx.tcx.hir.local_def_id(self.id)), - def_id: cx.tcx.hir.local_def_id(self.id), + stability: get_stability(cx, cx.tcx.hir().local_def_id(self.id)), + deprecation: get_deprecation(cx, cx.tcx.hir().local_def_id(self.id)), + def_id: cx.tcx.hir().local_def_id(self.id), inner: StructFieldItem(self.ty.clean(cx)), } } @@ -2834,7 +2846,7 @@ impl Clean for doctree::Struct { 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), + def_id: cx.tcx.hir().local_def_id(self.id), visibility: self.vis.clean(cx), stability: self.stab.clean(cx), deprecation: self.depr.clean(cx), @@ -2854,7 +2866,7 @@ impl Clean for doctree::Union { 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), + def_id: cx.tcx.hir().local_def_id(self.id), visibility: self.vis.clean(cx), stability: self.stab.clean(cx), deprecation: self.depr.clean(cx), @@ -2901,7 +2913,7 @@ impl Clean for doctree::Enum { 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), + def_id: cx.tcx.hir().local_def_id(self.id), visibility: self.vis.clean(cx), stability: self.stab.clean(cx), deprecation: self.depr.clean(cx), @@ -2928,7 +2940,7 @@ impl Clean for doctree::Variant { visibility: None, stability: self.stab.clean(cx), deprecation: self.depr.clean(cx), - def_id: cx.tcx.hir.local_def_id(self.def.id()), + def_id: cx.tcx.hir().local_def_id(self.def.id()), inner: VariantItem(Variant { kind: self.def.clean(cx), }), @@ -3008,7 +3020,7 @@ pub struct Span { impl Span { pub fn empty() -> Span { Span { - filename: FileName::Anon, + filename: FileName::Anon(0), loline: 0, locol: 0, hiline: 0, hicol: 0, } @@ -3174,7 +3186,7 @@ fn qpath_to_string(p: &hir::QPath) -> String { if i > 0 { s.push_str("::"); } - if seg.ident.name != keywords::CrateRoot.name() { + if seg.ident.name != keywords::PathRoot.name() { s.push_str(&*seg.ident.as_str()); } } @@ -3205,7 +3217,7 @@ impl Clean for doctree::Typedef { 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.clone()), + def_id: cx.tcx.hir().local_def_id(self.id.clone()), visibility: self.vis.clean(cx), stability: self.stab.clean(cx), deprecation: self.depr.clean(cx), @@ -3229,7 +3241,7 @@ impl Clean for doctree::Existential { 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.clone()), + def_id: cx.tcx.hir().local_def_id(self.id.clone()), visibility: self.vis.clean(cx), stability: self.stab.clean(cx), deprecation: self.depr.clean(cx), @@ -3280,7 +3292,7 @@ impl Clean for doctree::Static { 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), + def_id: cx.tcx.hir().local_def_id(self.id), visibility: self.vis.clean(cx), stability: self.stab.clean(cx), deprecation: self.depr.clean(cx), @@ -3305,7 +3317,7 @@ impl Clean for doctree::Constant { 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), + def_id: cx.tcx.hir().local_def_id(self.id), visibility: self.vis.clean(cx), stability: self.stab.clean(cx), deprecation: self.depr.clean(cx), @@ -3405,7 +3417,7 @@ impl Clean> for doctree::Impl { name: None, attrs: self.attrs.clean(cx), source: self.whence.clean(cx), - def_id: cx.tcx.hir.local_def_id(self.id), + def_id: cx.tcx.hir().local_def_id(self.id), visibility: self.vis.clean(cx), stability: self.stab.clean(cx), deprecation: self.depr.clean(cx), @@ -3548,7 +3560,7 @@ impl Clean> for doctree::Import { name: None, attrs: self.attrs.clean(cx), source: self.whence.clean(cx), - def_id: cx.tcx.hir.local_def_id(ast::CRATE_NODE_ID), + def_id: cx.tcx.hir().local_def_id(ast::CRATE_NODE_ID), visibility: self.vis.clean(cx), stability: None, deprecation: None, @@ -3617,10 +3629,10 @@ impl Clean for hir::ForeignItem { name: Some(self.name.clean(cx)), attrs: self.attrs.clean(cx), source: self.span.clean(cx), - def_id: cx.tcx.hir.local_def_id(self.id), + def_id: cx.tcx.hir().local_def_id(self.id), visibility: self.vis.clean(cx), - stability: get_stability(cx, cx.tcx.hir.local_def_id(self.id)), - deprecation: get_deprecation(cx, cx.tcx.hir.local_def_id(self.id)), + stability: get_stability(cx, cx.tcx.hir().local_def_id(self.id)), + deprecation: get_deprecation(cx, cx.tcx.hir().local_def_id(self.id)), inner, } } @@ -3683,8 +3695,8 @@ fn name_from_pat(p: &hir::Pat) -> String { fn print_const(cx: &DocContext, n: &ty::Const) -> String { match n.val { ConstValue::Unevaluated(def_id, _) => { - if let Some(node_id) = cx.tcx.hir.as_local_node_id(def_id) { - print_const_expr(cx, cx.tcx.hir.body_owned_by(node_id)) + if let Some(node_id) = cx.tcx.hir().as_local_node_id(def_id) { + print_const_expr(cx, cx.tcx.hir().body_owned_by(node_id)) } else { inline::print_inlined_const(cx, def_id) } @@ -3703,7 +3715,7 @@ fn print_const(cx: &DocContext, n: &ty::Const) -> String { } fn print_const_expr(cx: &DocContext, body: hir::BodyId) -> String { - cx.tcx.hir.node_to_pretty_string(body.node_id) + cx.tcx.hir().node_to_pretty_string(body.node_id) } /// Given a type Path, resolve it to a Type using the TyCtxt @@ -3726,7 +3738,7 @@ fn resolve_type(cx: &DocContext, hir::Float(float_ty) => return Primitive(float_ty.into()), }, Def::SelfTy(..) if path.segments.len() == 1 => { - return Generic(keywords::SelfType.name().to_string()); + return Generic(keywords::SelfUpper.name().to_string()); } Def::TyParam(..) if path.segments.len() == 1 => { return Generic(format!("{:#}", path)); @@ -3829,7 +3841,7 @@ impl Clean for doctree::ProcMacro { visibility: Some(Public), stability: self.stab.clean(cx), deprecation: self.depr.clean(cx), - def_id: cx.tcx.hir.local_def_id(self.id), + def_id: cx.tcx.hir().local_def_id(self.id), inner: ProcMacroItem(ProcMacro { kind: self.kind, helpers: self.helpers.clean(cx), @@ -3841,40 +3853,37 @@ impl Clean for doctree::ProcMacro { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Stability { pub level: stability::StabilityLevel, - pub feature: String, + pub feature: Option, pub since: String, - pub deprecated_since: String, - pub deprecated_reason: String, - pub unstable_reason: String, - pub issue: Option + pub deprecation: Option, + pub unstable_reason: Option, + pub issue: Option, } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Deprecation { - pub since: String, - pub note: String, + pub since: Option, + pub note: Option, } impl Clean for attr::Stability { fn clean(&self, _: &DocContext) -> Stability { Stability { level: stability::StabilityLevel::from_attr_level(&self.level), - feature: self.feature.to_string(), + feature: Some(self.feature.to_string()).filter(|f| !f.is_empty()), since: match self.level { attr::Stable {ref since} => since.to_string(), _ => String::new(), }, - deprecated_since: match self.rustc_depr { - Some(attr::RustcDeprecation {ref since, ..}) => since.to_string(), - _=> String::new(), - }, - deprecated_reason: match self.rustc_depr { - Some(ref depr) => depr.reason.to_string(), - _ => String::new(), - }, + deprecation: self.rustc_depr.as_ref().map(|d| { + Deprecation { + note: Some(d.reason.to_string()).filter(|r| !r.is_empty()), + since: Some(d.since.to_string()).filter(|d| !d.is_empty()), + } + }), unstable_reason: match self.level { - attr::Unstable { reason: Some(ref reason), .. } => reason.to_string(), - _ => String::new(), + attr::Unstable { reason: Some(ref reason), .. } => Some(reason.to_string()), + _ => None, }, issue: match self.level { attr::Unstable {issue, ..} => Some(issue), @@ -3893,13 +3902,13 @@ impl<'a> Clean for &'a attr::Stability { impl Clean for attr::Deprecation { fn clean(&self, _: &DocContext) -> Deprecation { Deprecation { - since: self.since.as_ref().map_or(String::new(), |s| s.to_string()), - note: self.note.as_ref().map_or(String::new(), |s| s.to_string()), + since: self.since.map(|s| s.to_string()).filter(|s| !s.is_empty()), + note: self.note.map(|n| n.to_string()).filter(|n| !n.is_empty()), } } } -/// An equality constraint on an associated type, e.g. `A=Bar` in `Foo` +/// An equality constraint on an associated type, e.g., `A=Bar` in `Foo` #[derive(Clone, PartialEq, Eq, RustcDecodable, RustcEncodable, Debug, Hash)] pub struct TypeBinding { pub name: String, @@ -3943,21 +3952,18 @@ where // Start of code copied from rust-clippy pub fn path_to_def_local(tcx: &TyCtxt, path: &[&str]) -> Option { - let krate = tcx.hir.krate(); + let krate = tcx.hir().krate(); let mut items = krate.module.item_ids.clone(); let mut path_it = path.iter().peekable(); loop { - let segment = match path_it.next() { - Some(segment) => segment, - None => return None, - }; + let segment = path_it.next()?; for item_id in mem::replace(&mut items, HirVec::new()).iter() { - let item = tcx.hir.expect_item(item_id.id); + let item = tcx.hir().expect_item(item_id.id); if item.name == *segment { if path_it.peek().is_none() { - return Some(tcx.hir.local_def_id(item_id.id)) + return Some(tcx.hir().local_def_id(item_id.id)) } items = match &item.node { @@ -3986,10 +3992,7 @@ pub fn path_to_def(tcx: &TyCtxt, path: &[&str]) -> Option { let mut path_it = path.iter().skip(1).peekable(); loop { - let segment = match path_it.next() { - Some(segment) => segment, - None => return None, - }; + let segment = path_it.next()?; for item in mem::replace(&mut items, Lrc::new(vec![])).iter() { if item.ident.name == *segment { diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index 635608d140d..81608b380d0 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -12,7 +12,7 @@ //! more canonical form. //! //! Currently all cross-crate-inlined function use `rustc::ty` to reconstruct -//! the AST (e.g. see all of `clean::inline`), but this is not always a +//! the AST (e.g., see all of `clean::inline`), but this is not always a //! non-lossy transformation. The current format of storage for where clauses //! for functions and such is simply a list of predicates. One example of this //! is that the AST predicate of: `where T: Trait` is encoded as: diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index f4d05c6dbd6..f9a46fe362e 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -20,7 +20,7 @@ use rustc::session::early_error; use rustc::session::config::{CodegenOptions, DebuggingOptions, ErrorOutputType, Externs}; use rustc::session::config::{nightly_options, build_codegen_options, build_debugging_options, get_cmd_lint_options}; -use rustc::session::search_paths::SearchPaths; +use rustc::session::search_paths::SearchPath; use rustc_driver; use rustc_target::spec::TargetTriple; use syntax::edition::Edition; @@ -46,7 +46,7 @@ pub struct Options { /// How to format errors and warnings. pub error_format: ErrorOutputType, /// Library search paths to hand to the compiler. - pub libs: SearchPaths, + pub libs: Vec, /// The list of external crates to link against. pub externs: Externs, /// List of `cfg` flags to hand to the compiler. Always includes `rustdoc`. @@ -181,6 +181,9 @@ pub struct RenderOptions { /// A file to use as the index page at the root of the output directory. Overrides /// `enable_index_page` to be true if set. pub index_page: Option, + /// An optional path to use as the location of static files. If not set, uses combinations of + /// `../` to reach the documentation root. + pub static_root_path: Option, // Options specific to reading standalone Markdown files @@ -295,10 +298,9 @@ impl Options { } let input = PathBuf::from(&matches.free[0]); - let mut libs = SearchPaths::new(); - for s in &matches.opt_strs("L") { - libs.add_path(s, error_format); - } + let libs = matches.opt_strs("L").iter() + .map(|s| SearchPath::from_cli_opt(s, error_format)) + .collect(); let externs = match parse_externs(&matches) { Ok(ex) => ex, Err(err) => { @@ -434,6 +436,7 @@ impl Options { let markdown_playground_url = matches.opt_str("markdown-playground-url"); let crate_version = matches.opt_str("crate-version"); let enable_index_page = matches.opt_present("enable-index-page") || index_page.is_some(); + let static_root_path = matches.opt_str("static-root-path"); let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format); @@ -472,6 +475,7 @@ impl Options { enable_minification, enable_index_page, index_page, + static_root_path, markdown_no_toc, markdown_css, markdown_playground_url, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index aac0f9f94e3..fa74e7094f6 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -51,13 +51,13 @@ use html::render::RenderInfo; use passes; pub use rustc::session::config::{Input, Options, CodegenOptions}; -pub use rustc::session::search_paths::SearchPaths; +pub use rustc::session::search_paths::SearchPath; pub type ExternalPaths = FxHashMap, clean::TypeKind)>; -pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> { +pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a> { pub tcx: TyCtxt<'a, 'tcx, 'tcx>, - pub resolver: &'a RefCell>, + pub resolver: &'a RefCell>, /// The stack of module NodeIds up till this point pub crate_name: Option, pub cstore: Rc, @@ -88,7 +88,7 @@ pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> { pub all_traits: Vec, } -impl<'a, 'tcx, 'rcx, 'cstore> DocContext<'a, 'tcx, 'rcx, 'cstore> { +impl<'a, 'tcx, 'rcx> DocContext<'a, 'tcx, 'rcx> { pub fn sess(&self) -> &session::Session { &self.tcx.sess } @@ -121,7 +121,7 @@ impl<'a, 'tcx, 'rcx, 'cstore> DocContext<'a, 'tcx, 'rcx, 'cstore> { let start_def_id = { let next_id = if crate_num == LOCAL_CRATE { self.tcx - .hir + .hir() .definitions() .def_path_table() .next_id(DefIndexAddressSpace::Low) @@ -168,7 +168,7 @@ impl<'a, 'tcx, 'rcx, 'cstore> DocContext<'a, 'tcx, 'rcx, 'cstore> { if self.all_fake_def_ids.borrow().contains(&def_id) { None } else { - self.tcx.hir.as_local_node_id(def_id) + self.tcx.hir().as_local_node_id(def_id) } } @@ -485,7 +485,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt glob_map: if resolver.make_glob_map { Some(resolver.glob_map.clone()) } else { None }, }; - let arenas = AllArenas::new(); + let mut arenas = AllArenas::new(); let hir_map = hir_map::map_crate(&sess, &*cstore, &mut hir_forest, &defs); let output_filenames = driver::build_output_filenames(&input, &None, @@ -501,7 +501,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt hir_map, analysis, resolutions, - &arenas, + &mut arenas, &name, &output_filenames, |tcx, analysis, _, result| { @@ -515,7 +515,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt // to the map from defid -> nodeid let access_levels = AccessLevels { map: access_levels.map.iter() - .map(|(&k, &v)| (tcx.hir.local_def_id(k), v)) + .map(|(&k, &v)| (tcx.hir().local_def_id(k), v)) .collect() }; @@ -545,11 +545,11 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt generated_synthetics: Default::default(), all_traits: tcx.all_traits(LOCAL_CRATE).to_vec(), }; - debug!("crate: {:?}", tcx.hir.krate()); + debug!("crate: {:?}", tcx.hir().krate()); let mut krate = { let mut v = RustdocVisitor::new(&ctxt); - v.visit(tcx.hir.krate()); + v.visit(tcx.hir().krate()); v.clean(&ctxt) }; diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 5263cfe7b0e..d8a57bc93fd 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -26,16 +26,20 @@ pub struct Page<'a> { pub title: &'a str, pub css_class: &'a str, pub root_path: &'a str, + pub static_root_path: Option<&'a str>, pub description: &'a str, pub keywords: &'a str, pub resource_suffix: &'a str, + pub extra_scripts: &'a [&'a str], + pub static_extra_scripts: &'a [&'a str], } pub fn render( dst: &mut dyn io::Write, layout: &Layout, page: &Page, sidebar: &S, t: &T, - css_file_extension: bool, themes: &[PathBuf], extra_scripts: &[&str]) + css_file_extension: bool, themes: &[PathBuf]) -> io::Result<()> { + let static_root_path = page.static_root_path.unwrap_or(page.root_path); write!(dst, "\ \ @@ -46,17 +50,21 @@ pub fn render( \ \ {title}\ - \ - \ + \ {themes}\ - \ - \ + \ - \ + \ + \ {css_extension}\ {favicon}\ {in_header}\ + \ \ \ /---------\ next ---, + // | |head_tail| | + // `--- prev \---------/ <-------` + assert_eq!(self.head_tail.as_ref().prev, first); + true + } else { + false + } + } else { + true + } + } + } + + /// Pushes an entry onto the back of the list. + /// + /// # Safety + /// + /// The entry must remain allocated until the entry is removed from the + /// list AND the caller who popped is done using the entry. + pub unsafe fn push<'a>(&mut self, entry: &'a mut UnsafeListEntry) -> &'a T { + self.init(); + + // BEFORE: + // /---------\ next ---> /---------\ + // ... |prev_tail| |head_tail| ... + // \---------/ <--- prev \---------/ + // + // AFTER: + // /---------\ next ---> /-----\ next ---> /---------\ + // ... |prev_tail| |entry| |head_tail| ... + // \---------/ <--- prev \-----/ <--- prev \---------/ + let mut entry = NonNull::new_unchecked(entry); + let mut prev_tail = mem::replace(&mut self.head_tail.as_mut().prev, entry); + entry.as_mut().prev = prev_tail; + entry.as_mut().next = self.head_tail; + prev_tail.as_mut().next = entry; + (*entry.as_ptr()).value.as_ref().unwrap() + } + + /// Pops an entry from the front of the list. + /// + /// # Safety + /// + /// The caller must make sure to synchronize ending the borrow of the + /// return value and deallocation of the containing entry. + pub unsafe fn pop<'a>(&mut self) -> Option<&'a T> { + self.init(); + + if self.is_empty() { + None + } else { + // BEFORE: + // /---------\ next ---> /-----\ next ---> /------\ + // ... |head_tail| |first| |second| ... + // \---------/ <--- prev \-----/ <--- prev \------/ + // + // AFTER: + // /---------\ next ---> /------\ + // ... |head_tail| |second| ... + // \---------/ <--- prev \------/ + let mut first = self.head_tail.as_mut().next; + let mut second = first.as_mut().next; + self.head_tail.as_mut().next = second; + second.as_mut().prev = self.head_tail; + first.as_mut().next = NonNull::dangling(); + first.as_mut().prev = NonNull::dangling(); + Some((*first.as_ptr()).value.as_ref().unwrap()) + } + } + } + + #[cfg(test)] + mod tests { + use super::*; + use cell::Cell; + + unsafe fn assert_empty(list: &mut UnsafeList) { + assert!(list.pop().is_none(), "assertion failed: list is not empty"); + } + + #[test] + fn init_empty() { + unsafe { + assert_empty(&mut UnsafeList::::new()); + } + } + + #[test] + fn push_pop() { + unsafe { + let mut node = UnsafeListEntry::new(1234); + let mut list = UnsafeList::new(); + assert_eq!(list.push(&mut node), &1234); + assert_eq!(list.pop().unwrap(), &1234); + assert_empty(&mut list); + } + } + + #[test] + fn complex_pushes_pops() { + unsafe { + let mut node1 = UnsafeListEntry::new(1234); + let mut node2 = UnsafeListEntry::new(4567); + let mut node3 = UnsafeListEntry::new(9999); + let mut node4 = UnsafeListEntry::new(8642); + let mut list = UnsafeList::new(); + list.push(&mut node1); + list.push(&mut node2); + assert_eq!(list.pop().unwrap(), &1234); + list.push(&mut node3); + assert_eq!(list.pop().unwrap(), &4567); + assert_eq!(list.pop().unwrap(), &9999); + assert_empty(&mut list); + list.push(&mut node4); + assert_eq!(list.pop().unwrap(), &8642); + assert_empty(&mut list); + } + } + + #[test] + fn cell() { + unsafe { + let mut node = UnsafeListEntry::new(Cell::new(0)); + let mut list = UnsafeList::new(); + let noderef = list.push(&mut node); + assert_eq!(noderef.get(), 0); + list.pop().unwrap().set(1); + assert_empty(&mut list); + assert_eq!(noderef.get(), 1); + } + } + } +} + +/// Trivial spinlock-based implementation of `sync::Mutex`. +// FIXME: Perhaps use Intel TSX to avoid locking? +mod spin_mutex { + use cell::UnsafeCell; + use sync::atomic::{AtomicBool, Ordering, spin_loop_hint}; + use ops::{Deref, DerefMut}; + + #[derive(Default)] + pub struct SpinMutex { + value: UnsafeCell, + lock: AtomicBool, + } + + unsafe impl Send for SpinMutex {} + unsafe impl Sync for SpinMutex {} + + pub struct SpinMutexGuard<'a, T: 'a> { + mutex: &'a SpinMutex, + } + + impl<'a, T> !Send for SpinMutexGuard<'a, T> {} + unsafe impl<'a, T: Sync> Sync for SpinMutexGuard<'a, T> {} + + impl SpinMutex { + pub const fn new(value: T) -> Self { + SpinMutex { + value: UnsafeCell::new(value), + lock: AtomicBool::new(false) + } + } + + #[inline(always)] + pub fn lock(&self) -> SpinMutexGuard { + loop { + match self.try_lock() { + None => while self.lock.load(Ordering::Relaxed) { + spin_loop_hint() + }, + Some(guard) => return guard + } + } + } + + #[inline(always)] + pub fn try_lock(&self) -> Option> { + if !self.lock.compare_and_swap(false, true, Ordering::Acquire) { + Some(SpinMutexGuard { + mutex: self, + }) + } else { + None + } + } + } + + pub macro try_lock_or_false { + ($e:expr) => { + if let Some(v) = $e.try_lock() { + v + } else { + return false + } + } + } + + impl<'a, T> Deref for SpinMutexGuard<'a, T> { + type Target = T; + + fn deref(&self) -> &T { + unsafe { + &*self.mutex.value.get() + } + } + } + + impl<'a, T> DerefMut for SpinMutexGuard<'a, T> { + fn deref_mut(&mut self) -> &mut T { + unsafe { + &mut*self.mutex.value.get() + } + } + } + + impl<'a, T> Drop for SpinMutexGuard<'a, T> { + fn drop(&mut self) { + self.mutex.lock.store(false, Ordering::Release) + } + } + + #[cfg(test)] + mod tests { + #![allow(deprecated)] + + use super::*; + use sync::Arc; + use thread; + + #[test] + fn sleep() { + let mutex = Arc::new(SpinMutex::::default()); + let mutex2 = mutex.clone(); + let guard = mutex.lock(); + let t1 = thread::spawn(move || { + *mutex2.lock() = 1; + }); + thread::sleep_ms(50); + assert_eq!(*guard, 0); + drop(guard); + t1.join().unwrap(); + assert_eq!(*mutex.lock(), 1); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use sync::Arc; + use thread; + + #[test] + fn queue() { + let wq = Arc::new(SpinMutex::>::default()); + let wq2 = wq.clone(); + + let locked = wq.lock(); + + let t1 = thread::spawn(move || { + assert!(WaitQueue::notify_one(wq2.lock()).is_none()) + }); + + WaitQueue::wait(locked); + + t1.join().unwrap(); + } +} diff --git a/src/libstd/sys/unix/android.rs b/src/libstd/sys/unix/android.rs index 10436723a81..462eab56664 100644 --- a/src/libstd/sys/unix/android.rs +++ b/src/libstd/sys/unix/android.rs @@ -15,7 +15,7 @@ //! always work with the most recent version of Android, but we also want to //! work with older versions of Android for whenever projects need to. //! -//! Our current minimum supported Android version is `android-9`, e.g. Android +//! Our current minimum supported Android version is `android-9`, e.g., Android //! with API level 9. We then in theory want to work on that and all future //! versions of Android! //! diff --git a/src/libstd/sys/unix/env.rs b/src/libstd/sys/unix/env.rs index ad116c57f55..1b6838f0295 100644 --- a/src/libstd/sys/unix/env.rs +++ b/src/libstd/sys/unix/env.rs @@ -10,176 +10,176 @@ #[cfg(target_os = "linux")] pub mod os { - pub const FAMILY: &'static str = "unix"; - pub const OS: &'static str = "linux"; - pub const DLL_PREFIX: &'static str = "lib"; - pub const DLL_SUFFIX: &'static str = ".so"; - pub const DLL_EXTENSION: &'static str = "so"; - pub const EXE_SUFFIX: &'static str = ""; - pub const EXE_EXTENSION: &'static str = ""; + pub const FAMILY: &str = "unix"; + pub const OS: &str = "linux"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".so"; + pub const DLL_EXTENSION: &str = "so"; + pub const EXE_SUFFIX: &str = ""; + pub const EXE_EXTENSION: &str = ""; } #[cfg(target_os = "macos")] pub mod os { - pub const FAMILY: &'static str = "unix"; - pub const OS: &'static str = "macos"; - pub const DLL_PREFIX: &'static str = "lib"; - pub const DLL_SUFFIX: &'static str = ".dylib"; - pub const DLL_EXTENSION: &'static str = "dylib"; - pub const EXE_SUFFIX: &'static str = ""; - pub const EXE_EXTENSION: &'static str = ""; + pub const FAMILY: &str = "unix"; + pub const OS: &str = "macos"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".dylib"; + pub const DLL_EXTENSION: &str = "dylib"; + pub const EXE_SUFFIX: &str = ""; + pub const EXE_EXTENSION: &str = ""; } #[cfg(target_os = "ios")] pub mod os { - pub const FAMILY: &'static str = "unix"; - pub const OS: &'static str = "ios"; - pub const DLL_PREFIX: &'static str = "lib"; - pub const DLL_SUFFIX: &'static str = ".dylib"; - pub const DLL_EXTENSION: &'static str = "dylib"; - pub const EXE_SUFFIX: &'static str = ""; - pub const EXE_EXTENSION: &'static str = ""; + pub const FAMILY: &str = "unix"; + pub const OS: &str = "ios"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".dylib"; + pub const DLL_EXTENSION: &str = "dylib"; + pub const EXE_SUFFIX: &str = ""; + pub const EXE_EXTENSION: &str = ""; } #[cfg(target_os = "freebsd")] pub mod os { - pub const FAMILY: &'static str = "unix"; - pub const OS: &'static str = "freebsd"; - pub const DLL_PREFIX: &'static str = "lib"; - pub const DLL_SUFFIX: &'static str = ".so"; - pub const DLL_EXTENSION: &'static str = "so"; - pub const EXE_SUFFIX: &'static str = ""; - pub const EXE_EXTENSION: &'static str = ""; + pub const FAMILY: &str = "unix"; + pub const OS: &str = "freebsd"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".so"; + pub const DLL_EXTENSION: &str = "so"; + pub const EXE_SUFFIX: &str = ""; + pub const EXE_EXTENSION: &str = ""; } #[cfg(target_os = "dragonfly")] pub mod os { - pub const FAMILY: &'static str = "unix"; - pub const OS: &'static str = "dragonfly"; - pub const DLL_PREFIX: &'static str = "lib"; - pub const DLL_SUFFIX: &'static str = ".so"; - pub const DLL_EXTENSION: &'static str = "so"; - pub const EXE_SUFFIX: &'static str = ""; - pub const EXE_EXTENSION: &'static str = ""; + pub const FAMILY: &str = "unix"; + pub const OS: &str = "dragonfly"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".so"; + pub const DLL_EXTENSION: &str = "so"; + pub const EXE_SUFFIX: &str = ""; + pub const EXE_EXTENSION: &str = ""; } #[cfg(target_os = "bitrig")] pub mod os { - pub const FAMILY: &'static str = "unix"; - pub const OS: &'static str = "bitrig"; - pub const DLL_PREFIX: &'static str = "lib"; - pub const DLL_SUFFIX: &'static str = ".so"; - pub const DLL_EXTENSION: &'static str = "so"; - pub const EXE_SUFFIX: &'static str = ""; - pub const EXE_EXTENSION: &'static str = ""; + pub const FAMILY: &str = "unix"; + pub const OS: &str = "bitrig"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".so"; + pub const DLL_EXTENSION: &str = "so"; + pub const EXE_SUFFIX: &str = ""; + pub const EXE_EXTENSION: &str = ""; } #[cfg(target_os = "netbsd")] pub mod os { - pub const FAMILY: &'static str = "unix"; - pub const OS: &'static str = "netbsd"; - pub const DLL_PREFIX: &'static str = "lib"; - pub const DLL_SUFFIX: &'static str = ".so"; - pub const DLL_EXTENSION: &'static str = "so"; - pub const EXE_SUFFIX: &'static str = ""; - pub const EXE_EXTENSION: &'static str = ""; + pub const FAMILY: &str = "unix"; + pub const OS: &str = "netbsd"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".so"; + pub const DLL_EXTENSION: &str = "so"; + pub const EXE_SUFFIX: &str = ""; + pub const EXE_EXTENSION: &str = ""; } #[cfg(target_os = "openbsd")] pub mod os { - pub const FAMILY: &'static str = "unix"; - pub const OS: &'static str = "openbsd"; - pub const DLL_PREFIX: &'static str = "lib"; - pub const DLL_SUFFIX: &'static str = ".so"; - pub const DLL_EXTENSION: &'static str = "so"; - pub const EXE_SUFFIX: &'static str = ""; - pub const EXE_EXTENSION: &'static str = ""; + pub const FAMILY: &str = "unix"; + pub const OS: &str = "openbsd"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".so"; + pub const DLL_EXTENSION: &str = "so"; + pub const EXE_SUFFIX: &str = ""; + pub const EXE_EXTENSION: &str = ""; } #[cfg(target_os = "android")] pub mod os { - pub const FAMILY: &'static str = "unix"; - pub const OS: &'static str = "android"; - pub const DLL_PREFIX: &'static str = "lib"; - pub const DLL_SUFFIX: &'static str = ".so"; - pub const DLL_EXTENSION: &'static str = "so"; - pub const EXE_SUFFIX: &'static str = ""; - pub const EXE_EXTENSION: &'static str = ""; + pub const FAMILY: &str = "unix"; + pub const OS: &str = "android"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".so"; + pub const DLL_EXTENSION: &str = "so"; + pub const EXE_SUFFIX: &str = ""; + pub const EXE_EXTENSION: &str = ""; } #[cfg(target_os = "solaris")] pub mod os { - pub const FAMILY: &'static str = "unix"; - pub const OS: &'static str = "solaris"; - pub const DLL_PREFIX: &'static str = "lib"; - pub const DLL_SUFFIX: &'static str = ".so"; - pub const DLL_EXTENSION: &'static str = "so"; - pub const EXE_SUFFIX: &'static str = ""; - pub const EXE_EXTENSION: &'static str = ""; + pub const FAMILY: &str = "unix"; + pub const OS: &str = "solaris"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".so"; + pub const DLL_EXTENSION: &str = "so"; + pub const EXE_SUFFIX: &str = ""; + pub const EXE_EXTENSION: &str = ""; } #[cfg(target_os = "haiku")] pub mod os { - pub const FAMILY: &'static str = "unix"; - pub const OS: &'static str = "haiku"; - pub const DLL_PREFIX: &'static str = "lib"; - pub const DLL_SUFFIX: &'static str = ".so"; - pub const DLL_EXTENSION: &'static str = "so"; - pub const EXE_SUFFIX: &'static str = ""; - pub const EXE_EXTENSION: &'static str = ""; + pub const FAMILY: &str = "unix"; + pub const OS: &str = "haiku"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".so"; + pub const DLL_EXTENSION: &str = "so"; + pub const EXE_SUFFIX: &str = ""; + pub const EXE_EXTENSION: &str = ""; } #[cfg(all(target_os = "emscripten", target_arch = "asmjs"))] pub mod os { - pub const FAMILY: &'static str = "unix"; - pub const OS: &'static str = "emscripten"; - pub const DLL_PREFIX: &'static str = "lib"; - pub const DLL_SUFFIX: &'static str = ".so"; - pub const DLL_EXTENSION: &'static str = "so"; - pub const EXE_SUFFIX: &'static str = ".js"; - pub const EXE_EXTENSION: &'static str = "js"; + pub const FAMILY: &str = "unix"; + pub const OS: &str = "emscripten"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".so"; + pub const DLL_EXTENSION: &str = "so"; + pub const EXE_SUFFIX: &str = ".js"; + pub const EXE_EXTENSION: &str = "js"; } #[cfg(all(target_os = "emscripten", target_arch = "wasm32"))] pub mod os { - pub const FAMILY: &'static str = "unix"; - pub const OS: &'static str = "emscripten"; - pub const DLL_PREFIX: &'static str = "lib"; - pub const DLL_SUFFIX: &'static str = ".so"; - pub const DLL_EXTENSION: &'static str = "so"; - pub const EXE_SUFFIX: &'static str = ".js"; - pub const EXE_EXTENSION: &'static str = "js"; + pub const FAMILY: &str = "unix"; + pub const OS: &str = "emscripten"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".so"; + pub const DLL_EXTENSION: &str = "so"; + pub const EXE_SUFFIX: &str = ".js"; + pub const EXE_EXTENSION: &str = "js"; } #[cfg(target_os = "fuchsia")] pub mod os { - pub const FAMILY: &'static str = "unix"; - pub const OS: &'static str = "fuchsia"; - pub const DLL_PREFIX: &'static str = "lib"; - pub const DLL_SUFFIX: &'static str = ".so"; - pub const DLL_EXTENSION: &'static str = "so"; - pub const EXE_SUFFIX: &'static str = ""; - pub const EXE_EXTENSION: &'static str = ""; + pub const FAMILY: &str = "unix"; + pub const OS: &str = "fuchsia"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".so"; + pub const DLL_EXTENSION: &str = "so"; + pub const EXE_SUFFIX: &str = ""; + pub const EXE_EXTENSION: &str = ""; } #[cfg(target_os = "l4re")] pub mod os { - pub const FAMILY: &'static str = "unix"; - pub const OS: &'static str = "l4re"; - pub const DLL_PREFIX: &'static str = "lib"; - pub const DLL_SUFFIX: &'static str = ".so"; - pub const DLL_EXTENSION: &'static str = "so"; - pub const EXE_SUFFIX: &'static str = ""; - pub const EXE_EXTENSION: &'static str = ""; + pub const FAMILY: &str = "unix"; + pub const OS: &str = "l4re"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".so"; + pub const DLL_EXTENSION: &str = "so"; + pub const EXE_SUFFIX: &str = ""; + pub const EXE_EXTENSION: &str = ""; } #[cfg(target_os = "hermit")] pub mod os { - pub const FAMILY: &'static str = "unix"; - pub const OS: &'static str = "hermit"; - pub const DLL_PREFIX: &'static str = "lib"; - pub const DLL_SUFFIX: &'static str = ".so"; - pub const DLL_EXTENSION: &'static str = "so"; - pub const EXE_SUFFIX: &'static str = ""; - pub const EXE_EXTENSION: &'static str = ""; + pub const FAMILY: &str = "unix"; + pub const OS: &str = "hermit"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".so"; + pub const DLL_EXTENSION: &str = "so"; + pub const EXE_SUFFIX: &str = ""; + pub const EXE_EXTENSION: &str = ""; } diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs index 7e65bbdef2a..af2f1998415 100644 --- a/src/libstd/sys/unix/ext/fs.rs +++ b/src/libstd/sys/unix/ext/fs.rs @@ -348,7 +348,7 @@ pub trait OpenOptionsExt { /// # Examples /// /// ```no_run - /// # #![feature(libc)] + /// # #![feature(rustc_private)] /// extern crate libc; /// use std::fs::OpenOptions; /// use std::os::unix::fs::OpenOptionsExt; diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index 737437c76b7..bcf0d440eba 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -132,7 +132,7 @@ impl SocketAddr { if len == 0 { // When there is a datagram from unnamed unix socket // linux returns zero bytes of address - len = sun_path_offset() as libc::socklen_t; // i.e. zero-length address + len = sun_path_offset() as libc::socklen_t; // i.e., zero-length address } else if addr.sun_family != libc::AF_UNIX as libc::sa_family_t { return Err(io::Error::new(io::ErrorKind::InvalidInput, "file descriptor did not correspond to a Unix socket")); diff --git a/src/libstd/sys/unix/l4re.rs b/src/libstd/sys/unix/l4re.rs index 21218489679..bbb0fd45ba3 100644 --- a/src/libstd/sys/unix/l4re.rs +++ b/src/libstd/sys/unix/l4re.rs @@ -21,7 +21,7 @@ pub mod net { use sys_common::{AsInner, FromInner, IntoInner}; use sys::fd::FileDesc; use time::Duration; - + use convert::TryFrom; pub extern crate libc as netc; @@ -118,7 +118,7 @@ pub mod net { } impl TcpStream { - pub fn connect(_: &SocketAddr) -> io::Result { + pub fn connect(_: io::Result<&SocketAddr>) -> io::Result { unimpl!(); } @@ -216,7 +216,7 @@ pub mod net { } impl TcpListener { - pub fn bind(_: &SocketAddr) -> io::Result { + pub fn bind(_: io::Result<&SocketAddr>) -> io::Result { unimpl!(); } @@ -278,7 +278,7 @@ pub mod net { } impl UdpSocket { - pub fn bind(_: &SocketAddr) -> io::Result { + pub fn bind(_: io::Result<&SocketAddr>) -> io::Result { unimpl!(); } @@ -402,7 +402,7 @@ pub mod net { unimpl!(); } - pub fn connect(&self, _: &SocketAddr) -> io::Result<()> { + pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> { unimpl!(); } } @@ -431,11 +431,30 @@ pub mod net { } } + impl LookupHost { + pub fn port(&self) -> u16 { + unimpl!(); + } + } + unsafe impl Sync for LookupHost {} unsafe impl Send for LookupHost {} - pub fn lookup_host(_: &str) -> io::Result { - unimpl!(); + + impl<'a> TryFrom<&'a str> for LookupHost { + type Error = io::Error; + + fn try_from(_v: &'a str) -> io::Result { + unimpl!(); + } + } + + impl<'a> TryFrom<(&'a str, u16)> for LookupHost { + type Error = io::Error; + + fn try_from(_v: (&'a str, u16)) -> io::Result { + unimpl!(); + } } } diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs index 2d10541752c..f30817e69ab 100644 --- a/src/libstd/sys/unix/net.rs +++ b/src/libstd/sys/unix/net.rs @@ -26,7 +26,7 @@ pub extern crate libc as netc; pub type wrlen_t = size_t; // See below for the usage of SOCK_CLOEXEC, but this constant is only defined on -// Linux currently (e.g. support doesn't exist on other platforms). In order to +// Linux currently (e.g., support doesn't exist on other platforms). In order to // get name resolution to work and things to compile we just define a dummy // SOCK_CLOEXEC here for other platforms. Note that the dummy constant isn't // actually ever used (the blocks below are wrapped in `if cfg!` as well. @@ -203,18 +203,21 @@ impl Socket { // Linux. This was added in 2.6.28, however, and because we support // 2.6.18 we must detect this support dynamically. if cfg!(target_os = "linux") { - weak! { - fn accept4(c_int, *mut sockaddr, *mut socklen_t, c_int) -> c_int + syscall! { + fn accept4( + fd: c_int, + addr: *mut sockaddr, + addr_len: *mut socklen_t, + flags: c_int + ) -> c_int } - if let Some(accept) = accept4.get() { - let res = cvt_r(|| unsafe { - accept(self.0.raw(), storage, len, SOCK_CLOEXEC) - }); - match res { - Ok(fd) => return Ok(Socket(FileDesc::new(fd))), - Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => {} - Err(e) => return Err(e), - } + let res = cvt_r(|| unsafe { + accept4(self.0.raw(), storage, len, SOCK_CLOEXEC) + }); + match res { + Ok(fd) => return Ok(Socket(FileDesc::new(fd))), + Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => {} + Err(e) => return Err(e), } } diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index b387a8d59a5..6e8ee445994 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -67,7 +67,8 @@ pub fn errno() -> i32 { } /// Sets the platform-specific value of errno -#[cfg(any(target_os = "solaris", target_os = "fuchsia"))] // only needed for readdir so far +#[cfg(all(not(target_os = "linux"), + not(target_os = "dragonfly")))] // needed for readdir and syscall! pub fn set_errno(e: i32) { unsafe { *errno_location() = e as c_int @@ -84,6 +85,18 @@ pub fn errno() -> i32 { unsafe { errno as i32 } } +#[cfg(target_os = "dragonfly")] +pub fn set_errno(e: i32) { + extern { + #[thread_local] + static mut errno: c_int; + } + + unsafe { + errno = e; + } +} + /// Gets a detailed string description for the given error number. pub fn error_string(errno: i32) -> String { extern { @@ -283,11 +296,14 @@ pub fn current_exe() -> io::Result { #[cfg(any(target_os = "linux", target_os = "android", target_os = "emscripten"))] pub fn current_exe() -> io::Result { - let selfexe = PathBuf::from("/proc/self/exe"); - if selfexe.exists() { - ::fs::read_link(selfexe) - } else { - Err(io::Error::new(io::ErrorKind::Other, "no /proc/self/exe available. Is /proc mounted?")) + match ::fs::read_link("/proc/self/exe") { + Err(ref e) if e.kind() == io::ErrorKind::NotFound => { + Err(io::Error::new( + io::ErrorKind::Other, + "no /proc/self/exe available. Is /proc mounted?" + )) + }, + other => other, } } diff --git a/src/libstd/sys/unix/path.rs b/src/libstd/sys/unix/path.rs index bf9af7a4353..834b4b448dc 100644 --- a/src/libstd/sys/unix/path.rs +++ b/src/libstd/sys/unix/path.rs @@ -25,5 +25,5 @@ pub fn parse_prefix(_: &OsStr) -> Option { None } -pub const MAIN_SEP_STR: &'static str = "/"; +pub const MAIN_SEP_STR: &str = "/"; pub const MAIN_SEP: char = '/'; diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs index 0a5dccdddda..24b2959a3fa 100644 --- a/src/libstd/sys/unix/pipe.rs +++ b/src/libstd/sys/unix/pipe.rs @@ -22,7 +22,7 @@ use sys::{cvt, cvt_r}; pub struct AnonPipe(FileDesc); pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { - weak! { fn pipe2(*mut c_int, c_int) -> c_int } + syscall! { fn pipe2(fds: *mut c_int, flags: c_int) -> c_int } static INVALID: AtomicBool = ATOMIC_BOOL_INIT; let mut fds = [0; 2]; @@ -39,22 +39,20 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { !INVALID.load(Ordering::SeqCst) { - if let Some(pipe) = pipe2.get() { - // Note that despite calling a glibc function here we may still - // get ENOSYS. Glibc has `pipe2` since 2.9 and doesn't try to - // emulate on older kernels, so if you happen to be running on - // an older kernel you may see `pipe2` as a symbol but still not - // see the syscall. - match cvt(unsafe { pipe(fds.as_mut_ptr(), libc::O_CLOEXEC) }) { - Ok(_) => { - return Ok((AnonPipe(FileDesc::new(fds[0])), - AnonPipe(FileDesc::new(fds[1])))); - } - Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => { - INVALID.store(true, Ordering::SeqCst); - } - Err(e) => return Err(e), + // Note that despite calling a glibc function here we may still + // get ENOSYS. Glibc has `pipe2` since 2.9 and doesn't try to + // emulate on older kernels, so if you happen to be running on + // an older kernel you may see `pipe2` as a symbol but still not + // see the syscall. + match cvt(unsafe { pipe2(fds.as_mut_ptr(), libc::O_CLOEXEC) }) { + Ok(_) => { + return Ok((AnonPipe(FileDesc::new(fds[0])), + AnonPipe(FileDesc::new(fds[1])))); } + Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => { + INVALID.store(true, Ordering::SeqCst); + } + Err(e) => return Err(e), } } cvt(unsafe { libc::pipe(fds.as_mut_ptr()) })?; diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs index bfbf12f34ee..3248f424460 100644 --- a/src/libstd/sys/unix/process/process_unix.rs +++ b/src/libstd/sys/unix/process/process_unix.rs @@ -22,7 +22,7 @@ use sys; impl Command { pub fn spawn(&mut self, default: Stdio, needs_stdin: bool) -> io::Result<(Process, StdioPipes)> { - const CLOEXEC_MSG_FOOTER: &'static [u8] = b"NOEX"; + const CLOEXEC_MSG_FOOTER: &[u8] = b"NOEX"; let envp = self.capture_env(); diff --git a/src/libstd/sys/unix/process/zircon.rs b/src/libstd/sys/unix/process/zircon.rs index a06c73ee263..0335c1e914c 100644 --- a/src/libstd/sys/unix/process/zircon.rs +++ b/src/libstd/sys/unix/process/zircon.rs @@ -215,7 +215,7 @@ pub const FDIO_SPAWN_ACTION_TRANSFER_FD: u32 = 0x0002; // and has a closed remote end will return ERR_REMOTE_CLOSED. #[allow(unused)] pub const ERR_SHOULD_WAIT: zx_status_t = -22; -// ERR_CANCELED: The in-progress operation (e.g. a wait) has been +// ERR_CANCELED: The in-progress operation (e.g., a wait) has been // // canceled. #[allow(unused)] pub const ERR_CANCELED: zx_status_t = -23; diff --git a/src/libstd/sys/unix/stdio.rs b/src/libstd/sys/unix/stdio.rs index 87ba2aef4f1..63e341abb2c 100644 --- a/src/libstd/sys/unix/stdio.rs +++ b/src/libstd/sys/unix/stdio.rs @@ -76,6 +76,6 @@ pub fn is_ebadf(err: &io::Error) -> bool { pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE; -pub fn stderr_prints_nothing() -> bool { - false +pub fn panic_output() -> Option { + Stderr::new().ok() } diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index f3a45d24657..e0d2c620498 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -49,7 +49,8 @@ unsafe fn pthread_attr_setstacksize(_attr: *mut libc::pthread_attr_t, } impl Thread { - pub unsafe fn new<'a>(stack: usize, p: Box) + // unsafe: see thread::Builder::spawn_unchecked for safety requirements + pub unsafe fn new(stack: usize, p: Box) -> io::Result { let p = box p; let mut native: libc::pthread_t = mem::zeroed(); @@ -210,7 +211,6 @@ pub mod guard { pub type Guard = Range; pub unsafe fn current() -> Option { None } pub unsafe fn init() -> Option { None } - pub unsafe fn deinit() {} } @@ -354,26 +354,6 @@ pub mod guard { } } - pub unsafe fn deinit() { - if !cfg!(target_os = "linux") { - if let Some(stackaddr) = get_stack_start_aligned() { - // Remove the protection on the guard page. - // FIXME: we cannot unmap the page, because when we mmap() - // above it may be already mapped by the OS, which we can't - // detect from mmap()'s return value. If we unmap this page, - // it will lead to failure growing stack size on platforms like - // macOS. Instead, just restore the page to a writable state. - // This ain't Linux, so we probably don't need to care about - // execstack. - let result = mprotect(stackaddr, PAGE_SIZE, PROT_READ | PROT_WRITE); - - if result != 0 { - panic!("unable to reset the guard page"); - } - } - } - } - #[cfg(any(target_os = "macos", target_os = "bitrig", target_os = "openbsd", diff --git a/src/libstd/sys/unix/time.rs b/src/libstd/sys/unix/time.rs index 1f9539c36e0..8f8aaa88b22 100644 --- a/src/libstd/sys/unix/time.rs +++ b/src/libstd/sys/unix/time.rs @@ -42,10 +42,6 @@ impl Timespec { } } - fn add_duration(&self, other: &Duration) -> Timespec { - self.checked_add_duration(other).expect("overflow when adding duration to time") - } - fn checked_add_duration(&self, other: &Duration) -> Option { let mut secs = other .as_secs() @@ -68,27 +64,25 @@ impl Timespec { }) } - fn sub_duration(&self, other: &Duration) -> Timespec { + fn checked_sub_duration(&self, other: &Duration) -> Option { let mut secs = other .as_secs() .try_into() // <- target type would be `libc::time_t` .ok() - .and_then(|secs| self.t.tv_sec.checked_sub(secs)) - .expect("overflow when subtracting duration from time"); + .and_then(|secs| self.t.tv_sec.checked_sub(secs))?; // Similar to above, nanos can't overflow. let mut nsec = self.t.tv_nsec as i32 - other.subsec_nanos() as i32; if nsec < 0 { nsec += NSEC_PER_SEC as i32; - secs = secs.checked_sub(1).expect("overflow when subtracting \ - duration from time"); + secs = secs.checked_sub(1)?; } - Timespec { + Some(Timespec { t: libc::timespec { tv_sec: secs, tv_nsec: nsec as _, }, - } + }) } } @@ -165,18 +159,16 @@ mod inner { Duration::new(nanos / NSEC_PER_SEC, (nanos % NSEC_PER_SEC) as u32) } - pub fn add_duration(&self, other: &Duration) -> Instant { - Instant { - t: self.t.checked_add(dur2intervals(other)) - .expect("overflow when adding duration to instant"), - } + pub fn checked_add_duration(&self, other: &Duration) -> Option { + Some(Instant { + t: self.t.checked_add(checked_dur2intervals(other)?)?, + }) } - pub fn sub_duration(&self, other: &Duration) -> Instant { - Instant { - t: self.t.checked_sub(dur2intervals(other)) - .expect("overflow when subtracting duration from instant"), - } + pub fn checked_sub_duration(&self, other: &Duration) -> Option { + Some(Instant { + t: self.t.checked_sub(checked_dur2intervals(other)?)?, + }) } } @@ -199,16 +191,12 @@ mod inner { self.t.sub_timespec(&other.t) } - pub fn add_duration(&self, other: &Duration) -> SystemTime { - SystemTime { t: self.t.add_duration(other) } - } - pub fn checked_add_duration(&self, other: &Duration) -> Option { - self.t.checked_add_duration(other).map(|t| SystemTime { t }) + Some(SystemTime { t: self.t.checked_add_duration(other)? }) } - pub fn sub_duration(&self, other: &Duration) -> SystemTime { - SystemTime { t: self.t.sub_duration(other) } + pub fn checked_sub_duration(&self, other: &Duration) -> Option { + Some(SystemTime { t: self.t.checked_sub_duration(other)? }) } } @@ -236,12 +224,12 @@ mod inner { } } - fn dur2intervals(dur: &Duration) -> u64 { + fn checked_dur2intervals(dur: &Duration) -> Option { + let nanos = dur.as_secs() + .checked_mul(NSEC_PER_SEC)? + .checked_add(dur.subsec_nanos() as u64)?; let info = info(); - let nanos = dur.as_secs().checked_mul(NSEC_PER_SEC).and_then(|nanos| { - nanos.checked_add(dur.subsec_nanos() as u64) - }).expect("overflow converting duration to nanoseconds"); - mul_div_u64(nanos, info.denom as u64, info.numer as u64) + Some(mul_div_u64(nanos, info.denom as u64, info.numer as u64)) } fn info() -> &'static libc::mach_timebase_info { @@ -299,12 +287,12 @@ mod inner { }) } - pub fn add_duration(&self, other: &Duration) -> Instant { - Instant { t: self.t.add_duration(other) } + pub fn checked_add_duration(&self, other: &Duration) -> Option { + Some(Instant { t: self.t.checked_add_duration(other)? }) } - pub fn sub_duration(&self, other: &Duration) -> Instant { - Instant { t: self.t.sub_duration(other) } + pub fn checked_sub_duration(&self, other: &Duration) -> Option { + Some(Instant { t: self.t.checked_sub_duration(other)? }) } } @@ -327,16 +315,12 @@ mod inner { self.t.sub_timespec(&other.t) } - pub fn add_duration(&self, other: &Duration) -> SystemTime { - SystemTime { t: self.t.add_duration(other) } - } - pub fn checked_add_duration(&self, other: &Duration) -> Option { - self.t.checked_add_duration(other).map(|t| SystemTime { t }) + Some(SystemTime { t: self.t.checked_add_duration(other)? }) } - pub fn sub_duration(&self, other: &Duration) -> SystemTime { - SystemTime { t: self.t.sub_duration(other) } + pub fn checked_sub_duration(&self, other: &Duration) -> Option { + Some(SystemTime { t: self.t.checked_sub_duration(other)? }) } } diff --git a/src/libstd/sys/unix/weak.rs b/src/libstd/sys/unix/weak.rs index 18944be58ee..7d293f1c47a 100644 --- a/src/libstd/sys/unix/weak.rs +++ b/src/libstd/sys/unix/weak.rs @@ -77,3 +77,38 @@ unsafe fn fetch(name: &str) -> usize { }; libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr()) as usize } + +#[cfg(not(target_os = "linux"))] +macro_rules! syscall { + (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => ( + unsafe fn $name($($arg_name: $t),*) -> $ret { + use libc; + use super::os; + + weak! { fn $name($($t),*) -> $ret } + + if let Some(fun) = $name.get() { + fun($($arg_name),*) + } else { + os::set_errno(libc::ENOSYS); + -1 + } + } + ) +} + +#[cfg(target_os = "linux")] +macro_rules! syscall { + (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => ( + unsafe fn $name($($arg_name:$t),*) -> $ret { + // This looks like a hack, but concat_idents only accepts idents + // (not paths). + use libc::*; + + syscall( + concat_idents!(SYS_, $name), + $($arg_name as c_long),* + ) as $ret + } + ) +} diff --git a/src/libstd/sys/wasm/cmath.rs b/src/libstd/sys/wasm/cmath.rs index 64fc14d42d9..d4f8d66ee3e 100644 --- a/src/libstd/sys/wasm/cmath.rs +++ b/src/libstd/sys/wasm/cmath.rs @@ -8,85 +8,32 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[inline] -pub unsafe fn cbrtf(n: f32) -> f32 { - f64::cbrt(n as f64) as f32 -} - -#[inline] -pub unsafe fn expm1f(n: f32) -> f32 { - f64::exp_m1(n as f64) as f32 -} - -#[inline] -#[allow(deprecated)] -pub unsafe fn fdimf(a: f32, b: f32) -> f32 { - f64::abs_sub(a as f64, b as f64) as f32 -} - -#[inline] -pub unsafe fn log1pf(n: f32) -> f32 { - f64::ln_1p(n as f64) as f32 -} - -#[inline] -pub unsafe fn hypotf(x: f32, y: f32) -> f32 { - f64::hypot(x as f64, y as f64) as f32 -} - -#[inline] -pub unsafe fn acosf(n: f32) -> f32 { - f64::acos(n as f64) as f32 -} - -#[inline] -pub unsafe fn asinf(n: f32) -> f32 { - f64::asin(n as f64) as f32 -} - -#[inline] -pub unsafe fn atan2f(n: f32, b: f32) -> f32 { - f64::atan2(n as f64, b as f64) as f32 -} - -#[inline] -pub unsafe fn atanf(n: f32) -> f32 { - f64::atan(n as f64) as f32 -} - -#[inline] -pub unsafe fn coshf(n: f32) -> f32 { - f64::cosh(n as f64) as f32 -} - -#[inline] -pub unsafe fn sinhf(n: f32) -> f32 { - f64::sinh(n as f64) as f32 -} - -#[inline] -pub unsafe fn tanf(n: f32) -> f32 { - f64::tan(n as f64) as f32 -} - -#[inline] -pub unsafe fn tanhf(n: f32) -> f32 { - f64::tanh(n as f64) as f32 -} - // These symbols are all defined in `compiler-builtins` extern { pub fn acos(n: f64) -> f64; + pub fn acosf(n: f32) -> f32; pub fn asin(n: f64) -> f64; + pub fn asinf(n: f32) -> f32; pub fn atan(n: f64) -> f64; pub fn atan2(a: f64, b: f64) -> f64; + pub fn atan2f(a: f32, b: f32) -> f32; + pub fn atanf(n: f32) -> f32; pub fn cbrt(n: f64) -> f64; + pub fn cbrtf(n: f32) -> f32; pub fn cosh(n: f64) -> f64; + pub fn coshf(n: f32) -> f32; pub fn expm1(n: f64) -> f64; + pub fn expm1f(n: f32) -> f32; pub fn fdim(a: f64, b: f64) -> f64; - pub fn log1p(n: f64) -> f64; - pub fn sinh(n: f64) -> f64; - pub fn tan(n: f64) -> f64; - pub fn tanh(n: f64) -> f64; + pub fn fdimf(a: f32, b: f32) -> f32; pub fn hypot(x: f64, y: f64) -> f64; + pub fn hypotf(x: f32, y: f32) -> f32; + pub fn log1p(n: f64) -> f64; + pub fn log1pf(n: f32) -> f32; + pub fn sinh(n: f64) -> f64; + pub fn sinhf(n: f32) -> f32; + pub fn tan(n: f64) -> f64; + pub fn tanf(n: f32) -> f32; + pub fn tanh(n: f64) -> f64; + pub fn tanhf(n: f32) -> f32; } diff --git a/src/libstd/sys/wasm/env.rs b/src/libstd/sys/wasm/env.rs index 1422042bd02..09235a944ee 100644 --- a/src/libstd/sys/wasm/env.rs +++ b/src/libstd/sys/wasm/env.rs @@ -9,11 +9,11 @@ // except according to those terms. pub mod os { - pub const FAMILY: &'static str = ""; - pub const OS: &'static str = ""; - pub const DLL_PREFIX: &'static str = ""; - pub const DLL_SUFFIX: &'static str = ".wasm"; - pub const DLL_EXTENSION: &'static str = "wasm"; - pub const EXE_SUFFIX: &'static str = ".wasm"; - pub const EXE_EXTENSION: &'static str = "wasm"; + pub const FAMILY: &str = ""; + pub const OS: &str = ""; + pub const DLL_PREFIX: &str = ""; + pub const DLL_SUFFIX: &str = ".wasm"; + pub const DLL_EXTENSION: &str = "wasm"; + pub const EXE_SUFFIX: &str = ".wasm"; + pub const EXE_EXTENSION: &str = "wasm"; } diff --git a/src/libstd/sys/wasm/net.rs b/src/libstd/sys/wasm/net.rs index 03a5b2d779e..e1c33b09cb4 100644 --- a/src/libstd/sys/wasm/net.rs +++ b/src/libstd/sys/wasm/net.rs @@ -13,11 +13,12 @@ use io; use net::{SocketAddr, Shutdown, Ipv4Addr, Ipv6Addr}; use time::Duration; use sys::{unsupported, Void}; +use convert::TryFrom; pub struct TcpStream(Void); impl TcpStream { - pub fn connect(_: &SocketAddr) -> io::Result { + pub fn connect(_: io::Result<&SocketAddr>) -> io::Result { unsupported() } @@ -103,7 +104,7 @@ impl fmt::Debug for TcpStream { pub struct TcpListener(Void); impl TcpListener { - pub fn bind(_: &SocketAddr) -> io::Result { + pub fn bind(_: io::Result<&SocketAddr>) -> io::Result { unsupported() } @@ -153,7 +154,7 @@ impl fmt::Debug for TcpListener { pub struct UdpSocket(Void); impl UdpSocket { - pub fn bind(_: &SocketAddr) -> io::Result { + pub fn bind(_: io::Result<&SocketAddr>) -> io::Result { unsupported() } @@ -273,7 +274,7 @@ impl UdpSocket { match self.0 {} } - pub fn connect(&self, _: &SocketAddr) -> io::Result<()> { + pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> { match self.0 {} } } @@ -286,6 +287,12 @@ impl fmt::Debug for UdpSocket { pub struct LookupHost(Void); +impl LookupHost { + pub fn port(&self) -> u16 { + match self.0 {} + } +} + impl Iterator for LookupHost { type Item = SocketAddr; fn next(&mut self) -> Option { @@ -293,8 +300,20 @@ impl Iterator for LookupHost { } } -pub fn lookup_host(_: &str) -> io::Result { - unsupported() +impl<'a> TryFrom<&'a str> for LookupHost { + type Error = io::Error; + + fn try_from(_v: &'a str) -> io::Result { + unsupported() + } +} + +impl<'a> TryFrom<(&'a str, u16)> for LookupHost { + type Error = io::Error; + + fn try_from(_v: (&'a str, u16)) -> io::Result { + unsupported() + } } #[allow(nonstandard_style)] diff --git a/src/libstd/sys/wasm/path.rs b/src/libstd/sys/wasm/path.rs index 395b8c1e40e..fcc9d617a87 100644 --- a/src/libstd/sys/wasm/path.rs +++ b/src/libstd/sys/wasm/path.rs @@ -25,5 +25,5 @@ pub fn parse_prefix(_: &OsStr) -> Option { None } -pub const MAIN_SEP_STR: &'static str = "/"; +pub const MAIN_SEP_STR: &str = "/"; pub const MAIN_SEP: char = '/'; diff --git a/src/libstd/sys/wasm/stdio.rs b/src/libstd/sys/wasm/stdio.rs index 023f29576a2..e51aba75333 100644 --- a/src/libstd/sys/wasm/stdio.rs +++ b/src/libstd/sys/wasm/stdio.rs @@ -70,6 +70,10 @@ pub fn is_ebadf(_err: &io::Error) -> bool { true } -pub fn stderr_prints_nothing() -> bool { - !cfg!(feature = "wasm_syscall") +pub fn panic_output() -> Option { + if cfg!(feature = "wasm_syscall") { + Stderr::new().ok() + } else { + None + } } diff --git a/src/libstd/sys/wasm/thread.rs b/src/libstd/sys/wasm/thread.rs index 4ad89c42b92..f9abb0b825a 100644 --- a/src/libstd/sys/wasm/thread.rs +++ b/src/libstd/sys/wasm/thread.rs @@ -19,7 +19,8 @@ pub struct Thread(Void); pub const DEFAULT_MIN_STACK_SIZE: usize = 4096; impl Thread { - pub unsafe fn new<'a>(_stack: usize, _p: Box) + // unsafe: see thread::Builder::spawn_unchecked for safety requirements + pub unsafe fn new(_stack: usize, _p: Box) -> io::Result { unsupported() @@ -67,7 +68,6 @@ pub mod guard { pub type Guard = !; pub unsafe fn current() -> Option { None } pub unsafe fn init() -> Option { None } - pub unsafe fn deinit() {} } cfg_if! { diff --git a/src/libstd/sys/wasm/time.rs b/src/libstd/sys/wasm/time.rs index 991e8176edf..cc56773e0ea 100644 --- a/src/libstd/sys/wasm/time.rs +++ b/src/libstd/sys/wasm/time.rs @@ -28,12 +28,12 @@ impl Instant { self.0 - other.0 } - pub fn add_duration(&self, other: &Duration) -> Instant { - Instant(self.0 + *other) + pub fn checked_add_duration(&self, other: &Duration) -> Option { + Some(Instant(self.0.checked_add(*other)?)) } - pub fn sub_duration(&self, other: &Duration) -> Instant { - Instant(self.0 - *other) + pub fn checked_sub_duration(&self, other: &Duration) -> Option { + Some(Instant(self.0.checked_sub(*other)?)) } } @@ -47,15 +47,11 @@ impl SystemTime { self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0) } - pub fn add_duration(&self, other: &Duration) -> SystemTime { - SystemTime(self.0 + *other) - } - pub fn checked_add_duration(&self, other: &Duration) -> Option { - self.0.checked_add(*other).map(|d| SystemTime(d)) + Some(SystemTime(self.0.checked_add(*other)?)) } - pub fn sub_duration(&self, other: &Duration) -> SystemTime { - SystemTime(self.0 - *other) + pub fn checked_sub_duration(&self, other: &Duration) -> Option { + Some(SystemTime(self.0.checked_sub(*other)?)) } } diff --git a/src/libstd/sys/windows/args.rs b/src/libstd/sys/windows/args.rs index 4784633edc1..9e9198e05ee 100644 --- a/src/libstd/sys/windows/args.rs +++ b/src/libstd/sys/windows/args.rs @@ -11,12 +11,14 @@ #![allow(dead_code)] // runtime init functions not used during testing use os::windows::prelude::*; +use sys::windows::os::current_exe; use sys::c; -use slice; -use ops::Range; use ffi::OsString; -use libc::{c_int, c_void}; use fmt; +use vec; +use core::iter; +use slice; +use path::PathBuf; pub unsafe fn init(_argc: isize, _argv: *const *const u8) { } @@ -24,20 +26,146 @@ pub unsafe fn cleanup() { } pub fn args() -> Args { unsafe { - let mut nArgs: c_int = 0; - let lpCmdLine = c::GetCommandLineW(); - let szArgList = c::CommandLineToArgvW(lpCmdLine, &mut nArgs); + let lp_cmd_line = c::GetCommandLineW(); + let parsed_args_list = parse_lp_cmd_line( + lp_cmd_line as *const u16, + || current_exe().map(PathBuf::into_os_string).unwrap_or_else(|_| OsString::new())); - // szArcList can be NULL if CommandLinToArgvW failed, - // but in that case nArgs is 0 so we won't actually - // try to read a null pointer - Args { cur: szArgList, range: 0..(nArgs as isize) } + Args { parsed_args_list: parsed_args_list.into_iter() } } } +/// Implements the Windows command-line argument parsing algorithm. +/// +/// Microsoft's documentation for the Windows CLI argument format can be found at +/// . +/// +/// Windows includes a function to do this in shell32.dll, +/// but linking with that DLL causes the process to be registered as a GUI application. +/// GUI applications add a bunch of overhead, even if no windows are drawn. See +/// . +/// +/// This function was tested for equivalence to the shell32.dll implementation in +/// Windows 10 Pro v1803, using an exhaustive test suite available at +/// or +/// . +unsafe fn parse_lp_cmd_line OsString>(lp_cmd_line: *const u16, exe_name: F) + -> Vec { + const BACKSLASH: u16 = '\\' as u16; + const QUOTE: u16 = '"' as u16; + const TAB: u16 = '\t' as u16; + const SPACE: u16 = ' ' as u16; + let mut ret_val = Vec::new(); + if lp_cmd_line.is_null() || *lp_cmd_line == 0 { + ret_val.push(exe_name()); + return ret_val; + } + let mut cmd_line = { + let mut end = 0; + while *lp_cmd_line.offset(end) != 0 { + end += 1; + } + slice::from_raw_parts(lp_cmd_line, end as usize) + }; + // The executable name at the beginning is special. + cmd_line = match cmd_line[0] { + // The executable name ends at the next quote mark, + // no matter what. + QUOTE => { + let args = { + let mut cut = cmd_line[1..].splitn(2, |&c| c == QUOTE); + if let Some(exe) = cut.next() { + ret_val.push(OsString::from_wide(exe)); + } + cut.next() + }; + if let Some(args) = args { + args + } else { + return ret_val; + } + } + // Implement quirk: when they say whitespace here, + // they include the entire ASCII control plane: + // "However, if lpCmdLine starts with any amount of whitespace, CommandLineToArgvW + // will consider the first argument to be an empty string. Excess whitespace at the + // end of lpCmdLine is ignored." + 0...SPACE => { + ret_val.push(OsString::new()); + &cmd_line[1..] + }, + // The executable name ends at the next whitespace, + // no matter what. + _ => { + let args = { + let mut cut = cmd_line.splitn(2, |&c| c > 0 && c <= SPACE); + if let Some(exe) = cut.next() { + ret_val.push(OsString::from_wide(exe)); + } + cut.next() + }; + if let Some(args) = args { + args + } else { + return ret_val; + } + } + }; + let mut cur = Vec::new(); + let mut in_quotes = false; + let mut was_in_quotes = false; + let mut backslash_count: usize = 0; + for &c in cmd_line { + match c { + // backslash + BACKSLASH => { + backslash_count += 1; + was_in_quotes = false; + }, + QUOTE if backslash_count % 2 == 0 => { + cur.extend(iter::repeat(b'\\' as u16).take(backslash_count / 2)); + backslash_count = 0; + if was_in_quotes { + cur.push('"' as u16); + was_in_quotes = false; + } else { + was_in_quotes = in_quotes; + in_quotes = !in_quotes; + } + } + QUOTE if backslash_count % 2 != 0 => { + cur.extend(iter::repeat(b'\\' as u16).take(backslash_count / 2)); + backslash_count = 0; + was_in_quotes = false; + cur.push(b'"' as u16); + } + SPACE | TAB if !in_quotes => { + cur.extend(iter::repeat(b'\\' as u16).take(backslash_count)); + if !cur.is_empty() || was_in_quotes { + ret_val.push(OsString::from_wide(&cur[..])); + cur.truncate(0); + } + backslash_count = 0; + was_in_quotes = false; + } + _ => { + cur.extend(iter::repeat(b'\\' as u16).take(backslash_count)); + backslash_count = 0; + was_in_quotes = false; + cur.push(c); + } + } + } + cur.extend(iter::repeat(b'\\' as u16).take(backslash_count)); + // include empty quoted strings at the end of the arguments list + if !cur.is_empty() || was_in_quotes || in_quotes { + ret_val.push(OsString::from_wide(&cur[..])); + } + ret_val +} + pub struct Args { - range: Range, - cur: *mut *mut u16, + parsed_args_list: vec::IntoIter, } pub struct ArgsInnerDebug<'a> { @@ -46,19 +174,7 @@ pub struct ArgsInnerDebug<'a> { impl<'a> fmt::Debug for ArgsInnerDebug<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str("[")?; - let mut first = true; - for i in self.args.range.clone() { - if !first { - f.write_str(", ")?; - } - first = false; - - // Here we do allocation which could be avoided. - fmt::Debug::fmt(&unsafe { os_string_from_ptr(*self.args.cur.offset(i)) }, f)?; - } - f.write_str("]")?; - Ok(()) + self.args.parsed_args_list.as_slice().fmt(f) } } @@ -70,38 +186,82 @@ impl Args { } } -unsafe fn os_string_from_ptr(ptr: *mut u16) -> OsString { - let mut len = 0; - while *ptr.offset(len) != 0 { len += 1; } - - // Push it onto the list. - let ptr = ptr as *const u16; - let buf = slice::from_raw_parts(ptr, len as usize); - OsStringExt::from_wide(buf) -} - impl Iterator for Args { type Item = OsString; - fn next(&mut self) -> Option { - self.range.next().map(|i| unsafe { os_string_from_ptr(*self.cur.offset(i)) } ) - } - fn size_hint(&self) -> (usize, Option) { self.range.size_hint() } + fn next(&mut self) -> Option { self.parsed_args_list.next() } + fn size_hint(&self) -> (usize, Option) { self.parsed_args_list.size_hint() } } impl DoubleEndedIterator for Args { - fn next_back(&mut self) -> Option { - self.range.next_back().map(|i| unsafe { os_string_from_ptr(*self.cur.offset(i)) } ) - } + fn next_back(&mut self) -> Option { self.parsed_args_list.next_back() } } impl ExactSizeIterator for Args { - fn len(&self) -> usize { self.range.len() } + fn len(&self) -> usize { self.parsed_args_list.len() } } -impl Drop for Args { - fn drop(&mut self) { - // self.cur can be null if CommandLineToArgvW previously failed, - // but LocalFree ignores NULL pointers - unsafe { c::LocalFree(self.cur as *mut c_void); } +#[cfg(test)] +mod tests { + use sys::windows::args::*; + use ffi::OsString; + + fn chk(string: &str, parts: &[&str]) { + let mut wide: Vec = OsString::from(string).encode_wide().collect(); + wide.push(0); + let parsed = unsafe { + parse_lp_cmd_line(wide.as_ptr() as *const u16, || OsString::from("TEST.EXE")) + }; + let expected: Vec = parts.iter().map(|k| OsString::from(k)).collect(); + assert_eq!(parsed.as_slice(), expected.as_slice()); + } + + #[test] + fn empty() { + chk("", &["TEST.EXE"]); + chk("\0", &["TEST.EXE"]); + } + + #[test] + fn single_words() { + chk("EXE one_word", &["EXE", "one_word"]); + chk("EXE a", &["EXE", "a"]); + chk("EXE 😅", &["EXE", "😅"]); + chk("EXE 😅🤦", &["EXE", "😅🤦"]); + } + + #[test] + fn official_examples() { + chk(r#"EXE "abc" d e"#, &["EXE", "abc", "d", "e"]); + chk(r#"EXE a\\\b d"e f"g h"#, &["EXE", r#"a\\\b"#, "de fg", "h"]); + chk(r#"EXE a\\\"b c d"#, &["EXE", r#"a\"b"#, "c", "d"]); + chk(r#"EXE a\\\\"b c" d e"#, &["EXE", r#"a\\b c"#, "d", "e"]); + } + + #[test] + fn whitespace_behavior() { + chk(r#" test"#, &["", "test"]); + chk(r#" test"#, &["", "test"]); + chk(r#" test test2"#, &["", "test", "test2"]); + chk(r#" test test2"#, &["", "test", "test2"]); + chk(r#"test test2 "#, &["test", "test2"]); + chk(r#"test test2 "#, &["test", "test2"]); + chk(r#"test "#, &["test"]); + } + + #[test] + fn genius_quotes() { + chk(r#"EXE "" """#, &["EXE", "", ""]); + chk(r#"EXE "" """"#, &["EXE", "", "\""]); + chk( + r#"EXE "this is """all""" in the same argument""#, + &["EXE", "this is \"all\" in the same argument"] + ); + chk(r#"EXE "a"""#, &["EXE", "a\""]); + chk(r#"EXE "a"" a"#, &["EXE", "a\"", "a"]); + // quotes cannot be escaped in command names + chk(r#""EXE" check"#, &["EXE", "check"]); + chk(r#""EXE check""#, &["EXE check"]); + chk(r#""EXE """for""" check"#, &["EXE ", r#"for""#, "check"]); + chk(r#""EXE \"for\" check"#, &[r#"EXE \"#, r#"for""#, "check"]); } } diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index c84874a3e88..fa21f459a8a 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -1035,9 +1035,6 @@ extern "system" { pub fn SetLastError(dwErrCode: DWORD); pub fn GetCommandLineW() -> *mut LPCWSTR; - pub fn LocalFree(ptr: *mut c_void); - pub fn CommandLineToArgvW(lpCmdLine: *mut LPCWSTR, - pNumArgs: *mut c_int) -> *mut *mut u16; pub fn GetTempPathW(nBufferLength: DWORD, lpBuffer: LPCWSTR) -> DWORD; pub fn OpenProcessToken(ProcessHandle: HANDLE, diff --git a/src/libstd/sys/windows/env.rs b/src/libstd/sys/windows/env.rs index e6d74895774..4523df04f24 100644 --- a/src/libstd/sys/windows/env.rs +++ b/src/libstd/sys/windows/env.rs @@ -9,11 +9,11 @@ // except according to those terms. pub mod os { - pub const FAMILY: &'static str = "windows"; - pub const OS: &'static str = "windows"; - pub const DLL_PREFIX: &'static str = ""; - pub const DLL_SUFFIX: &'static str = ".dll"; - pub const DLL_EXTENSION: &'static str = "dll"; - pub const EXE_SUFFIX: &'static str = ".exe"; - pub const EXE_EXTENSION: &'static str = "exe"; + pub const FAMILY: &str = "windows"; + pub const OS: &str = "windows"; + pub const DLL_PREFIX: &str = ""; + pub const DLL_SUFFIX: &str = ".dll"; + pub const DLL_EXTENSION: &str = "dll"; + pub const EXE_SUFFIX: &str = ".exe"; + pub const EXE_EXTENSION: &str = "exe"; } diff --git a/src/libstd/sys/windows/ext/ffi.rs b/src/libstd/sys/windows/ext/ffi.rs index bae0d02786a..0a13aeabe84 100644 --- a/src/libstd/sys/windows/ext/ffi.rs +++ b/src/libstd/sys/windows/ext/ffi.rs @@ -117,7 +117,7 @@ impl OsStringExt for OsString { /// [`OsStr`]: ../../../../std/ffi/struct.OsStr.html #[stable(feature = "rust1", since = "1.0.0")] pub trait OsStrExt { - /// Re-encodes an `OsStr` as a wide character sequence, i.e. potentially + /// Re-encodes an `OsStr` as a wide character sequence, i.e., potentially /// ill-formed UTF-16. /// /// This is lossless: calling [`OsString::from_wide`] and then diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 082d4689c7b..949060b34dd 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -443,7 +443,7 @@ impl FromInner for File { impl fmt::Debug for File { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - // FIXME(#24570): add more info here (e.g. mode) + // FIXME(#24570): add more info here (e.g., mode) let mut b = f.debug_struct("File"); b.field("handle", &self.handle.raw()); if let Ok(path) = get_path(&self) { diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs index 29ea82c2053..84ef62e5fe9 100644 --- a/src/libstd/sys/windows/os.rs +++ b/src/libstd/sys/windows/os.rs @@ -48,8 +48,8 @@ pub fn error_string(mut errnum: i32) -> String { // `[MS-ERREF]`: https://msdn.microsoft.com/en-us/library/cc231198.aspx if (errnum & c::FACILITY_NT_BIT as i32) != 0 { // format according to https://support.microsoft.com/en-us/help/259693 - const NTDLL_DLL: &'static [u16] = &['N' as _, 'T' as _, 'D' as _, 'L' as _, 'L' as _, - '.' as _, 'D' as _, 'L' as _, 'L' as _, 0]; + const NTDLL_DLL: &[u16] = &['N' as _, 'T' as _, 'D' as _, 'L' as _, 'L' as _, + '.' as _, 'D' as _, 'L' as _, 'L' as _, 0]; module = c::GetModuleHandleW(NTDLL_DLL.as_ptr()); if module != ptr::null_mut() { @@ -67,7 +67,7 @@ pub fn error_string(mut errnum: i32) -> String { buf.len() as c::DWORD, ptr::null()) as usize; if res == 0 { - // Sometimes FormatMessageW can fail e.g. system doesn't like langId, + // Sometimes FormatMessageW can fail e.g., system doesn't like langId, let fm_err = errno(); return format!("OS Error {} (FormatMessageW() returned error {})", errnum, fm_err); @@ -76,7 +76,7 @@ pub fn error_string(mut errnum: i32) -> String { match String::from_utf16(&buf[..res]) { Ok(mut msg) => { // Trim trailing CRLF inserted by FormatMessageW - let len = msg.trim_right().len(); + let len = msg.trim_end().len(); msg.truncate(len); msg }, diff --git a/src/libstd/sys/windows/path.rs b/src/libstd/sys/windows/path.rs index 98d62a0c953..385ea8e0531 100644 --- a/src/libstd/sys/windows/path.rs +++ b/src/libstd/sys/windows/path.rs @@ -91,10 +91,7 @@ pub fn parse_prefix<'a>(path: &'a OsStr) -> Option { } fn parse_two_comps(mut path: &[u8], f: fn(u8) -> bool) -> Option<(&[u8], &[u8])> { - let first = match path.iter().position(|x| f(*x)) { - None => return None, - Some(x) => &path[..x], - }; + let first = &path[..path.iter().position(|x| f(*x))?]; path = &path[(first.len() + 1)..]; let idx = path.iter().position(|x| f(*x)); let second = &path[..idx.unwrap_or(path.len())]; @@ -102,5 +99,5 @@ pub fn parse_prefix<'a>(path: &'a OsStr) -> Option { } } -pub const MAIN_SEP_STR: &'static str = "\\"; +pub const MAIN_SEP_STR: &str = "\\"; pub const MAIN_SEP: char = '\\'; diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs index 4b19519a57a..f9eed31f0e0 100644 --- a/src/libstd/sys/windows/pipe.rs +++ b/src/libstd/sys/windows/pipe.rs @@ -100,23 +100,23 @@ pub fn anon_pipe(ours_readable: bool) -> io::Result { 0, ptr::null_mut()); - // We pass the FILE_FLAG_FIRST_PIPE_INSTANCE flag above, and we're + // We pass the `FILE_FLAG_FIRST_PIPE_INSTANCE` flag above, and we're // also just doing a best effort at selecting a unique name. If - // ERROR_ACCESS_DENIED is returned then it could mean that we + // `ERROR_ACCESS_DENIED` is returned then it could mean that we // accidentally conflicted with an already existing pipe, so we try // again. // // Don't try again too much though as this could also perhaps be a // legit error. - // If ERROR_INVALID_PARAMETER is returned, this probably means we're - // running on pre-Vista version where PIPE_REJECT_REMOTE_CLIENTS is + // If `ERROR_INVALID_PARAMETER` is returned, this probably means we're + // running on pre-Vista version where `PIPE_REJECT_REMOTE_CLIENTS` is // not supported, so we continue retrying without it. This implies // reduced security on Windows versions older than Vista by allowing // connections to this pipe from remote machines. // Proper fix would increase the number of FFI imports and introduce // significant amount of Windows XP specific code with no clean // testing strategy - // for more info see https://github.com/rust-lang/rust/pull/37677 + // For more info, see https://github.com/rust-lang/rust/pull/37677. if handle == c::INVALID_HANDLE_VALUE { let err = io::Error::last_os_error(); let raw_os_err = err.raw_os_error(); diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index ff1ee0d26fe..03c1bb54af8 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -487,7 +487,7 @@ fn make_command_line(prog: &OsStr, args: &[OsString]) -> io::Result> { } else { if x == '"' as u16 { // Add n+1 backslashes to total 2n+1 before internal '"'. - cmd.extend((0..(backslashes + 1)).map(|_| '\\' as u16)); + cmd.extend((0..=backslashes).map(|_| '\\' as u16)); } backslashes = 0; } diff --git a/src/libstd/sys/windows/stdio.rs b/src/libstd/sys/windows/stdio.rs index c3a94698a0f..61e0db87ebe 100644 --- a/src/libstd/sys/windows/stdio.rs +++ b/src/libstd/sys/windows/stdio.rs @@ -228,6 +228,6 @@ pub fn is_ebadf(err: &io::Error) -> bool { // been seen to be acceptable. pub const STDIN_BUF_SIZE: usize = 8 * 1024; -pub fn stderr_prints_nothing() -> bool { - false +pub fn panic_output() -> Option { + Stderr::new().ok() } diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs index 85588cc6c8e..621ae2fda58 100644 --- a/src/libstd/sys/windows/thread.rs +++ b/src/libstd/sys/windows/thread.rs @@ -28,7 +28,8 @@ pub struct Thread { } impl Thread { - pub unsafe fn new<'a>(stack: usize, p: Box) + // unsafe: see thread::Builder::spawn_unchecked for safety requirements + pub unsafe fn new(stack: usize, p: Box) -> io::Result { let p = box p; @@ -97,5 +98,4 @@ pub mod guard { pub type Guard = !; pub unsafe fn current() -> Option { None } pub unsafe fn init() -> Option { None } - pub unsafe fn deinit() {} } diff --git a/src/libstd/sys/windows/time.rs b/src/libstd/sys/windows/time.rs index c809a0b98ac..bb2c97ea149 100644 --- a/src/libstd/sys/windows/time.rs +++ b/src/libstd/sys/windows/time.rs @@ -68,30 +68,27 @@ impl Instant { Duration::new(nanos / NANOS_PER_SEC, (nanos % NANOS_PER_SEC) as u32) } - pub fn add_duration(&self, other: &Duration) -> Instant { + pub fn checked_add_duration(&self, other: &Duration) -> Option { let freq = frequency() as u64; - let t = other.as_secs().checked_mul(freq).and_then(|i| { - (self.t as u64).checked_add(i) - }).and_then(|i| { - i.checked_add(mul_div_u64(other.subsec_nanos() as u64, freq, - NANOS_PER_SEC)) - }).expect("overflow when adding duration to time"); - Instant { + let t = other.as_secs() + .checked_mul(freq)? + .checked_add(mul_div_u64(other.subsec_nanos() as u64, freq, NANOS_PER_SEC))? + .checked_add(self.t as u64)?; + Some(Instant { t: t as c::LARGE_INTEGER, - } + }) } - pub fn sub_duration(&self, other: &Duration) -> Instant { + pub fn checked_sub_duration(&self, other: &Duration) -> Option { let freq = frequency() as u64; let t = other.as_secs().checked_mul(freq).and_then(|i| { (self.t as u64).checked_sub(i) }).and_then(|i| { - i.checked_sub(mul_div_u64(other.subsec_nanos() as u64, freq, - NANOS_PER_SEC)) - }).expect("overflow when subtracting duration from time"); - Instant { + i.checked_sub(mul_div_u64(other.subsec_nanos() as u64, freq, NANOS_PER_SEC)) + })?; + Some(Instant { t: t as c::LARGE_INTEGER, - } + }) } } @@ -127,20 +124,14 @@ impl SystemTime { } } - pub fn add_duration(&self, other: &Duration) -> SystemTime { - self.checked_add_duration(other).expect("overflow when adding duration to time") - } - pub fn checked_add_duration(&self, other: &Duration) -> Option { - checked_dur2intervals(other) - .and_then(|d| self.intervals().checked_add(d)) - .map(|i| SystemTime::from_intervals(i)) + let intervals = self.intervals().checked_add(checked_dur2intervals(other)?)?; + Some(SystemTime::from_intervals(intervals)) } - pub fn sub_duration(&self, other: &Duration) -> SystemTime { - let intervals = self.intervals().checked_sub(dur2intervals(other)) - .expect("overflow when subtracting from time"); - SystemTime::from_intervals(intervals) + pub fn checked_sub_duration(&self, other: &Duration) -> Option { + let intervals = self.intervals().checked_sub(checked_dur2intervals(other)?)?; + Some(SystemTime::from_intervals(intervals)) } } @@ -184,16 +175,12 @@ impl Hash for SystemTime { } } -fn checked_dur2intervals(d: &Duration) -> Option { - d.as_secs() - .checked_mul(INTERVALS_PER_SEC) - .and_then(|i| i.checked_add(d.subsec_nanos() as u64 / 100)) - .and_then(|i| i.try_into().ok()) -} - -fn dur2intervals(d: &Duration) -> i64 { - checked_dur2intervals(d) - .expect("overflow when converting duration to intervals") +fn checked_dur2intervals(dur: &Duration) -> Option { + dur.as_secs() + .checked_mul(INTERVALS_PER_SEC)? + .checked_add(dur.subsec_nanos() as u64 / 100)? + .try_into() + .ok() } fn intervals2dur(intervals: u64) -> Duration { diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index 77371782977..e44113f76f4 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -14,11 +14,12 @@ use env; use io::prelude::*; use io; +use path::{self, Path}; +use ptr; +use rustc_demangle::demangle; use str; use sync::atomic::{self, Ordering}; -use path::{self, Path}; use sys::mutex::Mutex; -use ptr; pub use sys::backtrace::{ unwind_backtrace, @@ -191,7 +192,14 @@ fn output(w: &mut dyn Write, idx: usize, frame: Frame, PrintFormat::Short => write!(w, " {:2}: ", idx)?, } match s { - Some(string) => demangle(w, string, format)?, + Some(string) => { + let symbol = demangle(string); + match format { + PrintFormat::Full => write!(w, "{}", symbol)?, + // strip the trailing hash if short mode + PrintFormat::Short => write!(w, "{:#}", symbol)?, + } + } None => w.write_all(b"")?, } w.write_all(b"\n") @@ -235,228 +243,3 @@ fn output_fileline(w: &mut dyn Write, w.write_all(b"\n") } - -// All rust symbols are in theory lists of "::"-separated identifiers. Some -// assemblers, however, can't handle these characters in symbol names. To get -// around this, we use C++-style mangling. The mangling method is: -// -// 1. Prefix the symbol with "_ZN" -// 2. For each element of the path, emit the length plus the element -// 3. End the path with "E" -// -// For example, "_ZN4testE" => "test" and "_ZN3foo3barE" => "foo::bar". -// -// We're the ones printing our backtraces, so we can't rely on anything else to -// demangle our symbols. It's *much* nicer to look at demangled symbols, so -// this function is implemented to give us nice pretty output. -// -// Note that this demangler isn't quite as fancy as it could be. We have lots -// of other information in our symbols like hashes, version, type information, -// etc. Additionally, this doesn't handle glue symbols at all. -pub fn demangle(writer: &mut dyn Write, mut s: &str, format: PrintFormat) -> io::Result<()> { - // During ThinLTO LLVM may import and rename internal symbols, so strip out - // those endings first as they're one of the last manglings applied to - // symbol names. - let llvm = ".llvm."; - if let Some(i) = s.find(llvm) { - let candidate = &s[i + llvm.len()..]; - let all_hex = candidate.chars().all(|c| { - match c { - 'A' ..= 'F' | '0' ..= '9' => true, - _ => false, - } - }); - - if all_hex { - s = &s[..i]; - } - } - - // Validate the symbol. If it doesn't look like anything we're - // expecting, we just print it literally. Note that we must handle non-rust - // symbols because we could have any function in the backtrace. - let mut valid = true; - let mut inner = s; - if s.len() > 4 && s.starts_with("_ZN") && s.ends_with("E") { - inner = &s[3 .. s.len() - 1]; - // On Windows, dbghelp strips leading underscores, so we accept "ZN...E" form too. - } else if s.len() > 3 && s.starts_with("ZN") && s.ends_with("E") { - inner = &s[2 .. s.len() - 1]; - } else { - valid = false; - } - - if valid { - let mut chars = inner.chars(); - while valid { - let mut i = 0; - for c in chars.by_ref() { - if c.is_numeric() { - i = i * 10 + c as usize - '0' as usize; - } else { - break - } - } - if i == 0 { - valid = chars.next().is_none(); - break - } else if chars.by_ref().take(i - 1).count() != i - 1 { - valid = false; - } - } - } - - // Alright, let's do this. - if !valid { - writer.write_all(s.as_bytes())?; - } else { - // remove the `::hfc2edb670e5eda97` part at the end of the symbol. - if format == PrintFormat::Short { - // The symbol in still mangled. - let mut split = inner.rsplitn(2, "17h"); - match (split.next(), split.next()) { - (Some(addr), rest) => { - if addr.len() == 16 && - addr.chars().all(|c| c.is_digit(16)) - { - inner = rest.unwrap_or(""); - } - } - _ => (), - } - } - - let mut first = true; - while !inner.is_empty() { - if !first { - writer.write_all(b"::")?; - } else { - first = false; - } - let mut rest = inner; - while rest.chars().next().unwrap().is_numeric() { - rest = &rest[1..]; - } - let i: usize = inner[.. (inner.len() - rest.len())].parse().unwrap(); - inner = &rest[i..]; - rest = &rest[..i]; - if rest.starts_with("_$") { - rest = &rest[1..]; - } - while !rest.is_empty() { - if rest.starts_with(".") { - if let Some('.') = rest[1..].chars().next() { - writer.write_all(b"::")?; - rest = &rest[2..]; - } else { - writer.write_all(b".")?; - rest = &rest[1..]; - } - } else if rest.starts_with("$") { - macro_rules! demangle { - ($($pat:expr => $demangled:expr),*) => ({ - $(if rest.starts_with($pat) { - writer.write_all($demangled)?; - rest = &rest[$pat.len()..]; - } else)* - { - writer.write_all(rest.as_bytes())?; - break; - } - - }) - } - - // see src/librustc/back/link.rs for these mappings - demangle! ( - "$SP$" => b"@", - "$BP$" => b"*", - "$RF$" => b"&", - "$LT$" => b"<", - "$GT$" => b">", - "$LP$" => b"(", - "$RP$" => b")", - "$C$" => b",", - - // in theory we can demangle any Unicode code point, but - // for simplicity we just catch the common ones. - "$u7e$" => b"~", - "$u20$" => b" ", - "$u27$" => b"'", - "$u5b$" => b"[", - "$u5d$" => b"]", - "$u7b$" => b"{", - "$u7d$" => b"}", - "$u3b$" => b";", - "$u2b$" => b"+", - "$u22$" => b"\"" - ) - } else { - let idx = match rest.char_indices().find(|&(_, c)| c == '$' || c == '.') { - None => rest.len(), - Some((i, _)) => i, - }; - writer.write_all(rest[..idx].as_bytes())?; - rest = &rest[idx..]; - } - } - } - } - - Ok(()) -} - -#[cfg(test)] -mod tests { - use sys_common; - macro_rules! t { ($a:expr, $b:expr) => ({ - let mut m = Vec::new(); - sys_common::backtrace::demangle(&mut m, - $a, - super::PrintFormat::Full).unwrap(); - assert_eq!(String::from_utf8(m).unwrap(), $b); - }) } - - #[test] - fn demangle() { - t!("test", "test"); - t!("_ZN4testE", "test"); - t!("_ZN4test", "_ZN4test"); - t!("_ZN4test1a2bcE", "test::a::bc"); - } - - #[test] - fn demangle_dollars() { - t!("_ZN4$RP$E", ")"); - t!("_ZN8$RF$testE", "&test"); - t!("_ZN8$BP$test4foobE", "*test::foob"); - t!("_ZN9$u20$test4foobE", " test::foob"); - t!("_ZN35Bar$LT$$u5b$u32$u3b$$u20$4$u5d$$GT$E", "Bar<[u32; 4]>"); - } - - #[test] - fn demangle_many_dollars() { - t!("_ZN13test$u20$test4foobE", "test test::foob"); - t!("_ZN12test$BP$test4foobE", "test*test::foob"); - } - - #[test] - fn demangle_windows() { - t!("ZN4testE", "test"); - t!("ZN13test$u20$test4foobE", "test test::foob"); - t!("ZN12test$RF$test4foobE", "test&test::foob"); - } - - #[test] - fn demangle_elements_beginning_with_underscore() { - t!("_ZN13_$LT$test$GT$E", ""); - t!("_ZN28_$u7b$$u7b$closure$u7d$$u7d$E", "{{closure}}"); - t!("_ZN15__STATIC_FMTSTRE", "__STATIC_FMTSTR"); - } - - #[test] - fn demangle_trait_impls() { - t!("_ZN71_$LT$Test$u20$$u2b$$u20$$u27$static$u20$as$u20$foo..Bar$LT$Test$GT$$GT$3barE", - ">::bar"); - } -} diff --git a/src/libstd/sys_common/gnu/libbacktrace.rs b/src/libstd/sys_common/gnu/libbacktrace.rs index 6ad3af6aee1..c2589d477ee 100644 --- a/src/libstd/sys_common/gnu/libbacktrace.rs +++ b/src/libstd/sys_common/gnu/libbacktrace.rs @@ -23,7 +23,7 @@ pub fn foreach_symbol_fileline(frame: Frame, where F: FnMut(&[u8], u32) -> io::Result<()> { // pcinfo may return an arbitrary number of file:line pairs, - // in the order of stack trace (i.e. inlined calls first). + // in the order of stack trace (i.e., inlined calls first). // in order to avoid allocation, we stack-allocate a fixed size of entries. const FILELINE_SIZE: usize = 32; let mut fileline_buf = [(ptr::null(), !0); FILELINE_SIZE]; diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs index 4b8cde3d1f4..881794d9f16 100644 --- a/src/libstd/sys_common/mod.rs +++ b/src/libstd/sys_common/mod.rs @@ -57,9 +57,11 @@ pub mod bytestring; pub mod process; cfg_if! { - if #[cfg(any(target_os = "cloudabi", target_os = "l4re", target_os = "redox"))] { - pub use sys::net; - } else if #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] { + if #[cfg(any(target_os = "cloudabi", + target_os = "l4re", + target_os = "redox", + all(target_arch = "wasm32", not(target_os = "emscripten")), + target_env = "sgx"))] { pub use sys::net; } else { pub mod net; diff --git a/src/libstd/sys_common/net.rs b/src/libstd/sys_common/net.rs index d09a233ed89..dce2bf71cec 100644 --- a/src/libstd/sys_common/net.rs +++ b/src/libstd/sys_common/net.rs @@ -20,6 +20,7 @@ use sys::net::{cvt, cvt_r, cvt_gai, Socket, init, wrlen_t}; use sys::net::netc as c; use sys_common::{AsInner, FromInner, IntoInner}; use time::Duration; +use convert::{TryFrom, TryInto}; #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "ios", target_os = "macos", @@ -129,6 +130,13 @@ fn to_ipv6mr_interface(value: u32) -> ::libc::c_uint { pub struct LookupHost { original: *mut c::addrinfo, cur: *mut c::addrinfo, + port: u16 +} + +impl LookupHost { + pub fn port(&self) -> u16 { + self.port + } } impl Iterator for LookupHost { @@ -158,17 +166,45 @@ impl Drop for LookupHost { } } -pub fn lookup_host(host: &str) -> io::Result { - init(); +impl<'a> TryFrom<&'a str> for LookupHost { + type Error = io::Error; - let c_host = CString::new(host)?; - let mut hints: c::addrinfo = unsafe { mem::zeroed() }; - hints.ai_socktype = c::SOCK_STREAM; - let mut res = ptr::null_mut(); - unsafe { - cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), &hints, &mut res)).map(|_| { - LookupHost { original: res, cur: res } - }) + fn try_from(s: &str) -> io::Result { + macro_rules! try_opt { + ($e:expr, $msg:expr) => ( + match $e { + Some(r) => r, + None => return Err(io::Error::new(io::ErrorKind::InvalidInput, + $msg)), + } + ) + } + + // split the string by ':' and convert the second part to u16 + let mut parts_iter = s.rsplitn(2, ':'); + let port_str = try_opt!(parts_iter.next(), "invalid socket address"); + let host = try_opt!(parts_iter.next(), "invalid socket address"); + let port: u16 = try_opt!(port_str.parse().ok(), "invalid port value"); + + (host, port).try_into() + } +} + +impl<'a> TryFrom<(&'a str, u16)> for LookupHost { + type Error = io::Error; + + fn try_from((host, port): (&'a str, u16)) -> io::Result { + init(); + + let c_host = CString::new(host)?; + let mut hints: c::addrinfo = unsafe { mem::zeroed() }; + hints.ai_socktype = c::SOCK_STREAM; + let mut res = ptr::null_mut(); + unsafe { + cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), &hints, &mut res)).map(|_| { + LookupHost { original: res, cur: res, port } + }) + } } } @@ -181,7 +217,9 @@ pub struct TcpStream { } impl TcpStream { - pub fn connect(addr: &SocketAddr) -> io::Result { + pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result { + let addr = addr?; + init(); let sock = Socket::new(addr, c::SOCK_STREAM)?; @@ -317,7 +355,9 @@ pub struct TcpListener { } impl TcpListener { - pub fn bind(addr: &SocketAddr) -> io::Result { + pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result { + let addr = addr?; + init(); let sock = Socket::new(addr, c::SOCK_STREAM)?; @@ -418,7 +458,9 @@ pub struct UdpSocket { } impl UdpSocket { - pub fn bind(addr: &SocketAddr) -> io::Result { + pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result { + let addr = addr?; + init(); let sock = Socket::new(addr, c::SOCK_DGRAM)?; @@ -584,8 +626,8 @@ impl UdpSocket { Ok(ret as usize) } - pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> { - let (addrp, len) = addr.into_inner(); + pub fn connect(&self, addr: io::Result<&SocketAddr>) -> io::Result<()> { + let (addrp, len) = addr?.into_inner(); cvt_r(|| unsafe { c::connect(*self.inner.as_inner(), addrp, len) }).map(|_| ()) } } @@ -618,7 +660,7 @@ mod tests { #[test] fn no_lookup_host_duplicates() { let mut addrs = HashMap::new(); - let lh = match lookup_host("localhost") { + let lh = match LookupHost::try_from(("localhost", 0)) { Ok(lh) => lh, Err(e) => panic!("couldn't resolve `localhost': {}", e) }; diff --git a/src/libstd/sys_common/util.rs b/src/libstd/sys_common/util.rs index a373e980b97..fc86a59d17f 100644 --- a/src/libstd/sys_common/util.rs +++ b/src/libstd/sys_common/util.rs @@ -10,14 +10,13 @@ use fmt; use io::prelude::*; -use sys::stdio::{Stderr, stderr_prints_nothing}; +use sys::stdio::panic_output; use thread; pub fn dumb_print(args: fmt::Arguments) { - if stderr_prints_nothing() { - return + if let Some(mut out) = panic_output() { + let _ = out.write_fmt(args); } - let _ = Stderr::new().map(|mut stderr| stderr.write_fmt(args)); } // Other platforms should use the appropriate platform-specific mechanism for diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs index 19ce932aa12..3530b7af9ad 100644 --- a/src/libstd/sys_common/wtf8.rs +++ b/src/libstd/sys_common/wtf8.rs @@ -40,7 +40,7 @@ use str; use sync::Arc; use sys_common::AsInner; -const UTF8_REPLACEMENT_CHARACTER: &'static str = "\u{FFFD}"; +const UTF8_REPLACEMENT_CHARACTER: &str = "\u{FFFD}"; /// A Unicode code point: from U+0000 to U+10FFFF. /// diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index 4df47511172..8bb99096061 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -269,7 +269,7 @@ impl LocalKey { // ptr::write(ptr, Some(value)) // // Due to this pattern it's possible for the destructor of the value in - // `ptr` (e.g. if this is being recursively initialized) to re-access + // `ptr` (e.g., if this is being recursively initialized) to re-access // TLS, in which case there will be a `&` and `&mut` pointer to the same // value (an aliasing violation). To avoid setting the "I'm running a // destructor" flag we just use `mem::replace` which should sequence the diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 3a9f3ec5c6f..b70dfc46af5 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -93,7 +93,7 @@ //! Threads are represented via the [`Thread`] type, which you can get in one of //! two ways: //! -//! * By spawning a new thread, e.g. using the [`thread::spawn`][`spawn`] +//! * By spawning a new thread, e.g., using the [`thread::spawn`][`spawn`] //! function, and calling [`thread`][`JoinHandle::thread`] on the [`JoinHandle`]. //! * By requesting the current thread, using the [`thread::current`] function. //! @@ -124,7 +124,7 @@ //! thread, use [`Thread::name`]. A couple examples of where the name of a thread gets used: //! //! * If a panic occurs in a named thread, the thread name will be printed in the panic message. -//! * The thread name is provided to the OS where applicable (e.g. `pthread_setname_np` in +//! * The thread name is provided to the OS where applicable (e.g., `pthread_setname_np` in //! unix-like platforms). //! //! ## Stack size @@ -167,10 +167,12 @@ #![stable(feature = "rust1", since = "1.0.0")] use any::Any; +use boxed::FnBox; use cell::UnsafeCell; use ffi::{CStr, CString}; use fmt; use io; +use mem; use panic; use panicking; use str; @@ -420,7 +422,7 @@ impl Builder { /// /// - ensure that [`join`][`JoinHandle::join`] is called before any referenced /// data is dropped - /// - use only types with `'static` lifetime bounds, i.e. those with no or only + /// - use only types with `'static` lifetime bounds, i.e., those with no or only /// `'static` references (both [`thread::Builder::spawn`][`Builder::spawn`] /// and [`thread::spawn`][`spawn`] enforce this property statically) /// @@ -452,8 +454,8 @@ impl Builder { /// [`io::Result`]: ../../std/io/type.Result.html /// [`JoinHandle`]: ../../std/thread/struct.JoinHandle.html #[unstable(feature = "thread_spawn_unchecked", issue = "55132")] - pub unsafe fn spawn_unchecked(self, f: F) -> io::Result> where - F: FnOnce() -> T, F: Send, T: Send + pub unsafe fn spawn_unchecked<'a, F, T>(self, f: F) -> io::Result> where + F: FnOnce() -> T, F: Send + 'a, T: Send + 'a { let Builder { name, stack_size } = self; @@ -482,7 +484,21 @@ impl Builder { }; Ok(JoinHandle(JoinInner { - native: Some(imp::Thread::new(stack_size, Box::new(main))?), + // `imp::Thread::new` takes a closure with a `'static` lifetime, since it's passed + // through FFI or otherwise used with low-level threading primitives that have no + // notion of or way to enforce lifetimes. + // + // As mentioned in the `Safety` section of this function's documentation, the caller of + // this function needs to guarantee that the passed-in lifetime is sufficiently long + // for the lifetime of the thread. + // + // Similarly, the `sys` implementation must guarantee that no references to the closure + // exist after the thread has terminated, which is signaled by `Thread::join` + // returning. + native: Some(imp::Thread::new( + stack_size, + mem::transmute::, Box>(Box::new(main)) + )?), thread: my_thread, packet: Packet(my_packet), })) @@ -676,7 +692,7 @@ pub fn yield_now() { /// already poison themselves when a thread panics while holding the lock. /// /// This can also be used in multithreaded applications, in order to send a -/// message to other threads warning that a thread has panicked (e.g. for +/// message to other threads warning that a thread has panicked (e.g., for /// monitoring purposes). /// /// # Examples @@ -806,9 +822,14 @@ const NOTIFIED: usize = 2; /// In other words, each [`Thread`] acts a bit like a spinlock that can be /// locked and unlocked using `park` and `unpark`. /// +/// Notice that being unblocked does not imply any synchronization with someone +/// that unparked this thread, it could also be spurious. +/// For example, it would be a valid, but inefficient, implementation to make both [`park`] and +/// [`unpark`] return immediately without doing anything. +/// /// The API is typically used by acquiring a handle to the current thread, /// placing that handle in a shared data structure so that other threads can -/// find it, and then `park`ing. When some desired condition is met, another +/// find it, and then `park`ing in a loop. When some desired condition is met, another /// thread calls [`unpark`] on the handle. /// /// The motivation for this design is twofold: @@ -823,21 +844,33 @@ const NOTIFIED: usize = 2; /// /// ``` /// use std::thread; +/// use std::sync::{Arc, atomic::{Ordering, AtomicBool}}; /// use std::time::Duration; /// -/// let parked_thread = thread::Builder::new() -/// .spawn(|| { +/// let flag = Arc::new(AtomicBool::new(false)); +/// let flag2 = Arc::clone(&flag); +/// +/// let parked_thread = thread::spawn(move || { +/// // We want to wait until the flag is set. We *could* just spin, but using +/// // park/unpark is more efficient. +/// while !flag2.load(Ordering::Acquire) { /// println!("Parking thread"); /// thread::park(); +/// // We *could* get here spuriously, i.e., way before the 10ms below are over! +/// // But that is no problem, we are in a loop until the flag is set anyway. /// println!("Thread unparked"); -/// }) -/// .unwrap(); +/// } +/// println!("Flag received"); +/// }); /// /// // Let some time pass for the thread to be spawned. /// thread::sleep(Duration::from_millis(10)); /// +/// // Set the flag, and let the thread wake up. /// // There is no race condition here, if `unpark` /// // happens first, `park` will return immediately. +/// // Hence there is no risk of a deadlock. +/// flag.store(true, Ordering::Release); /// println!("Unpark the thread"); /// parked_thread.thread().unpark(); /// @@ -1062,7 +1095,7 @@ struct Inner { /// Threads are represented via the `Thread` type, which you can get in one of /// two ways: /// -/// * By spawning a new thread, e.g. using the [`thread::spawn`][`spawn`] +/// * By spawning a new thread, e.g., using the [`thread::spawn`][`spawn`] /// function, and calling [`thread`][`JoinHandle::thread`] on the /// [`JoinHandle`]. /// * By requesting the current thread, using the [`thread::current`] function. diff --git a/src/libstd/time.rs b/src/libstd/time.rs index 5d0d501615f..63cede79e48 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -208,6 +208,22 @@ impl Instant { pub fn elapsed(&self) -> Duration { Instant::now() - *self } + + /// Returns `Some(t)` where `t` is the time `self + duration` if `t` can be represented as + /// `Instant` (which means it's inside the bounds of the underlying data structure), `None` + /// otherwise. + #[unstable(feature = "time_checked_add", issue = "55940")] + pub fn checked_add(&self, duration: Duration) -> Option { + self.0.checked_add_duration(&duration).map(|t| Instant(t)) + } + + /// Returns `Some(t)` where `t` is the time `self - duration` if `t` can be represented as + /// `Instant` (which means it's inside the bounds of the underlying data structure), `None` + /// otherwise. + #[unstable(feature = "time_checked_add", issue = "55940")] + pub fn checked_sub(&self, duration: Duration) -> Option { + self.0.checked_sub_duration(&duration).map(|t| Instant(t)) + } } #[stable(feature = "time2", since = "1.8.0")] @@ -215,7 +231,8 @@ impl Add for Instant { type Output = Instant; fn add(self, other: Duration) -> Instant { - Instant(self.0.add_duration(&other)) + self.checked_add(other) + .expect("overflow when adding duration to instant") } } @@ -231,7 +248,8 @@ impl Sub for Instant { type Output = Instant; fn sub(self, other: Duration) -> Instant { - Instant(self.0.sub_duration(&other)) + self.checked_sub(other) + .expect("overflow when subtracting duration from instant") } } @@ -330,7 +348,7 @@ impl SystemTime { /// Returns the amount of time elapsed since this system time was created. /// /// This function may fail as the underlying system clock is susceptible to - /// drift and updates (e.g. the system clock could go backwards), so this + /// drift and updates (e.g., the system clock could go backwards), so this /// function may not always succeed. If successful, [`Ok`]`(`[`Duration`]`)` is /// returned where the duration represents the amount of time elapsed from /// this time measurement to the current time. @@ -365,6 +383,14 @@ impl SystemTime { pub fn checked_add(&self, duration: Duration) -> Option { self.0.checked_add_duration(&duration).map(|t| SystemTime(t)) } + + /// Returns `Some(t)` where `t` is the time `self - duration` if `t` can be represented as + /// `SystemTime` (which means it's inside the bounds of the underlying data structure), `None` + /// otherwise. + #[unstable(feature = "time_checked_add", issue = "55940")] + pub fn checked_sub(&self, duration: Duration) -> Option { + self.0.checked_sub_duration(&duration).map(|t| SystemTime(t)) + } } #[stable(feature = "time2", since = "1.8.0")] @@ -372,7 +398,8 @@ impl Add for SystemTime { type Output = SystemTime; fn add(self, dur: Duration) -> SystemTime { - SystemTime(self.0.add_duration(&dur)) + self.checked_add(dur) + .expect("overflow when adding duration to instant") } } @@ -388,7 +415,8 @@ impl Sub for SystemTime { type Output = SystemTime; fn sub(self, dur: Duration) -> SystemTime { - SystemTime(self.0.sub_duration(&dur)) + self.checked_sub(dur) + .expect("overflow when subtracting duration from instant") } } @@ -521,6 +549,20 @@ mod tests { let second = Duration::new(1, 0); assert_almost_eq!(a - second + second, a); + assert_almost_eq!(a.checked_sub(second).unwrap().checked_add(second).unwrap(), a); + + // checked_add_duration will not panic on overflow + let mut maybe_t = Some(Instant::now()); + let max_duration = Duration::from_secs(u64::max_value()); + // in case `Instant` can store `>= now + max_duration`. + for _ in 0..2 { + maybe_t = maybe_t.and_then(|t| t.checked_add(max_duration)); + } + assert_eq!(maybe_t, None); + + // checked_add_duration calculates the right time and will work for another year + let year = Duration::from_secs(60 * 60 * 24 * 365); + assert_eq!(a + year, a.checked_add(year).unwrap()); } #[test] @@ -557,6 +599,7 @@ mod tests { .duration(), second); assert_almost_eq!(a - second + second, a); + assert_almost_eq!(a.checked_sub(second).unwrap().checked_add(second).unwrap(), a); // A difference of 80 and 800 years cannot fit inside a 32-bit time_t if !(cfg!(unix) && ::mem::size_of::<::libc::time_t>() <= 4) { diff --git a/src/libsyntax/Cargo.toml b/src/libsyntax/Cargo.toml index 519cc7aa92c..fba2623e005 100644 --- a/src/libsyntax/Cargo.toml +++ b/src/libsyntax/Cargo.toml @@ -17,4 +17,4 @@ syntax_pos = { path = "../libsyntax_pos" } rustc_errors = { path = "../librustc_errors" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_target = { path = "../librustc_target" } -smallvec = { version = "0.6.5", features = ["union"] } +smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 227017a9073..0792b2dc49c 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -68,12 +68,12 @@ impl fmt::Debug for Lifetime { /// It's represented as a sequence of identifiers, /// along with a bunch of supporting information. /// -/// E.g. `std::cmp::PartialEq` +/// E.g., `std::cmp::PartialEq`. #[derive(Clone, RustcEncodable, RustcDecodable)] pub struct Path { pub span: Span, /// The segments in the path: the things separated by `::`. - /// Global paths begin with `keywords::CrateRoot`. + /// Global paths begin with `keywords::PathRoot`. pub segments: Vec, } @@ -96,8 +96,8 @@ impl fmt::Display for Path { } impl Path { - // convert a span and an identifier to the corresponding - // 1-segment path + // Convert a span and an identifier to the corresponding + // one-segment path. pub fn from_ident(ident: Ident) -> Path { Path { segments: vec![PathSegment::from_ident(ident)], @@ -105,25 +105,14 @@ impl Path { } } - // Make a "crate root" segment for this path unless it already has it - // or starts with something like `self`/`super`/`$crate`/etc. - pub fn make_root(&self) -> Option { - if let Some(ident) = self.segments.get(0).map(|seg| seg.ident) { - if ident.is_path_segment_keyword() { - return None; - } - } - Some(PathSegment::crate_root(self.span.shrink_to_lo())) - } - pub fn is_global(&self) -> bool { - !self.segments.is_empty() && self.segments[0].ident.name == keywords::CrateRoot.name() + !self.segments.is_empty() && self.segments[0].ident.name == keywords::PathRoot.name() } } /// A segment of a path: an identifier, an optional lifetime, and a set of types. /// -/// E.g. `std`, `String` or `Box` +/// E.g., `std`, `String` or `Box`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct PathSegment { /// The identifier portion of this path segment. @@ -144,14 +133,14 @@ impl PathSegment { pub fn from_ident(ident: Ident) -> Self { PathSegment { ident, id: DUMMY_NODE_ID, args: None } } - pub fn crate_root(span: Span) -> Self { - PathSegment::from_ident(Ident::new(keywords::CrateRoot.name(), span)) + pub fn path_root(span: Span) -> Self { + PathSegment::from_ident(Ident::new(keywords::PathRoot.name(), span)) } } /// Arguments of a path segment. /// -/// E.g. `` as in `Foo` or `(A, B)` as in `Foo(A, B)` +/// E.g., `` as in `Foo` or `(A, B)` as in `Foo(A, B)`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum GenericArgs { /// The `<'a, A,B,C>` in `foo::bar::baz::<'a, A,B,C>` @@ -293,7 +282,7 @@ pub type GenericBounds = Vec; #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum GenericParamKind { - /// A lifetime definition, e.g. `'a: 'b+'c+'d`. + /// A lifetime definition (e.g., `'a: 'b + 'c + 'd`). Lifetime, Type { default: Option>, @@ -345,11 +334,11 @@ pub struct WhereClause { /// A single predicate in a `where` clause #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum WherePredicate { - /// A type binding, e.g. `for<'c> Foo: Send+Clone+'c` + /// A type binding (e.g., `for<'c> Foo: Send + Clone + 'c`). BoundPredicate(WhereBoundPredicate), - /// A lifetime predicate, e.g. `'a: 'b+'c` + /// A lifetime predicate (e.g., `'a: 'b + 'c`). RegionPredicate(WhereRegionPredicate), - /// An equality predicate (unsupported) + /// An equality predicate (unsupported). EqPredicate(WhereEqPredicate), } @@ -365,7 +354,7 @@ impl WherePredicate { /// A type bound. /// -/// E.g. `for<'c> Foo: Send+Clone+'c` +/// E.g., `for<'c> Foo: Send + Clone + 'c`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct WhereBoundPredicate { pub span: Span, @@ -379,7 +368,7 @@ pub struct WhereBoundPredicate { /// A lifetime predicate. /// -/// E.g. `'a: 'b+'c` +/// E.g., `'a: 'b + 'c`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct WhereRegionPredicate { pub span: Span, @@ -389,7 +378,7 @@ pub struct WhereRegionPredicate { /// An equality predicate (unsupported). /// -/// E.g. `T=int` +/// E.g., `T = int`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct WhereEqPredicate { pub id: NodeId, @@ -398,8 +387,8 @@ pub struct WhereEqPredicate { pub rhs_ty: P, } -/// The set of MetaItems that define the compilation environment of the crate, -/// used to drive conditional compilation +/// The set of `MetaItem`s that define the compilation environment of the crate, +/// used to drive conditional compilation. pub type CrateConfig = FxHashSet<(Name, Option)>; #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] @@ -414,20 +403,20 @@ pub type NestedMetaItem = Spanned; /// Possible values inside of compile-time attribute lists. /// -/// E.g. the '..' in `#[name(..)]`. +/// E.g., the '..' in `#[name(..)]`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum NestedMetaItemKind { /// A full MetaItem, for recursive meta items. MetaItem(MetaItem), /// A literal. /// - /// E.g. "foo", 64, true + /// E.g., `"foo"`, `64`, `true`. Literal(Lit), } /// A spanned compile-time attribute item. /// -/// E.g. `#[test]`, `#[derive(..)]`, `#[rustfmt::skip]` or `#[feature = "foo"]` +/// E.g., `#[test]`, `#[derive(..)]`, `#[rustfmt::skip]` or `#[feature = "foo"]`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct MetaItem { pub ident: Path, @@ -437,26 +426,26 @@ pub struct MetaItem { /// A compile-time attribute item. /// -/// E.g. `#[test]`, `#[derive(..)]` or `#[feature = "foo"]` +/// E.g., `#[test]`, `#[derive(..)]` or `#[feature = "foo"]`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum MetaItemKind { /// Word meta item. /// - /// E.g. `test` as in `#[test]` + /// E.g., `test` as in `#[test]`. Word, /// List meta item. /// - /// E.g. `derive(..)` as in `#[derive(..)]` + /// E.g., `derive(..)` as in `#[derive(..)]`. List(Vec), /// Name value meta item. /// - /// E.g. `feature = "foo"` as in `#[feature = "foo"]` + /// E.g., `feature = "foo"` as in `#[feature = "foo"]`. NameValue(Lit), } /// A Block (`{ .. }`). /// -/// E.g. `{ .. }` as in `fn foo() { .. }` +/// E.g., `{ .. }` as in `fn foo() { .. }`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Block { /// Statements in a block @@ -579,7 +568,7 @@ pub enum RangeSyntax { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum PatKind { - /// Represents a wildcard pattern (`_`) + /// Represents a wildcard pattern (`_`). Wild, /// A `PatKind::Ident` may either be a new bound variable (`ref mut binding @ OPT_SUBPATTERN`), @@ -588,13 +577,13 @@ pub enum PatKind { /// during name resolution. Ident(BindingMode, Ident, Option>), - /// A struct or struct variant pattern, e.g. `Variant {x, y, ..}`. + /// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`). /// The `bool` is `true` in the presence of a `..`. Struct(Path, Vec>, bool), - /// A tuple struct/variant pattern `Variant(x, y, .., z)`. + /// A tuple struct/variant pattern (`Variant(x, y, .., z)`). /// If the `..` pattern fragment is present, then `Option` denotes its position. - /// 0 <= position <= subpats.len() + /// `0 <= position <= subpats.len()`. TupleStruct(Path, Vec>, Option), /// A possibly qualified path pattern. @@ -603,24 +592,24 @@ pub enum PatKind { /// only legally refer to associated constants. Path(Option, Path), - /// A tuple pattern `(a, b)`. + /// A tuple pattern (`(a, b)`). /// If the `..` pattern fragment is present, then `Option` denotes its position. - /// 0 <= position <= subpats.len() + /// `0 <= position <= subpats.len()`. Tuple(Vec>, Option), - /// A `box` pattern + /// A `box` pattern. Box(P), - /// A reference pattern, e.g. `&mut (a, b)` + /// A reference pattern (e.g., `&mut (a, b)`). Ref(P, Mutability), - /// A literal + /// A literal. Lit(P), - /// A range pattern, e.g. `1...2`, `1..=2` or `1..2` + /// A range pattern (e.g., `1...2`, `1..=2` or `1..2`). Range(P, P, Spanned), /// `[a, b, ..i, y, z]` is represented as: /// `PatKind::Slice(box [a, b], Some(i), box [y, z])` Slice(Vec>, Option>, Vec>), - /// Parentheses in patterns used for grouping, i.e. `(PAT)`. + /// Parentheses in patterns used for grouping (i.e., `(PAT)`). Paren(P), - /// A macro pattern; pre-expansion + /// A macro pattern; pre-expansion. Mac(Mac), } @@ -818,23 +807,23 @@ pub enum StmtKind { #[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug)] pub enum MacStmtStyle { - /// The macro statement had a trailing semicolon, e.g. `foo! { ... };` - /// `foo!(...);`, `foo![...];` + /// The macro statement had a trailing semicolon (e.g., `foo! { ... };` + /// `foo!(...);`, `foo![...];`). Semicolon, - /// The macro statement had braces; e.g. foo! { ... } + /// The macro statement had braces (e.g., `foo! { ... }`). Braces, - /// The macro statement had parentheses or brackets and no semicolon; e.g. - /// `foo!(...)`. All of these will end up being converted into macro + /// The macro statement had parentheses or brackets and no semicolon (e.g., + /// `foo!(...)`). All of these will end up being converted into macro /// expressions. NoBraces, } -/// Local represents a `let` statement, e.g., `let : = ;` +/// Local represents a `let` statement, e.g., `let : = ;`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Local { pub pat: P, pub ty: Option>, - /// Initializer expression to set the value, if any + /// Initializer expression to set the value, if any. pub init: Option>, pub id: NodeId, pub span: Span, @@ -843,7 +832,7 @@ pub struct Local { /// An arm of a 'match'. /// -/// E.g. `0..=10 => { println!("match!") }` as in +/// E.g., `0..=10 => { println!("match!") }` as in /// /// ``` /// match 123 { @@ -889,8 +878,8 @@ pub enum UnsafeSource { /// A constant (expression) that's not an item or associated item, /// but needs its own `DefId` for type-checking, const-eval, etc. -/// These are usually found nested inside types (e.g. array lengths) -/// or expressions (e.g. repeat counts), and also used to define +/// These are usually found nested inside types (e.g., array lengths) +/// or expressions (e.g., repeat counts), and also used to define /// explicit discriminant values for enum variants. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct AnonConst { @@ -912,7 +901,7 @@ pub struct Expr { static_assert!(MEM_SIZE_OF_EXPR: std::mem::size_of::() == 88); impl Expr { - /// Whether this expression would be valid somewhere that expects a value, for example, an `if` + /// Whether this expression would be valid somewhere that expects a value; for example, an `if` /// condition. pub fn returns(&self) -> bool { if let ExprKind::Block(ref block, _) = self.node { @@ -1060,24 +1049,24 @@ pub enum ExprKind { /// /// The `PathSegment` represents the method name and its generic arguments /// (within the angle brackets). - /// The first element of the vector of `Expr`s is the expression that evaluates + /// The first element of the vector of an `Expr` is the expression that evaluates /// to the object on which the method is being called on (the receiver), /// and the remaining elements are the rest of the arguments. /// Thus, `x.foo::(a, b, c, d)` is represented as /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`. MethodCall(PathSegment, Vec>), - /// A tuple (`(a, b, c ,d)`) + /// A tuple (e.g., `(a, b, c, d)`). Tup(Vec>), - /// A binary operation (For example: `a + b`, `a * b`) + /// A binary operation (e.g., `a + b`, `a * b`). Binary(BinOp, P, P), - /// A unary operation (For example: `!x`, `*x`) + /// A unary operation (e.g., `!x`, `*x`). Unary(UnOp, P), - /// A literal (For example: `1`, `"foo"`) + /// A literal (e.g., `1`, `"foo"`). Lit(Lit), - /// A cast (`foo as f64`) + /// A cast (e.g., `foo as f64`). Cast(P, P), Type(P, P), - /// An `if` block, with an optional else block + /// An `if` block, with an optional `else` block. /// /// `if expr { block } else { expr }` If(P, P, Option>), @@ -1091,31 +1080,31 @@ pub enum ExprKind { /// /// `'label: while expr { block }` While(P, P, Option, D }` + /// E.g., `enum Foo { C, D }`. Enum(EnumDef, Generics), /// A struct definition (`struct` or `pub struct`). /// - /// E.g. `struct Foo { x: A }` + /// E.g., `struct Foo { x: A }`. Struct(VariantData, Generics), /// A union definition (`union` or `pub union`). /// - /// E.g. `union Foo { x: A, y: B }` + /// E.g., `union Foo { x: A, y: B }`. Union(VariantData, Generics), /// A Trait declaration (`trait` or `pub trait`). /// - /// E.g. `trait Foo { .. }`, `trait Foo { .. }` or `auto trait Foo {}` + /// E.g., `trait Foo { .. }`, `trait Foo { .. }` or `auto trait Foo {}`. Trait(IsAuto, Unsafety, Generics, GenericBounds, Vec), /// Trait alias /// - /// E.g. `trait Foo = Bar + Quux;` + /// E.g., `trait Foo = Bar + Quux;`. TraitAlias(Generics, GenericBounds), /// An implementation. /// - /// E.g. `impl Foo { .. }` or `impl Trait for Foo { .. }` + /// E.g., `impl Foo { .. }` or `impl Trait for Foo { .. }`. Impl( Unsafety, ImplPolarity, @@ -2253,7 +2241,7 @@ pub enum ItemKind { ), /// A macro invocation. /// - /// E.g. `macro_rules! foo { .. }` or `foo!(..)` + /// E.g., `macro_rules! foo { .. }` or `foo!(..)`. Mac(Mac), /// A macro definition. @@ -2293,17 +2281,17 @@ pub struct ForeignItem { pub vis: Visibility, } -/// An item within an `extern` block +/// An item within an `extern` block. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum ForeignItemKind { - /// A foreign function + /// A foreign function. Fn(P, Generics), - /// A foreign static item (`static ext: u8`), with optional mutability - /// (the boolean is true when mutable) + /// A foreign static item (`static ext: u8`), with optional mutability. + /// (The boolean is `true` for mutable items). Static(P, bool), - /// A foreign type + /// A foreign type. Ty, - /// A macro invocation + /// A macro invocation. Macro(Mac), } @@ -2323,7 +2311,7 @@ mod tests { use super::*; use serialize; - // are ASTs encodable? + // Are ASTs encodable? #[test] fn check_asts_encodable() { fn assert_encodable() {} diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index 64876659477..73cbe49f43b 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -34,7 +34,7 @@ use parse::token::{self, Token}; use ptr::P; use symbol::Symbol; use ThinVec; -use tokenstream::{TokenStream, TokenTree, Delimited, DelimSpan}; +use tokenstream::{TokenStream, TokenTree, DelimSpan}; use GLOBALS; use std::iter; @@ -96,7 +96,7 @@ impl NestedMetaItem { self.meta_item().map_or(false, |meta_item| meta_item.check_name(name)) } - /// Returns the name of the meta item, e.g. `foo` in `#[foo]`, + /// Returns the name of the meta item, e.g., `foo` in `#[foo]`, /// `#[foo="bar"]` and `#[foo(bar)]`, if self is a MetaItem pub fn name(&self) -> Option { self.meta_item().and_then(|meta_item| Some(meta_item.name())) @@ -180,7 +180,7 @@ impl Attribute { } /// Returns the **last** segment of the name of this attribute. - /// E.g. `foo` for `#[foo]`, `skip` for `#[rustfmt::skip]`. + /// e.g., `foo` for `#[foo]`, `skip` for `#[rustfmt::skip]`. pub fn name(&self) -> Name { name_from_path(&self.path) } @@ -483,7 +483,7 @@ impl MetaItem { last_pos = segment.ident.span.hi(); } idents.push(self.node.tokens(self.span)); - TokenStream::concat(idents) + TokenStream::new(idents) } fn from_tokens(tokens: &mut iter::Peekable) -> Option @@ -539,7 +539,7 @@ impl MetaItemKind { match *self { MetaItemKind::Word => TokenStream::empty(), MetaItemKind::NameValue(ref lit) => { - TokenStream::concat(vec![TokenTree::Token(span, Token::Eq).into(), lit.tokens()]) + TokenStream::new(vec![TokenTree::Token(span, Token::Eq).into(), lit.tokens()]) } MetaItemKind::List(ref list) => { let mut tokens = Vec::new(); @@ -549,10 +549,11 @@ impl MetaItemKind { } tokens.push(item.node.tokens()); } - TokenTree::Delimited(DelimSpan::from_single(span), Delimited { - delim: token::Paren, - tts: TokenStream::concat(tokens).into(), - }).into() + TokenTree::Delimited( + DelimSpan::from_single(span), + token::Paren, + TokenStream::new(tokens).into(), + ).into() } } } @@ -570,9 +571,9 @@ impl MetaItemKind { None }; } - Some(TokenTree::Delimited(_, ref delimited)) if delimited.delim == token::Paren => { + Some(TokenTree::Delimited(_, delim, ref tts)) if delim == token::Paren => { tokens.next(); - delimited.stream() + tts.stream() } _ => return Some(MetaItemKind::Word), }; @@ -803,7 +804,7 @@ pub fn inject(mut krate: ast::Crate, parse_sess: &ParseSess, attrs: &[String]) - for raw_attr in attrs { let mut parser = parse::new_parser_from_source_str( parse_sess, - FileName::CliCrateAttr, + FileName::cli_crate_attr_source_code(&raw_attr), raw_attr.clone(), ); diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index d8fb20d4250..41307175ade 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -328,7 +328,7 @@ impl<'a> StripUnconfigured<'a> { // Anything else is always required, and thus has to error out // in case of a cfg attr. // - // NB: This is intentionally not part of the fold_expr() function + // N.B., this is intentionally not part of the fold_expr() function // in order for fold_opt_expr() to be able to avoid this check if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(a)) { let msg = "removing an expression is not supported in this position"; @@ -421,7 +421,7 @@ impl<'a> fold::Folder for StripUnconfigured<'a> { } fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { - // Don't configure interpolated AST (c.f. #34171). + // Don't configure interpolated AST (cf. issue #34171). // Interpolated AST will get configured once the surrounding tokens are parsed. mac } diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs index 1229db9b0e0..3b88767f0e8 100644 --- a/src/libsyntax/diagnostics/plugin.rs +++ b/src/libsyntax/diagnostics/plugin.rs @@ -141,6 +141,7 @@ pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt, ]) } +#[allow(deprecated)] pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt, span: Span, token_tree: &[TokenTree]) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index bb927b62a18..b807a65f6ae 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -670,7 +670,7 @@ pub enum SyntaxExtension { /// An attribute-like procedural macro that derives a builtin trait. BuiltinDerive(BuiltinDeriveFn), - /// A declarative macro, e.g. `macro m() {}`. + /// A declarative macro, e.g., `macro m() {}`. DeclMacro { expander: Box, def_info: Option<(ast::NodeId, Span)>, @@ -732,17 +732,12 @@ pub type NamedSyntaxExtension = (Name, SyntaxExtension); pub trait Resolver { fn next_node_id(&mut self) -> ast::NodeId; fn get_module_scope(&mut self, id: ast::NodeId) -> Mark; - fn eliminate_crate_var(&mut self, item: P) -> P; - fn is_whitelisted_legacy_custom_derive(&self, name: Name) -> bool; fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment, derives: &[Mark]); fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc); fn resolve_imports(&mut self); - // Resolves attribute and derive legacy macros from `#![plugin(..)]`. - fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec, allow_derive: bool) - -> Option; fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: Mark, force: bool) -> Result>, Determinacy>; @@ -770,16 +765,12 @@ pub struct DummyResolver; impl Resolver for DummyResolver { fn next_node_id(&mut self) -> ast::NodeId { ast::DUMMY_NODE_ID } fn get_module_scope(&mut self, _id: ast::NodeId) -> Mark { Mark::root() } - fn eliminate_crate_var(&mut self, item: P) -> P { item } - fn is_whitelisted_legacy_custom_derive(&self, _name: Name) -> bool { false } fn visit_ast_fragment_with_placeholders(&mut self, _invoc: Mark, _fragment: &AstFragment, _derives: &[Mark]) {} fn add_builtin(&mut self, _ident: ast::Ident, _ext: Lrc) {} fn resolve_imports(&mut self) {} - fn find_legacy_attr_invoc(&mut self, _attrs: &mut Vec, _allow_derive: bool) - -> Option { None } fn resolve_macro_invocation(&mut self, _invoc: &Invocation, _invoc_id: Mark, _force: bool) -> Result>, Determinacy> { Err(Determinacy::Determined) @@ -915,7 +906,7 @@ impl<'a> ExtCtxt<'a> { /// `span_err` should be strongly preferred where-ever possible: /// this should *only* be used when: /// - /// - continuing has a high risk of flow-on errors (e.g. errors in + /// - continuing has a high risk of flow-on errors (e.g., errors in /// declaring a macro would cause all uses of that macro to /// complain about "undefined macro"), or /// - there is literally nothing else that can be done (however, @@ -1002,7 +993,7 @@ pub fn expr_to_spanned_string<'a>( expr }); - // we want to be able to handle e.g. `concat!("foo", "bar")` + // we want to be able to handle e.g., `concat!("foo", "bar")` let expr = cx.expander().fold_expr(expr); Err(match expr.node { ast::ExprKind::Lit(ref l) => match l.node { diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index cacec867cf1..5770f6bb8a2 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -318,9 +318,13 @@ impl<'a> AstBuilder for ExtCtxt<'a> { args: Vec, bindings: Vec ) -> ast::Path { + assert!(!idents.is_empty()); + let add_root = global && !idents[0].is_path_segment_keyword(); + let mut segments = Vec::with_capacity(idents.len() + add_root as usize); + if add_root { + segments.push(ast::PathSegment::path_root(span)); + } let last_ident = idents.pop().unwrap(); - let mut segments: Vec = vec![]; - segments.extend(idents.into_iter().map(|ident| { ast::PathSegment::from_ident(ident.with_span_pos(span)) })); @@ -334,13 +338,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { id: ast::DUMMY_NODE_ID, args, }); - let mut path = ast::Path { span, segments }; - if global { - if let Some(seg) = path.make_root() { - path.segments.insert(0, seg); - } - } - path + ast::Path { span, segments } } /// Constructs a qualified path. @@ -625,7 +623,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.expr_path(self.path_ident(span, id)) } fn expr_self(&self, span: Span) -> P { - self.expr_ident(span, keywords::SelfValue.ident()) + self.expr_ident(span, keywords::SelfLower.ident()) } fn expr_binary(&self, sp: Span, op: ast::BinOpKind, diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 68a96293891..57ccc3e9817 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ast::{self, Block, Ident, NodeId, PatKind, Path}; +use ast::{self, Block, Ident, LitKind, NodeId, PatKind, Path}; use ast::{MacStmtStyle, StmtKind, ItemKind}; use attr::{self, HasAttrs}; use source_map::{ExpnInfo, MacroBang, MacroAttribute, dummy_spanned, respan}; @@ -34,8 +34,8 @@ use tokenstream::{TokenStream, TokenTree}; use visit::{self, Visitor}; use rustc_data_structures::fx::FxHashMap; -use std::fs::File; -use std::io::Read; +use std::fs; +use std::io::ErrorKind; use std::{iter, mem}; use std::rc::Rc; use std::path::PathBuf; @@ -203,10 +203,7 @@ fn macro_bang_format(path: &ast::Path) -> ExpnFormat { if i != 0 { path_str.push_str("::"); } - - if segment.ident.name != keywords::CrateRoot.name() && - segment.ident.name != keywords::DollarCrate.name() - { + if segment.ident.name != keywords::PathRoot.name() { path_str.push_str(&segment.ident.as_str()) } } @@ -622,9 +619,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> { fn extract_proc_macro_attr_input(&self, tokens: TokenStream, span: Span) -> TokenStream { let mut trees = tokens.trees(); match trees.next() { - Some(TokenTree::Delimited(_, delim)) => { + Some(TokenTree::Delimited(_, _, tts)) => { if trees.next().is_none() { - return delim.tts.into() + return tts.into() } } Some(TokenTree::Token(..)) => {} @@ -1134,12 +1131,6 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { let (mut attr, mut traits, mut after_derive) = (None, Vec::new(), false); item = item.map_attrs(|mut attrs| { - if let Some(legacy_attr_invoc) = self.cx.resolver.find_legacy_attr_invoc(&mut attrs, - true) { - attr = Some(legacy_attr_invoc); - return attrs; - } - attr = self.find_attr_invoc(&mut attrs, &mut after_derive); traits = collect_derives(&mut self.cx, &mut attrs); attrs @@ -1156,12 +1147,6 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { let (mut attr, mut after_derive) = (None, false); item = item.map_attrs(|mut attrs| { - if let Some(legacy_attr_invoc) = self.cx.resolver.find_legacy_attr_invoc(&mut attrs, - false) { - attr = Some(legacy_attr_invoc); - return attrs; - } - attr = self.find_attr_invoc(&mut attrs, &mut after_derive); attrs }); @@ -1363,7 +1348,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { module.mod_path.push(item.ident); // Detect if this is an inline module (`mod m { ... }` as opposed to `mod m;`). - // In the non-inline case, `inner` is never the dummy span (c.f. `parse_item_mod`). + // In the non-inline case, `inner` is never the dummy span (cf. `parse_item_mod`). // Thus, if `inner` is the dummy span, we know the module is inline. let inline_module = item.span.contains(inner) || inner.is_dummy(); @@ -1519,20 +1504,8 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { return noop_fold_attribute(at, self); } - let mut buf = vec![]; let filename = self.cx.root_path.join(file.to_string()); - - match File::open(&filename).and_then(|mut f| f.read_to_end(&mut buf)) { - Ok(..) => {} - Err(e) => { - self.cx.span_err(at.span, - &format!("couldn't read {}: {}", - filename.display(), - e)); - } - } - - match String::from_utf8(buf) { + match fs::read_to_string(&filename) { Ok(src) => { let src_interned = Symbol::intern(&src); @@ -1542,25 +1515,82 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { let include_info = vec![ dummy_spanned(ast::NestedMetaItemKind::MetaItem( - attr::mk_name_value_item_str(Ident::from_str("file"), - dummy_spanned(file)))), + attr::mk_name_value_item_str( + Ident::from_str("file"), + dummy_spanned(file), + ), + )), dummy_spanned(ast::NestedMetaItemKind::MetaItem( - attr::mk_name_value_item_str(Ident::from_str("contents"), - dummy_spanned(src_interned)))), + attr::mk_name_value_item_str( + Ident::from_str("contents"), + dummy_spanned(src_interned), + ), + )), ]; let include_ident = Ident::from_str("include"); let item = attr::mk_list_item(DUMMY_SP, include_ident, include_info); items.push(dummy_spanned(ast::NestedMetaItemKind::MetaItem(item))); } - Err(_) => { - self.cx.span_err(at.span, - &format!("{} wasn't a utf-8 file", - filename.display())); + Err(e) => { + let lit = it + .meta_item() + .and_then(|item| item.name_value_literal()) + .unwrap(); + + if e.kind() == ErrorKind::InvalidData { + self.cx + .struct_span_err( + lit.span, + &format!("{} wasn't a utf-8 file", filename.display()), + ) + .span_label(lit.span, "contains invalid utf-8") + .emit(); + } else { + let mut err = self.cx.struct_span_err( + lit.span, + &format!("couldn't read {}: {}", filename.display(), e), + ); + err.span_label(lit.span, "couldn't read file"); + + if e.kind() == ErrorKind::NotFound { + err.help("external doc paths are relative to the crate root"); + } + + err.emit(); + } } } } else { - items.push(noop_fold_meta_list_item(it, self)); + let mut err = self.cx.struct_span_err( + it.span, + &format!("expected path to external documentation"), + ); + + // Check if the user erroneously used `doc(include(...))` syntax. + let literal = it.meta_item_list().and_then(|list| { + if list.len() == 1 { + list[0].literal().map(|literal| &literal.node) + } else { + None + } + }); + + let (path, applicability) = match &literal { + Some(LitKind::Str(path, ..)) => { + (path.to_string(), Applicability::MachineApplicable) + } + _ => (String::from(""), Applicability::HasPlaceholders), + }; + + err.span_suggestion_with_applicability( + it.span, + "provide a file path with `=`", + format!("include = \"{}\"", path), + applicability, + ); + + err.emit(); } } @@ -1623,7 +1653,6 @@ impl<'feat> ExpansionConfig<'feat> { } feature_tests! { - fn enable_quotes = quote, fn enable_asm = asm, fn enable_custom_test_frameworks = custom_test_frameworks, fn enable_global_asm = global_asm, @@ -1631,7 +1660,6 @@ impl<'feat> ExpansionConfig<'feat> { fn enable_concat_idents = concat_idents, fn enable_trace_macros = trace_macros, fn enable_allow_internal_unstable = allow_internal_unstable, - fn enable_custom_derive = custom_derive, fn enable_format_args_nl = format_args_nl, fn macros_in_extern_enabled = macros_in_extern, fn proc_macro_hygiene = proc_macro_hygiene, diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index 69ed318b049..5820b49ab62 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -36,7 +36,7 @@ pub mod rt { use symbol::Symbol; use ThinVec; - use tokenstream::{self, DelimSpan, TokenTree, TokenStream}; + use tokenstream::{DelimSpan, TokenTree, TokenStream}; pub use parse::new_parser_from_tts; pub use syntax_pos::{BytePos, Span, DUMMY_SP, FileName}; @@ -246,9 +246,9 @@ pub mod rt { inner.push(self.tokens.clone()); let delim_span = DelimSpan::from_single(self.span); - r.push(TokenTree::Delimited(delim_span, tokenstream::Delimited { - delim: token::Bracket, tts: TokenStream::concat(inner).into() - })); + r.push(TokenTree::Delimited( + delim_span, token::Bracket, TokenStream::new(inner).into() + )); r } } @@ -262,10 +262,9 @@ pub mod rt { impl ToTokens for () { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![TokenTree::Delimited(DelimSpan::dummy(), tokenstream::Delimited { - delim: token::Paren, - tts: TokenStream::empty().into(), - })] + vec![ + TokenTree::Delimited(DelimSpan::dummy(), token::Paren, TokenStream::empty().into()) + ] } } @@ -353,27 +352,27 @@ pub mod rt { impl<'a> ExtParseUtils for ExtCtxt<'a> { fn parse_item(&self, s: String) -> P { panictry!(parse::parse_item_from_source_str( - FileName::QuoteExpansion, + FileName::quote_expansion_source_code(&s), s, self.parse_sess())).expect("parse error") } fn parse_stmt(&self, s: String) -> ast::Stmt { panictry!(parse::parse_stmt_from_source_str( - FileName::QuoteExpansion, + FileName::quote_expansion_source_code(&s), s, self.parse_sess())).expect("parse error") } fn parse_expr(&self, s: String) -> P { panictry!(parse::parse_expr_from_source_str( - FileName::QuoteExpansion, + FileName::quote_expansion_source_code(&s), s, self.parse_sess())) } fn parse_tts(&self, s: String) -> Vec { - let source_name = FileName::QuoteExpansion; + let source_name = FileName::quote_expansion_source_code(&s); parse::parse_stream_from_source_str(source_name, s, self.parse_sess(), None) .into_trees().collect() } @@ -382,8 +381,6 @@ pub mod rt { // Replaces `Token::OpenDelim .. Token::CloseDelim` with `TokenTree::Delimited(..)`. pub fn unflatten(tts: Vec) -> Vec { - use tokenstream::Delimited; - let mut results = Vec::new(); let mut result = Vec::new(); let mut open_span = DUMMY_SP; @@ -395,10 +392,11 @@ pub fn unflatten(tts: Vec) -> Vec { } TokenTree::Token(span, token::CloseDelim(delim)) => { let delim_span = DelimSpan::from_pair(open_span, span); - let tree = TokenTree::Delimited(delim_span, Delimited { + let tree = TokenTree::Delimited( + delim_span, delim, - tts: result.into_iter().map(TokenStream::from).collect::().into(), - }); + result.into_iter().map(TokenStream::from).collect::().into(), + ); result = results.pop().unwrap(); result.push(tree); } @@ -758,10 +756,10 @@ fn statements_mk_tt(cx: &ExtCtxt, tt: &TokenTree, quoted: bool) -> Vec { - let mut stmts = statements_mk_tt(cx, &delimed.open_tt(span.open), false); - stmts.extend(statements_mk_tts(cx, delimed.stream())); - stmts.extend(statements_mk_tt(cx, &delimed.close_tt(span.close), false)); + TokenTree::Delimited(span, delim, ref tts) => { + let mut stmts = statements_mk_tt(cx, &TokenTree::open_tt(span.open, delim), false); + stmts.extend(statements_mk_tts(cx, tts.stream())); + stmts.extend(statements_mk_tt(cx, &TokenTree::close_tt(span.close, delim), false)); stmts } } diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index e1ba8897a47..ec27ceeb74c 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -21,8 +21,8 @@ use smallvec::SmallVec; use symbol::Symbol; use tokenstream; -use std::fs::File; -use std::io::prelude::*; +use std::fs; +use std::io::ErrorKind; use std::path::PathBuf; use rustc_data_structures::sync::Lrc; @@ -137,18 +137,7 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenT None => return DummyResult::expr(sp) }; let file = res_rel_file(cx, sp, file); - let mut bytes = Vec::new(); - match File::open(&file).and_then(|mut f| f.read_to_end(&mut bytes)) { - Ok(..) => {} - Err(e) => { - cx.span_err(sp, - &format!("couldn't read {}: {}", - file.display(), - e)); - return DummyResult::expr(sp); - } - }; - match String::from_utf8(bytes) { + match fs::read_to_string(&file) { Ok(src) => { let interned_src = Symbol::intern(&src); @@ -157,11 +146,13 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenT cx.source_map().new_source_file(file.into(), src); base::MacEager::expr(cx.expr_str(sp, interned_src)) + }, + Err(ref e) if e.kind() == ErrorKind::InvalidData => { + cx.span_err(sp, &format!("{} wasn't a utf-8 file", file.display())); + DummyResult::expr(sp) } - Err(_) => { - cx.span_err(sp, - &format!("{} wasn't a utf-8 file", - file.display())); + Err(e) => { + cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e)); DummyResult::expr(sp) } } @@ -174,19 +165,23 @@ pub fn expand_include_bytes(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::Toke None => return DummyResult::expr(sp) }; let file = res_rel_file(cx, sp, file); - let mut bytes = Vec::new(); - match File::open(&file).and_then(|mut f| f.read_to_end(&mut bytes)) { - Err(e) => { - cx.span_err(sp, - &format!("couldn't read {}: {}", file.display(), e)); - DummyResult::expr(sp) - } - Ok(..) => { - // Add this input file to the code map to make it available as - // dependency information, but don't enter it's contents - cx.source_map().new_source_file(file.into(), String::new()); + match fs::read(&file) { + Ok(bytes) => { + // Add the contents to the source map if it contains UTF-8. + let (contents, bytes) = match String::from_utf8(bytes) { + Ok(s) => { + let bytes = s.as_bytes().to_owned(); + (s, bytes) + }, + Err(e) => (String::new(), e.into_bytes()), + }; + cx.source_map().new_source_file(file.into(), contents); base::MacEager::expr(cx.expr_lit(sp, ast::LitKind::ByteStr(Lrc::new(bytes)))) + }, + Err(e) => { + cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e)); + DummyResult::expr(sp) } } } @@ -201,6 +196,7 @@ fn res_rel_file(cx: &mut ExtCtxt, sp: syntax_pos::Span, arg: String) -> PathBuf let callsite = sp.source_callsite(); let mut path = match cx.source_map().span_to_unmapped_path(callsite) { FileName::Real(path) => path, + FileName::DocTest(path, _) => path, other => panic!("cannot resolve relative path in non-file source `{}`", other), }; path.pop(); diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 8fd9590a664..26348d5ec82 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -214,10 +214,10 @@ struct MatcherPos<'root, 'tt: 'root> { up: Option>, /// Specifically used to "unzip" token trees. By "unzip", we mean to unwrap the delimiters from - /// a delimited token tree (e.g. something wrapped in `(` `)`) or to get the contents of a doc + /// a delimited token tree (e.g., something wrapped in `(` `)`) or to get the contents of a doc /// comment... /// - /// When matching against matchers with nested delimited submatchers (e.g. `pat ( pat ( .. ) + /// When matching against matchers with nested delimited submatchers (e.g., `pat ( pat ( .. ) /// pat ) pat`), we need to keep track of the matchers we are descending into. This stack does /// that where the bottom of the stack is the outermost matcher. /// Also, throughout the comments, this "descent" is often referred to as "unzipping"... @@ -309,7 +309,7 @@ fn create_matches(len: usize) -> Box<[Rc]> { vec![] } else { let empty_matches = Rc::new(SmallVec::new()); - vec![empty_matches.clone(); len] + vec![empty_matches; len] }.into_boxed_slice() } @@ -373,7 +373,7 @@ fn nameize>( ms: &[TokenTree], mut res: I, ) -> NamedParseResult { - // Recursively descend into each type of matcher (e.g. sequences, delimited, metavars) and make + // Recursively descend into each type of matcher (e.g., sequences, delimited, metavars) and make // sure that each metavar has _exactly one_ binding. If a metavar does not have exactly one // binding, then there is an error. If it does, then we insert the binding into the // `NamedParseResult`. @@ -895,7 +895,7 @@ fn may_begin_with(name: &str, token: &Token) -> bool { /// /// - `p`: the "black-box" parser to use /// - `sp`: the `Span` we want to parse -/// - `name`: the name of the metavar _matcher_ we want to match (e.g. `tt`, `ident`, `block`, +/// - `name`: the name of the metavar _matcher_ we want to match (e.g., `tt`, `ident`, `block`, /// etc...) /// /// # Returns diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index ff622b0c18f..30322ff523d 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -77,9 +77,9 @@ impl<'a> ParserAnyMacro<'a> { e })); - // We allow semicolons at the end of expressions -- e.g. the semicolon in + // We allow semicolons at the end of expressions -- e.g., the semicolon in // `macro_rules! m { () => { panic!(); } }` isn't parsed by `.parse_expr()`, - // but `m!()` is allowed in expression positions (c.f. issue #34706). + // but `m!()` is allowed in expression positions (cf. issue #34706). if kind == AstFragmentKind::Expr && parser.token == token::Semi { parser.bump(); } @@ -482,15 +482,15 @@ fn check_matcher(sess: &ParseSess, err == sess.span_diagnostic.err_count() } -// The FirstSets for a matcher is a mapping from subsequences in the +// `The FirstSets` for a matcher is a mapping from subsequences in the // matcher to the FIRST set for that subsequence. // // This mapping is partially precomputed via a backwards scan over the // token trees of the matcher, which provides a mapping from each -// repetition sequence to its FIRST set. +// repetition sequence to its *first* set. // -// (Hypothetically sequences should be uniquely identifiable via their -// spans, though perhaps that is false e.g. for macro-generated macros +// (Hypothetically, sequences should be uniquely identifiable via their +// spans, though perhaps that is false, e.g., for macro-generated macros // that do not try to inject artificial span information. My plan is // to try to catch such cases ahead of time and not include them in // the precomputed mapping.) diff --git a/src/libsyntax/ext/tt/quoted.rs b/src/libsyntax/ext/tt/quoted.rs index edc431be369..b142f09cdbc 100644 --- a/src/libsyntax/ext/tt/quoted.rs +++ b/src/libsyntax/ext/tt/quoted.rs @@ -93,9 +93,9 @@ pub enum TokenTree { Delimited(DelimSpan, Lrc), /// A kleene-style repetition sequence Sequence(DelimSpan, Lrc), - /// E.g. `$var` + /// e.g., `$var` MetaVar(Span, ast::Ident), - /// E.g. `$var:expr`. This is only used in the left hand side of MBE macros. + /// e.g., `$var:expr`. This is only used in the left hand side of MBE macros. MetaVarDecl( Span, ast::Ident, /* name to bind */ @@ -199,7 +199,7 @@ pub fn parse( let mut trees = input.trees().peekable(); while let Some(tree) = trees.next() { // Given the parsed tree, if there is a metavar and we are expecting matchers, actually - // parse out the matcher (i.e. in `$id:ident` this would parse the `:` and `ident`). + // parse out the matcher (i.e., in `$id:ident` this would parse the `:` and `ident`). let tree = parse_tree( tree, &mut trees, @@ -281,16 +281,16 @@ where tokenstream::TokenTree::Token(span, token::Dollar) => match trees.next() { // `tree` is followed by a delimited set of token trees. This indicates the beginning // of a repetition sequence in the macro (e.g. `$(pat)*`). - Some(tokenstream::TokenTree::Delimited(span, delimited)) => { + Some(tokenstream::TokenTree::Delimited(span, delim, tts)) => { // Must have `(` not `{` or `[` - if delimited.delim != token::Paren { - let tok = pprust::token_to_string(&token::OpenDelim(delimited.delim)); + if delim != token::Paren { + let tok = pprust::token_to_string(&token::OpenDelim(delim)); let msg = format!("expected `(`, found `{}`", tok); sess.span_diagnostic.span_err(span.entire(), &msg); } // Parse the contents of the sequence itself let sequence = parse( - delimited.tts.into(), + tts.into(), expect_matchers, sess, features, @@ -309,7 +309,7 @@ where edition, macro_node_id, ); - // Count the number of captured "names" (i.e. named metavars) + // Count the number of captured "names" (i.e., named metavars) let name_captures = macro_parser::count_names(&sequence); TokenTree::Sequence( span, @@ -352,14 +352,14 @@ where // `tree` is an arbitrary token. Keep it. tokenstream::TokenTree::Token(span, tok) => TokenTree::Token(span, tok), - // `tree` is the beginning of a delimited set of tokens (e.g. `(` or `{`). We need to + // `tree` is the beginning of a delimited set of tokens (e.g., `(` or `{`). We need to // descend into the delimited set and further parse it. - tokenstream::TokenTree::Delimited(span, delimited) => TokenTree::Delimited( + tokenstream::TokenTree::Delimited(span, delim, tts) => TokenTree::Delimited( span, Lrc::new(Delimited { - delim: delimited.delim, + delim: delim, tts: parse( - delimited.tts.into(), + tts.into(), expect_matchers, sess, features, @@ -444,7 +444,6 @@ where macro_node_id, ), Edition::Edition2018 => parse_sep_and_kleene_op_2018(input, span, sess, features, attrs), - _ => unimplemented!(), } } diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 3d897d17e0b..a63abd40495 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -17,7 +17,7 @@ use fold::noop_fold_tt; use parse::token::{self, Token, NtTT}; use smallvec::SmallVec; use syntax_pos::DUMMY_SP; -use tokenstream::{TokenStream, TokenTree, Delimited, DelimSpan}; +use tokenstream::{TokenStream, TokenTree, DelimSpan}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; @@ -103,12 +103,13 @@ pub fn transcribe(cx: &ExtCtxt, } Frame::Delimited { forest, span, .. } => { if result_stack.is_empty() { - return TokenStream::concat(result); + return TokenStream::new(result); } - let tree = TokenTree::Delimited(span, Delimited { - delim: forest.delim, - tts: TokenStream::concat(result).into(), - }); + let tree = TokenTree::Delimited( + span, + forest.delim, + TokenStream::new(result).into(), + ); result = result_stack.pop().unwrap(); result.push(tree.into()); } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index fac7ff2bf34..941a3a288da 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Feature gating +//! # Feature gating //! //! This module implements the gating necessary for preventing certain compiler //! features from being used by default. This module will crawl a pre-expanded @@ -53,8 +53,7 @@ macro_rules! declare_features { /// Represents active features that are currently being implemented or /// currently being considered for addition/removal. const ACTIVE_FEATURES: - &'static [(&'static str, &'static str, Option, - Option, fn(&mut Features, Span))] = + &[(&str, &str, Option, Option, fn(&mut Features, Span))] = &[$((stringify!($feature), $ver, $issue, $edition, set!($feature))),+]; /// A set of features to be used by later passes. @@ -106,7 +105,7 @@ macro_rules! declare_features { } } -// If you change this, please modify src/doc/unstable-book as well. +// If you change this, please modify `src/doc/unstable-book` as well. // // Don't ever remove anything from this list; set them to 'Removed'. // @@ -114,7 +113,7 @@ macro_rules! declare_features { // was set. This is most important for knowing when a particular feature became // stable (active). // -// NB: tools/tidy/src/features.rs parses this information directly out of the +// N.B., `tools/tidy/src/features.rs` parses this information directly out of the // source, so take care when modifying it. declare_features! ( @@ -153,66 +152,61 @@ declare_features! ( (active, panic_runtime, "1.10.0", Some(32837), None), (active, needs_panic_runtime, "1.10.0", Some(32837), None), - // OIBIT specific features + // Features specific to OIBIT (auto traits) (active, optin_builtin_traits, "1.0.0", Some(13231), None), - // Allows use of #[staged_api] + // Allows `#[staged_api]`. // // rustc internal (active, staged_api, "1.0.0", None, None), - // Allows using #![no_core] + // Allows `#![no_core]`. (active, no_core, "1.3.0", Some(29639), None), - // Allows using `box` in patterns; RFC 469 + // Allows the use of `box` in patterns (RFC 469). (active, box_patterns, "1.0.0", Some(29641), None), - // Allows using the unsafe_destructor_blind_to_params attribute; - // RFC 1238 + // Allows the use of the `unsafe_destructor_blind_to_params` attribute (RFC 1238). (active, dropck_parametricity, "1.3.0", Some(28498), None), - // Allows using the may_dangle attribute; RFC 1327 + // Allows using the `may_dangle` attribute (RFC 1327). (active, dropck_eyepatch, "1.10.0", Some(34761), None), - // Allows the use of custom attributes; RFC 572 + // Allows the use of custom attributes (RFC 572). (active, custom_attribute, "1.0.0", Some(29642), None), - // Allows the use of #[derive(Anything)] as sugar for - // #[derive_Anything]. - (active, custom_derive, "1.0.0", Some(29644), None), - - // Allows the use of rustc_* attributes; RFC 572 + // Allows the use of `rustc_*` attributes (RFC 572). (active, rustc_attrs, "1.0.0", Some(29642), None), - // Allows the use of non lexical lifetimes; RFC 2094 + // Allows the use of non lexical lifetimes (RFC 2094). (active, nll, "1.0.0", Some(43234), None), - // Allows the use of #[allow_internal_unstable]. This is an - // attribute on macro_rules! and can't use the attribute handling + // Allows the use of `#[allow_internal_unstable]`. This is an + // attribute on `macro_rules!` and can't use the attribute handling // below (it has to be checked before expansion possibly makes // macros disappear). // // rustc internal (active, allow_internal_unstable, "1.0.0", None, None), - // Allows the use of #[allow_internal_unsafe]. This is an - // attribute on macro_rules! and can't use the attribute handling + // Allows the use of `#[allow_internal_unsafe]`. This is an + // attribute on `macro_rules!` and can't use the attribute handling // below (it has to be checked before expansion possibly makes // macros disappear). // // rustc internal (active, allow_internal_unsafe, "1.0.0", None, None), - // #23121. Array patterns have some hazards yet. + // Allows the use of slice patterns (issue #23121). (active, slice_patterns, "1.0.0", Some(23121), None), - // Allows the definition of `const fn` functions with some advanced features. + // Allows the definition of `const` functions with some advanced features. (active, const_fn, "1.2.0", Some(24111), None), - // Allows let bindings and destructuring in `const fn` functions and constants. + // Allows let bindings and destructuring in `const` functions and constants. (active, const_let, "1.22.1", Some(48821), None), - // Allows accessing fields of unions inside const fn. + // Allows accessing fields of unions inside `const` functions. (active, const_fn_union, "1.27.0", Some(51909), None), // Allows casting raw pointers to `usize` during const eval. @@ -227,10 +221,10 @@ declare_features! ( // Allows comparing raw pointers during const eval. (active, const_compare_raw_pointers, "1.27.0", Some(53020), None), - // Allows panicking during const eval (produces compile-time errors) + // Allows panicking during const eval (producing compile-time errors). (active, const_panic, "1.30.0", Some(51999), None), - // Allows using #[prelude_import] on glob `use` items. + // Allows using `#[prelude_import]` on glob `use` items. // // rustc internal (active, prelude_import, "1.2.0", None, None), @@ -238,117 +232,121 @@ declare_features! ( // Allows default type parameters to influence type inference. (active, default_type_parameter_fallback, "1.3.0", Some(27336), None), - // Allows associated type defaults + // Allows associated type defaults. (active, associated_type_defaults, "1.2.0", Some(29661), None), - // Allows `repr(simd)`, and importing the various simd intrinsics + // Allows `repr(simd)` and importing the various simd intrinsics. (active, repr_simd, "1.4.0", Some(27731), None), - // Allows `extern "platform-intrinsic" { ... }` + // Allows `extern "platform-intrinsic" { ... }`. (active, platform_intrinsics, "1.4.0", Some(27731), None), - // Allows `#[unwind(..)]` + // Allows `#[unwind(..)]`. + // // rustc internal for rust runtime (active, unwind_attributes, "1.4.0", None, None), // Allows the use of `#[naked]` on functions. (active, naked_functions, "1.9.0", Some(32408), None), - // Allows `#[no_debug]` + // Allows `#[no_debug]`. (active, no_debug, "1.5.0", Some(29721), None), - // Allows `#[omit_gdb_pretty_printer_section]` + // Allows `#[omit_gdb_pretty_printer_section]`. // // rustc internal (active, omit_gdb_pretty_printer_section, "1.5.0", None, None), - // Allows cfg(target_vendor = "..."). + // Allows `cfg(target_vendor = "...")`. (active, cfg_target_vendor, "1.5.0", Some(29718), None), - // Allow attributes on expressions and non-item statements + // Allows attributes on expressions and non-item statements. (active, stmt_expr_attributes, "1.6.0", Some(15701), None), - // allow using type ascription in expressions + // Allows the use of type ascription in expressions. (active, type_ascription, "1.6.0", Some(23416), None), - // Allows cfg(target_thread_local) + // Allows `cfg(target_thread_local)`. (active, cfg_target_thread_local, "1.7.0", Some(29594), None), // rustc internal (active, abi_vectorcall, "1.7.0", None, None), - // X..Y patterns + // Allows `X..Y` patterns. (active, exclusive_range_pattern, "1.11.0", Some(37854), None), // impl specialization (RFC 1210) (active, specialization, "1.7.0", Some(31844), None), - // Allows cfg(target_has_atomic = "..."). + // Allows `cfg(target_has_atomic = "...")`. (active, cfg_target_has_atomic, "1.9.0", Some(32976), None), - // The `!` type. Does not imply exhaustive_patterns (below) any more. + // The `!` type. Does not imply 'exhaustive_patterns' (below) any more. (active, never_type, "1.13.0", Some(35121), None), - // Allows exhaustive pattern matching on types that contain uninhabited types + // Allows exhaustive pattern matching on types that contain uninhabited types. (active, exhaustive_patterns, "1.13.0", Some(51085), None), - // Allows untagged unions `union U { ... }` + // Allows untagged unions `union U { ... }`. (active, untagged_unions, "1.13.0", Some(32836), None), - // Used to identify the `compiler_builtins` crate - // rustc internal + // Used to identify the `compiler_builtins` crate. + // + // rustc internal. (active, compiler_builtins, "1.13.0", None, None), - // Allows #[link(..., cfg(..))] + // Allows `#[link(..., cfg(..))]`. (active, link_cfg, "1.14.0", Some(37406), None), - // `extern "ptx-*" fn()` + // Allows `extern "ptx-*" fn()`. (active, abi_ptx, "1.15.0", Some(38788), None), - // The `repr(i128)` annotation for enums + // The `repr(i128)` annotation for enums. (active, repr128, "1.16.0", Some(35118), None), - // The `unadjusted` ABI. Perma unstable. + // The `unadjusted` ABI; perma-unstable. + // // rustc internal (active, abi_unadjusted, "1.16.0", None, None), // Declarative macros 2.0 (`macro`). (active, decl_macro, "1.17.0", Some(39412), None), - // Allows #[link(kind="static-nobundle"...)] + // Allows `#[link(kind="static-nobundle"...)]`. (active, static_nobundle, "1.16.0", Some(37403), None), - // `extern "msp430-interrupt" fn()` + // Allows `extern "msp430-interrupt" fn()`. (active, abi_msp430_interrupt, "1.16.0", Some(38487), None), - // Used to identify crates that contain sanitizer runtimes + // Used to identify crates that contain sanitizer runtimes. + // // rustc internal (active, sanitizer_runtime, "1.17.0", None, None), - // Used to identify crates that contain the profiler runtime + // Used to identify crates that contain the profiler runtime. // // rustc internal (active, profiler_runtime, "1.18.0", None, None), - // `extern "x86-interrupt" fn()` + // Allows `extern "x86-interrupt" fn()`. (active, abi_x86_interrupt, "1.17.0", Some(40180), None), - // Allows the `try {...}` expression + // Allows the `try {...}` expression. (active, try_blocks, "1.29.0", Some(31436), None), - // Allows module-level inline assembly by way of global_asm!() + // Allows module-level inline assembly by way of `global_asm!()`. (active, global_asm, "1.18.0", Some(35119), None), - // Allows overlapping impls of marker traits + // Allows overlapping impls of marker traits. (active, overlapping_marker_traits, "1.18.0", Some(29864), None), - // Trait attribute to allow overlapping impls + // Trait attribute to allow overlapping impls. (active, marker_trait_attr, "1.30.0", Some(29864), None), // rustc internal (active, abi_thiscall, "1.19.0", None, None), - // Allows a test to fail without failing the whole suite + // Allows a test to fail without failing the whole suite. (active, allow_fail, "1.19.0", Some(46488), None), // Allows unsized tuple coercion. @@ -363,28 +361,28 @@ declare_features! ( // rustc internal (active, allocator_internals, "1.20.0", None, None), - // #[doc(cfg(...))] + // `#[doc(cfg(...))]` (active, doc_cfg, "1.21.0", Some(43781), None), - // #[doc(masked)] + // `#[doc(masked)]` (active, doc_masked, "1.21.0", Some(44027), None), - // #[doc(spotlight)] + // `#[doc(spotlight)]` (active, doc_spotlight, "1.22.0", Some(45040), None), - // #[doc(include="some-file")] + // `#[doc(include = "some-file")]` (active, external_doc, "1.22.0", Some(44732), None), - // Future-proofing enums/structs with #[non_exhaustive] attribute (RFC 2008) + // Future-proofing enums/structs with `#[non_exhaustive]` attribute (RFC 2008). (active, non_exhaustive, "1.22.0", Some(44109), None), - // `crate` as visibility modifier, synonymous to `pub(crate)` + // Adds `crate` as visibility modifier, synonymous with `pub(crate)`. (active, crate_visibility_modifier, "1.23.0", Some(53120), None), // extern types (active, extern_types, "1.23.0", Some(43467), None), - // Allows trait methods with arbitrary self types + // Allows trait methods with arbitrary self types. (active, arbitrary_self_types, "1.23.0", Some(44874), None), - // In-band lifetime bindings (e.g. `fn foo(x: &'a u8) -> &'a u8`) + // 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) @@ -393,25 +391,19 @@ declare_features! ( // `extern` in paths (active, extern_in_paths, "1.23.0", Some(55600), None), - // Infer static outlives requirements; RFC 2093 + // Infer static outlives requirements (RFC 2093). (active, infer_static_outlives_requirements, "1.26.0", Some(54185), None), - // Multiple patterns with `|` in `if let` and `while let` + // Multiple patterns with `|` in `if let` and `while let`. (active, if_while_or_patterns, "1.26.0", Some(48215), None), - // Allows `#[repr(packed)]` attribute on structs - (active, repr_packed, "1.26.0", Some(33158), None), - - // `use path as _;` and `extern crate c as _;` - (active, underscore_imports, "1.26.0", Some(48216), None), - - // Allows macro invocations in `extern {}` blocks + // Allows macro invocations in `extern {}` blocks. (active, macros_in_extern, "1.27.0", Some(49476), None), // `existential type` (active, existential_type, "1.28.0", Some(34511), None), - // unstable #[target_feature] directives + // unstable `#[target_feature]` directives (active, arm_target_feature, "1.27.0", Some(44839), None), (active, aarch64_target_feature, "1.27.0", Some(44839), None), (active, hexagon_target_feature, "1.27.0", Some(44839), None), @@ -422,69 +414,71 @@ declare_features! ( (active, sse4a_target_feature, "1.27.0", Some(44839), None), (active, tbm_target_feature, "1.27.0", Some(44839), None), (active, wasm_target_feature, "1.30.0", Some(44839), None), + (active, adx_target_feature, "1.32.0", Some(44839), None), + (active, cmpxchg16b_target_feature, "1.32.0", Some(44839), None), // Allows macro invocations on modules expressions and statements and // procedural macros to expand to non-items. (active, proc_macro_hygiene, "1.30.0", Some(54727), None), - // #[doc(alias = "...")] + // `#[doc(alias = "...")]` (active, doc_alias, "1.27.0", Some(50146), None), - // Allows irrefutable patterns in if-let and while-let statements (RFC 2086) + // Allows irrefutable patterns in `if let` and `while let` statements (RFC 2086). (active, irrefutable_let_patterns, "1.27.0", Some(44495), None), // inconsistent bounds in where clauses (active, trivial_bounds, "1.28.0", Some(48214), None), - // 'a: { break 'a; } + // `'a: { break 'a; }` (active, label_break_value, "1.28.0", Some(48594), None), - // Integer match exhaustiveness checking - (active, exhaustive_integer_patterns, "1.30.0", Some(50907), None), + // Exhaustive pattern matching on `usize` and `isize`. + (active, precise_pointer_size_matching, "1.32.0", Some(56354), None), - // #[doc(keyword = "...")] + // `#[doc(keyword = "...")]` (active, doc_keyword, "1.28.0", Some(51315), None), - // Allows async and await syntax + // Allows async and await syntax. (active, async_await, "1.28.0", Some(50547), None), - // #[alloc_error_handler] + // `#[alloc_error_handler]` (active, alloc_error_handler, "1.29.0", Some(51540), None), (active, abi_amdgpu_kernel, "1.29.0", Some(51575), None), - // Perma-unstable; added for testing E0705 + // Added for testing E0705; perma-unstable. (active, test_2018_feature, "1.31.0", Some(0), Some(Edition::Edition2018)), - // Support for arbitrary delimited token streams in non-macro attributes + // support for arbitrary delimited token streams in non-macro attributes (active, unrestricted_attribute_tokens, "1.30.0", Some(55208), None), - // Allows `use x::y;` to resolve through `self::x`, not just `::x` + // Allows `use x::y;` to resolve through `self::x`, not just `::x`. (active, uniform_paths, "1.30.0", Some(53130), None), - // Allows unsized rvalues at arguments and parameters + // Allows unsized rvalues at arguments and parameters. (active, unsized_locals, "1.30.0", Some(48055), None), - // #![test_runner] - // #[test_case] + // `#![test_runner]` + // `#[test_case]` (active, custom_test_frameworks, "1.30.0", Some(50297), None), - // Non-builtin attributes in inner attribute position + // non-builtin attributes in inner attribute position (active, custom_inner_attributes, "1.30.0", Some(54726), None), - // allow mixing of bind-by-move in patterns and references to + // 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. + // (aka NLL). Essentially this means you need to be using the + // 2018 edition or later. (active, bind_by_move_pattern_guards, "1.30.0", Some(15287), None), - // Allows `impl Trait` in bindings (`let`, `const`, `static`) + // Allows `impl Trait` in bindings (`let`, `const`, `static`). (active, impl_trait_in_bindings, "1.30.0", Some(34511), None), - // #[cfg_attr(predicate, multiple, attributes, here)] + // `#[cfg_attr(predicate, multiple, attributes, here)]` (active, cfg_attr_multi, "1.31.0", Some(54881), None), - // Allows `const _: TYPE = VALUE` + // Allows `const _: TYPE = VALUE`. (active, underscore_const_names, "1.31.0", Some(54912), None), // `reason = ` in lint attributes and `expect` lint attribute @@ -492,12 +486,15 @@ declare_features! ( // `extern crate self as foo;` puts local crate root into extern prelude under name `foo`. (active, extern_crate_self, "1.31.0", Some(56409), None), + + // Allows calling `const unsafe fn` inside `unsafe` blocks in `const fn` functions. + (active, min_const_unsafe_fn, "1.31.0", Some(55607), None), ); declare_features! ( (removed, import_shadowing, "1.0.0", None, None, None), (removed, managed_boxes, "1.0.0", None, None, None), - // Allows use of unary negate on unsigned integers, e.g. -e for e: u8 + // Allows use of unary negate on unsigned integers, e.g., -e for e: u8 (removed, negate_unsigned, "1.0.0", Some(29645), None, None), (removed, reflect, "1.0.0", Some(27749), None, None), // A way to temporarily opt out of opt in copy. This will *never* be accepted. @@ -528,6 +525,9 @@ declare_features! ( Some("subsumed by `#![feature(proc_macro_hygiene)]`")), (removed, panic_implementation, "1.28.0", Some(44489), None, Some("subsumed by `#[panic_handler]`")), + // Allows the use of `#[derive(Anything)]` as sugar for `#[derive_Anything]`. + (removed, custom_derive, "1.0.0", Some(29644), None, + Some("subsumed by `#[proc_macro_derive]`")), ); declare_features! ( @@ -536,9 +536,9 @@ declare_features! ( declare_features! ( (accepted, associated_types, "1.0.0", None, None), - // allow overloading augmented assignment operations like `a += b` + // Allows overloading augmented assignment operations like `a += b`. (accepted, augmented_assignments, "1.8.0", Some(28235), None), - // allow empty structs and enum variants with braces + // Allows empty structs and enum variants with braces. (accepted, braced_empty_structs, "1.8.0", Some(29720), None), // Allows indexing into constant arrays. (accepted, const_indexing, "1.26.0", Some(29947), None), @@ -549,69 +549,68 @@ declare_features! ( // to bootstrap fix for #5723. (accepted, issue_5723_bootstrap, "1.0.0", None, None), (accepted, macro_rules, "1.0.0", None, None), - // Allows using #![no_std] + // Allows using `#![no_std]`. (accepted, no_std, "1.6.0", None, None), (accepted, slicing_syntax, "1.0.0", None, None), (accepted, struct_variant, "1.0.0", None, None), // These are used to test this portion of the compiler, they don't actually - // mean anything + // mean anything. (accepted, test_accepted_feature, "1.0.0", None, None), (accepted, tuple_indexing, "1.0.0", None, None), // Allows macros to appear in the type position. (accepted, type_macros, "1.13.0", Some(27245), None), (accepted, while_let, "1.0.0", None, None), - // Allows `#[deprecated]` attribute + // Allows `#[deprecated]` attribute. (accepted, deprecated, "1.9.0", Some(29935), None), // `expr?` (accepted, question_mark, "1.13.0", Some(31436), None), - // Allows `..` in tuple (struct) patterns + // Allows `..` in tuple (struct) patterns. (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627), None), (accepted, item_like_imports, "1.15.0", Some(35120), None), // Allows using `Self` and associated types in struct expressions and patterns. (accepted, more_struct_aliases, "1.16.0", Some(37544), None), - // elide `'static` lifetimes in `static`s and `const`s + // elide `'static` lifetimes in `static`s and `const`s. (accepted, static_in_const, "1.17.0", Some(35897), None), // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions. (accepted, field_init_shorthand, "1.17.0", Some(37340), None), // Allows the definition recursive static items. (accepted, static_recursion, "1.17.0", Some(29719), None), - // pub(restricted) visibilities (RFC 1422) + // `pub(restricted)` visibilities (RFC 1422) (accepted, pub_restricted, "1.18.0", Some(32409), None), - // The #![windows_subsystem] attribute + // `#![windows_subsystem]` (accepted, windows_subsystem, "1.18.0", Some(37499), None), // Allows `break {expr}` with a value inside `loop`s. (accepted, loop_break_value, "1.19.0", Some(37339), None), // Permits numeric fields in struct expressions and patterns. (accepted, relaxed_adts, "1.19.0", Some(35626), None), - // Coerces non capturing closures to function pointers + // Coerces non capturing closures to function pointers. (accepted, closure_to_fn_coercion, "1.19.0", Some(39817), None), // Allows attributes on struct literal fields. (accepted, struct_field_attributes, "1.20.0", Some(38814), None), - // Allows the definition of associated constants in `trait` or `impl` - // blocks. + // Allows the definition of associated constants in `trait` or `impl` blocks. (accepted, associated_consts, "1.20.0", Some(29646), None), - // Usage of the `compile_error!` macro + // Usage of the `compile_error!` macro. (accepted, compile_error, "1.20.0", Some(40872), None), // See rust-lang/rfcs#1414. Allows code like `let x: &'static u32 = &42` to work. (accepted, rvalue_static_promotion, "1.21.0", Some(38865), None), - // Allow Drop types in constants (RFC 1440) + // Allows `Drop` types in constants (RFC 1440). (accepted, drop_types_in_const, "1.22.0", Some(33156), None), // Allows the sysV64 ABI to be specified on all platforms - // instead of just the platforms on which it is the C ABI + // instead of just the platforms on which it is the C ABI. (accepted, abi_sysv64, "1.24.0", Some(36167), None), - // Allows `repr(align(16))` struct attribute (RFC 1358) + // Allows `repr(align(16))` struct attribute (RFC 1358). (accepted, repr_align, "1.25.0", Some(33626), None), - // allow '|' at beginning of match arms (RFC 1925) + // Allows '|' at beginning of match arms (RFC 1925). (accepted, match_beginning_vert, "1.25.0", Some(44101), None), // Nested groups in `use` (RFC 2128) (accepted, use_nested_groups, "1.25.0", Some(44494), None), - // a..=b and ..=b + // `a..=b` and `..=b` (accepted, inclusive_range_syntax, "1.26.0", Some(28237), None), - // allow `..=` in patterns (RFC 1192) + // Allows `..=` in patterns (RFC 1192). (accepted, dotdoteq_in_patterns, "1.26.0", Some(28237), None), // Termination trait in main (RFC 1937) (accepted, termination_trait, "1.26.0", Some(43301), None), - // Copy/Clone closures (RFC 2132) + // `Copy`/`Clone` closures (RFC 2132). (accepted, clone_closures, "1.26.0", Some(44490), None), (accepted, copy_closures, "1.26.0", Some(44490), None), // Allows `impl Trait` in function arguments. @@ -622,73 +621,79 @@ declare_features! ( (accepted, i128_type, "1.26.0", Some(35118), None), // Default match binding modes (RFC 2005) (accepted, match_default_bindings, "1.26.0", Some(42640), None), - // allow `'_` placeholder lifetimes + // Allows `'_` placeholder lifetimes. (accepted, underscore_lifetimes, "1.26.0", Some(44524), None), - // Allows attributes on lifetime/type formal parameters in generics (RFC 1327) + // Allows attributes on lifetime/type formal parameters in generics (RFC 1327). (accepted, generic_param_attrs, "1.27.0", Some(48848), None), - // Allows cfg(target_feature = "..."). + // Allows `cfg(target_feature = "...")`. (accepted, cfg_target_feature, "1.27.0", Some(29717), None), - // Allows #[target_feature(...)] + // Allows `#[target_feature(...)]`. (accepted, target_feature, "1.27.0", None, None), // Trait object syntax with `dyn` prefix (accepted, dyn_trait, "1.27.0", Some(44662), None), - // allow `#[must_use]` on functions; and, must-use operators (RFC 1940) + // Allows `#[must_use]` on functions, and introduces must-use operators (RFC 1940). (accepted, fn_must_use, "1.27.0", Some(43302), None), - // Allows use of the :lifetime macro fragment specifier + // Allows use of the `:lifetime` macro fragment specifier. (accepted, macro_lifetime_matcher, "1.27.0", Some(34303), None), // Termination trait in tests (RFC 1937) (accepted, termination_trait_test, "1.27.0", Some(48854), None), - // The #[global_allocator] attribute + // The `#[global_allocator]` attribute (accepted, global_allocator, "1.28.0", Some(27389), None), - // Allows `#[repr(transparent)]` attribute on newtype structs + // Allows `#[repr(transparent)]` attribute on newtype structs. (accepted, repr_transparent, "1.28.0", Some(43036), None), - // Defining procedural macros in `proc-macro` crates + // Procedural macros in `proc-macro` crates (accepted, proc_macro, "1.29.0", Some(38356), None), // `foo.rs` as an alternative to `foo/mod.rs` (accepted, non_modrs_mods, "1.30.0", Some(44660), None), - // Allows use of the :vis macro fragment specifier + // Allows use of the `:vis` macro fragment specifier (accepted, macro_vis_matcher, "1.30.0", Some(41022), None), // Allows importing and reexporting macros with `use`, // enables macro modularization in general. (accepted, use_extern_macros, "1.30.0", Some(35896), None), - // Allows keywords to be escaped for use as identifiers + // Allows keywords to be escaped for use as identifiers. (accepted, raw_identifiers, "1.30.0", Some(48589), None), - // Attributes scoped to tools + // Attributes scoped to tools. (accepted, tool_attributes, "1.30.0", Some(44690), None), - // Allows multi-segment paths in attributes and derives + // Allows multi-segment paths in attributes and derives. (accepted, proc_macro_path_invoc, "1.30.0", Some(38356), None), // Allows all literals in attribute lists and values of key-value pairs. (accepted, attr_literals, "1.30.0", Some(34981), None), - // Infer outlives requirements; RFC 2093 + // Infer outlives requirements (RFC 2093). (accepted, infer_outlives_requirements, "1.30.0", Some(44493), None), (accepted, panic_handler, "1.30.0", Some(44489), None), - // Used to preserve symbols (see llvm.used) + // 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 + // 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 + // Access to crate names passed via `--extern` through prelude. (accepted, extern_prelude, "1.30.0", Some(44660), None), // Parentheses in patterns (accepted, pattern_parentheses, "1.31.0", Some(51087), None), - // Allows the definition of `const fn` functions + // Allows the definition of `const fn` functions. (accepted, min_const_fn, "1.31.0", Some(53555), None), // Scoped lints (accepted, tool_lints, "1.31.0", Some(44690), None), - // impl Iterator for &mut Iterator - // impl Debug for Foo<'_> + // `impl Iterator for &mut Iterator` + // `impl Debug for Foo<'_>` (accepted, impl_header_lifetime_elision, "1.31.0", Some(15872), None), - // `extern crate foo as bar;` puts `bar` into extern prelude + // `extern crate foo as bar;` puts `bar` into extern prelude. (accepted, extern_crate_item_prelude, "1.31.0", Some(55599), None), - // Allows use of the :literal macro fragment specifier (RFC 1576) - (accepted, macro_literal_matcher, "1.31.0", Some(35625), None), - // Use `?` as the Kleene "at most one" operator + // Allows use of the `:literal` macro fragment specifier (RFC 1576). + (accepted, macro_literal_matcher, "1.32.0", Some(35625), None), + // Use `?` as the Kleene "at most one" operator. (accepted, macro_at_most_once_rep, "1.32.0", Some(48075), None), // `Self` struct constructor (RFC 2302) (accepted, self_struct_ctor, "1.32.0", Some(51994), None), // `Self` in type definitions (RFC 2300) (accepted, self_in_typedefs, "1.32.0", Some(49303), None), + // Integer match exhaustiveness checking (RFC 2591) + (accepted, exhaustive_integer_patterns, "1.33.0", Some(50907), None), + // `use path as _;` and `extern crate c as _;` + (accepted, underscore_imports, "1.33.0", Some(48216), None), + // Allows `#[repr(packed(N))]` attribute on structs. + (accepted, repr_packed, "1.33.0", Some(33158), None), ); // If you change this, please modify `src/doc/unstable-book` as well. You must @@ -769,7 +774,7 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool { } // Attributes that have a special meaning to rustc or rustdoc -pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGate)] = &[ +pub const BUILTIN_ATTRIBUTES: &[(&str, AttributeType, AttributeGate)] = &[ // Normal attributes ("warn", Normal, Ungated), @@ -1273,7 +1278,7 @@ impl<'a> Context<'a> { if attr.path == &**n { // Plugins can't gate attributes, so we don't check for it // unlike the code above; we only use this loop to - // short-circuit to avoid the checks below + // short-circuit to avoid the checks below. debug!("check_attribute: {:?} is registered by a plugin, {:?}", attr.path, ty); return; } @@ -1283,13 +1288,10 @@ impl<'a> Context<'a> { "unless otherwise specified, attributes \ with the prefix `rustc_` \ are reserved for internal compiler diagnostics"); - } else if name.starts_with("derive_") { - gate_feature!(self, custom_derive, attr.span, EXPLAIN_DERIVE_UNDERSCORE); } else if !attr::is_known(attr) { - // Only run the custom attribute lint during regular - // feature gate checking. Macro gating runs - // before the plugin attributes are registered - // so we skip this then + // Only run the custom attribute lint during regular feature gate + // checking. Macro gating runs before the plugin attributes are + // registered, so we skip this in that case. if !is_macro { let msg = format!("The attribute `{}` is currently unknown to the compiler and \ may have meaning added to it in the future", attr.path); @@ -1383,48 +1385,38 @@ fn leveled_feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue } -const EXPLAIN_BOX_SYNTAX: &'static str = +const EXPLAIN_BOX_SYNTAX: &str = "box expression syntax is experimental; you can call `Box::new` instead."; -pub const EXPLAIN_STMT_ATTR_SYNTAX: &'static str = +pub const EXPLAIN_STMT_ATTR_SYNTAX: &str = "attributes on expressions are experimental."; -pub const EXPLAIN_ASM: &'static str = +pub const EXPLAIN_ASM: &str = "inline assembly is not stable enough for use and is subject to change"; -pub const EXPLAIN_GLOBAL_ASM: &'static str = +pub const EXPLAIN_GLOBAL_ASM: &str = "`global_asm!` is not stable enough for use and is subject to change"; -pub const EXPLAIN_CUSTOM_TEST_FRAMEWORKS: &'static str = +pub const EXPLAIN_CUSTOM_TEST_FRAMEWORKS: &str = "custom test frameworks are an unstable feature"; -pub const EXPLAIN_LOG_SYNTAX: &'static str = +pub const EXPLAIN_LOG_SYNTAX: &str = "`log_syntax!` is not stable enough for use and is subject to change"; -pub const EXPLAIN_CONCAT_IDENTS: &'static str = +pub const EXPLAIN_CONCAT_IDENTS: &str = "`concat_idents` is not stable enough for use and is subject to change"; -pub const EXPLAIN_FORMAT_ARGS_NL: &'static str = +pub const EXPLAIN_FORMAT_ARGS_NL: &str = "`format_args_nl` is only for internal language use and is subject to change"; -pub const EXPLAIN_TRACE_MACROS: &'static str = +pub const EXPLAIN_TRACE_MACROS: &str = "`trace_macros` is not stable enough for use and is subject to change"; -pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &'static str = +pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &str = "allow_internal_unstable side-steps feature gating and stability checks"; -pub const EXPLAIN_ALLOW_INTERNAL_UNSAFE: &'static str = +pub const EXPLAIN_ALLOW_INTERNAL_UNSAFE: &str = "allow_internal_unsafe side-steps the unsafe_code lint"; -pub const EXPLAIN_CUSTOM_DERIVE: &'static str = - "`#[derive]` for custom traits is deprecated and will be removed in the future."; - -pub const EXPLAIN_DEPR_CUSTOM_DERIVE: &'static str = - "`#[derive]` for custom traits is deprecated and will be removed in the future. \ - Prefer using procedural macro custom derive."; - -pub const EXPLAIN_DERIVE_UNDERSCORE: &'static str = - "attributes of the form `#[derive_*]` are reserved for the compiler"; - -pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str = +pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &str = "unsized tuple coercion is not stable enough for use and is subject to change"; struct PostExpansionVisitor<'a> { @@ -1555,26 +1547,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } - fn visit_use_tree(&mut self, use_tree: &'a ast::UseTree, id: NodeId, _nested: bool) { - if let ast::UseTreeKind::Simple(Some(ident), ..) = use_tree.kind { - if ident.name == "_" { - gate_feature_post!(&self, underscore_imports, use_tree.span, - "renaming imports with `_` is unstable"); - } - } - - visit::walk_use_tree(self, use_tree, id); - } - fn visit_item(&mut self, i: &'a ast::Item) { match i.node { - ast::ItemKind::ExternCrate(_) => { - if i.ident.name == "_" { - gate_feature_post!(&self, underscore_imports, i.span, - "renaming extern crates with `_` is unstable"); - } - } - ast::ItemKind::Static(..) | ast::ItemKind::Const(_,_) => { if i.ident.name == "_" { @@ -1613,13 +1587,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, repr_simd, attr.span, "SIMD types are experimental and possibly buggy"); } - if let Some((name, _)) = item.name_value_literal() { - if name == "packed" { - gate_feature_post!(&self, repr_packed, attr.span, - "the `#[repr(packed(n))]` attribute \ - is experimental"); - } - } } } } @@ -1797,14 +1764,13 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { _node_id: NodeId) { match fn_kind { FnKind::ItemFn(_, header, _, _) => { - // check for const fn and async fn declarations + // Check for const fn and async fn declarations. if header.asyncness.is_async() { gate_feature_post!(&self, async_await, span, "async fn is unstable"); } - // stability of const fn methods are covered in - // visit_trait_item and visit_impl_item below; this is - // because default methods don't pass through this - // point. + // Stability of const fn methods are covered in + // `visit_trait_item` and `visit_impl_item` below; this is + // because default methods don't pass through this point. self.check_abi(header.abi, span); } @@ -1881,7 +1847,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { fn visit_path(&mut self, path: &'a ast::Path, _id: NodeId) { for segment in &path.segments { - // Identifiers we are going to check could come from a legacy macro (e.g. `#[test]`). + // Identifiers we are going to check could come from a legacy macro (e.g., `#[test]`). // For such macros identifiers must have empty context, because this context is // used during name resolution and produced names must be unhygienic for compatibility. // On the other hand, we need the actual non-empty context for feature gate checking @@ -1928,7 +1894,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], for &edition in ALL_EDITIONS { if edition <= crate_edition { // The `crate_edition` implies its respective umbrella feature-gate - // (i.e. `#![feature(rust_20XX_preview)]` isn't needed on edition 20XX). + // (i.e., `#![feature(rust_20XX_preview)]` isn't needed on edition 20XX). edition_enabled_features.insert(Symbol::intern(edition.feature_name()), edition); } } @@ -2088,7 +2054,7 @@ pub enum UnstableFeatures { impl UnstableFeatures { pub fn from_environment() -> UnstableFeatures { - // Whether this is a feature-staged build, i.e. on the beta or stable channel + // Whether this is a feature-staged build, i.e., on the beta or stable channel let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some(); // Whether we should enable unstable features for bootstrapping let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok(); diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 0e6e2f90693..ecb02452638 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -229,7 +229,7 @@ pub trait Folder : Sized { fn fold_mac(&mut self, _mac: Mac) -> Mac { panic!("fold_mac disabled by default"); - // NB: see note about macros above. + // N.B., see note about macros above. // if you really want a folder that // works on macros, use this // definition in your trait impl: @@ -605,12 +605,10 @@ pub fn noop_fold_tt(tt: TokenTree, fld: &mut T) -> TokenTree { match tt { TokenTree::Token(span, tok) => TokenTree::Token(fld.new_span(span), fld.fold_token(tok)), - TokenTree::Delimited(span, delimed) => TokenTree::Delimited( + TokenTree::Delimited(span, delim, tts) => TokenTree::Delimited( DelimSpan::from_pair(fld.new_span(span.open), fld.new_span(span.close)), - Delimited { - tts: fld.fold_tts(delimed.stream()).into(), - delim: delimed.delim, - } + delim, + fld.fold_tts(tts.stream()).into(), ), } } @@ -637,7 +635,7 @@ pub fn noop_fold_token(t: token::Token, fld: &mut T) -> token::Token /// apply folder to elements of interpolated nodes // -// NB: this can occur only when applying a fold to partially expanded code, where +// N.B., this can occur only when applying a fold to partially expanded code, where // parsed pieces have gotten implanted ito *other* macro invocations. This is relevant // for macro hygiene, but possibly not elsewhere. // diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index ca9c5ad7b60..1fa11a4d6c8 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -134,7 +134,7 @@ pub mod diagnostics { pub mod metadata; } -// NB: This module needs to be declared first so diagnostics are +// N.B., this module needs to be declared first so diagnostics are // registered before they are used. pub mod diagnostic_list; @@ -145,12 +145,6 @@ pub mod util { #[cfg(test)] pub mod parser_testing; pub mod move_map; - - mod rc_slice; - pub use self::rc_slice::RcSlice; - - mod rc_vec; - pub use self::rc_vec::RcVec; } pub mod json; @@ -173,7 +167,6 @@ pub mod parse; pub mod ptr; pub mod show_span; pub mod std_inject; -pub mod str; pub use syntax_pos::edition; pub use syntax_pos::symbol; pub mod test; diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index a240604bfe0..1bd0656846b 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -22,8 +22,8 @@ enum InnerAttributeParsePolicy<'a> { NotPermitted { reason: &'a str }, } -const DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG: &'static str = "an inner attribute is not \ - permitted in this context"; +const DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG: &str = "an inner attribute is not \ + permitted in this context"; impl<'a> Parser<'a> { /// Parse attributes that appear before an item @@ -170,7 +170,7 @@ impl<'a> Parser<'a> { token::CloseDelim(_) | token::Eof => self.unexpected()?, _ => self.parse_token_tree(), }; - TokenStream::concat(vec![eq.into(), tree.into()]) + TokenStream::new(vec![eq.into(), tree.into()]) } else { TokenStream::empty() }; diff --git a/src/libsyntax/parse/lexer/comments.rs b/src/libsyntax/parse/lexer/comments.rs index 172a48ddba2..d3039326c89 100644 --- a/src/libsyntax/parse/lexer/comments.rs +++ b/src/libsyntax/parse/lexer/comments.rs @@ -16,7 +16,6 @@ use syntax_pos::{BytePos, CharPos, Pos, FileName}; use parse::lexer::{is_block_doc_comment, is_pattern_whitespace}; use parse::lexer::{self, ParseSess, StringReader, TokenAndSpan}; use print::pprust; -use str::char_at; use std::io::Read; use std::usize; @@ -207,20 +206,14 @@ fn read_line_comments(rdr: &mut StringReader, /// Otherwise returns Some(k) where k is first char offset after that leading /// whitespace. Note k may be outside bounds of s. fn all_whitespace(s: &str, col: CharPos) -> Option { - let len = s.len(); - let mut col = col.to_usize(); - let mut cursor: usize = 0; - - while col > 0 && cursor < len { - let ch = char_at(s, cursor); + let mut idx = 0; + for (i, ch) in s.char_indices().take(col.to_usize()) { if !ch.is_whitespace() { return None; } - cursor += ch.len_utf8(); - col -= 1; + idx = i + ch.len_utf8(); } - - Some(cursor) + Some(idx) } fn trim_whitespace_prefix_and_push_line(lines: &mut Vec, s: String, col: CharPos) { @@ -228,7 +221,7 @@ fn trim_whitespace_prefix_and_push_line(lines: &mut Vec, s: String, col: let s1 = match all_whitespace(&s[..], col) { Some(col) => { if col < len { - (&s[col..len]).to_string() + s[col..len].to_string() } else { String::new() } @@ -247,20 +240,13 @@ fn read_block_comment(rdr: &mut StringReader, let mut lines: Vec = Vec::new(); // Count the number of chars since the start of the line by rescanning. - let mut src_index = rdr.src_index(rdr.source_file.line_begin_pos(rdr.pos)); + let src_index = rdr.src_index(rdr.source_file.line_begin_pos(rdr.pos)); let end_src_index = rdr.src_index(rdr.pos); assert!(src_index <= end_src_index, "src_index={}, end_src_index={}, line_begin_pos={}", src_index, end_src_index, rdr.source_file.line_begin_pos(rdr.pos).to_u32()); - let mut n = 0; - while src_index < end_src_index { - let c = char_at(&rdr.src, src_index); - src_index += c.len_utf8(); - n += 1; - } - - let col = CharPos(n); + let col = CharPos(rdr.src[src_index..end_src_index].chars().count()); rdr.bump(); rdr.bump(); diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index c90c62c13f9..4be54e5bacc 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -13,12 +13,12 @@ use syntax_pos::{self, BytePos, CharPos, Pos, Span, NO_EXPANSION}; use source_map::{SourceMap, FilePathMapping}; use errors::{Applicability, FatalError, Diagnostic, DiagnosticBuilder}; use parse::{token, ParseSess}; -use str::char_at; use symbol::{Symbol, keywords}; use core::unicode::property::Pattern_White_Space; use std::borrow::Cow; use std::char; +use std::iter; use std::mem::replace; use rustc_data_structures::sync::Lrc; @@ -459,45 +459,42 @@ impl<'a> StringReader<'a> { /// Converts CRLF to LF in the given string, raising an error on bare CR. fn translate_crlf<'b>(&self, start: BytePos, s: &'b str, errmsg: &'b str) -> Cow<'b, str> { - let mut i = 0; - while i < s.len() { - let ch = char_at(s, i); - let next = i + ch.len_utf8(); + let mut chars = s.char_indices().peekable(); + while let Some((i, ch)) = chars.next() { if ch == '\r' { - if next < s.len() && char_at(s, next) == '\n' { - return translate_crlf_(self, start, s, errmsg, i).into(); + if let Some((lf_idx, '\n')) = chars.peek() { + return translate_crlf_(self, start, s, *lf_idx, chars, errmsg).into(); } let pos = start + BytePos(i as u32); - let end_pos = start + BytePos(next as u32); + let end_pos = start + BytePos((i + ch.len_utf8()) as u32); self.err_span_(pos, end_pos, errmsg); } - i = next; } return s.into(); fn translate_crlf_(rdr: &StringReader, start: BytePos, s: &str, - errmsg: &str, - mut i: usize) + mut j: usize, + mut chars: iter::Peekable>, + errmsg: &str) -> String { let mut buf = String::with_capacity(s.len()); - let mut j = 0; - while i < s.len() { - let ch = char_at(s, i); - let next = i + ch.len_utf8(); + // Skip first CR + buf.push_str(&s[.. j - 1]); + while let Some((i, ch)) = chars.next() { if ch == '\r' { if j < i { buf.push_str(&s[j..i]); } + let next = i + ch.len_utf8(); j = next; - if next >= s.len() || char_at(s, next) != '\n' { + if chars.peek().map(|(_, ch)| *ch) != Some('\n') { let pos = start + BytePos(i as u32); let end_pos = start + BytePos(next as u32); rdr.err_span_(pos, end_pos, errmsg); } } - i = next; } if j < s.len() { buf.push_str(&s[j..]); @@ -1130,7 +1127,7 @@ impl<'a> StringReader<'a> { "expected at least one digit in exponent" ); if let Some(ch) = self.ch { - // check for e.g. Unicode minus '−' (Issue #49746) + // check for e.g., Unicode minus '−' (Issue #49746) if unicode_chars::check_for_substitution(self, ch, &mut err) { self.bump(); self.scan_digits(10, 10); @@ -1858,6 +1855,11 @@ fn ident_continue(c: Option) -> bool { (c > '\x7f' && c.is_xid_continue()) } +#[inline] +fn char_at(s: &str, byte: usize) -> char { + s[byte..].chars().next().unwrap() +} + #[cfg(test)] mod tests { use super::*; @@ -1898,7 +1900,7 @@ mod tests { sess: &'a ParseSess, teststr: String) -> StringReader<'a> { - let sf = sm.new_source_file(PathBuf::from("zebra.rs").into(), teststr); + let sf = sm.new_source_file(PathBuf::from(teststr.clone()).into(), teststr); StringReader::new(sess, sf, None) } diff --git a/src/libsyntax/parse/lexer/tokentrees.rs b/src/libsyntax/parse/lexer/tokentrees.rs index 8047ab01465..6f9dc247a78 100644 --- a/src/libsyntax/parse/lexer/tokentrees.rs +++ b/src/libsyntax/parse/lexer/tokentrees.rs @@ -11,7 +11,7 @@ use print::pprust::token_to_string; use parse::lexer::StringReader; use parse::{token, PResult}; -use tokenstream::{Delimited, DelimSpan, TokenStream, TokenTree}; +use tokenstream::{DelimSpan, TokenStream, TokenTree}; impl<'a> StringReader<'a> { // Parse a stream of tokens into a list of `TokenTree`s, up to an `Eof`. @@ -22,7 +22,7 @@ impl<'a> StringReader<'a> { tts.push(self.parse_token_tree()?); } - Ok(TokenStream::concat(tts)) + Ok(TokenStream::new(tts)) } // Parse a stream of tokens into a list of `TokenTree`s, up to a `CloseDelim`. @@ -30,14 +30,14 @@ impl<'a> StringReader<'a> { let mut tts = vec![]; loop { if let token::CloseDelim(..) = self.token { - return TokenStream::concat(tts); + return TokenStream::new(tts); } match self.parse_token_tree() { Ok(tree) => tts.push(tree), Err(mut e) => { e.emit(); - return TokenStream::concat(tts); + return TokenStream::new(tts); } } } @@ -97,7 +97,15 @@ impl<'a> StringReader<'a> { // Correct delimiter. token::CloseDelim(d) if d == delim => { let (open_brace, open_brace_span) = self.open_braces.pop().unwrap(); - self.matching_delim_spans.push((open_brace, open_brace_span, self.span)); + if self.open_braces.len() == 0 { + // Clear up these spans to avoid suggesting them as we've found + // properly matched delimiters so far for an entire block. + self.matching_delim_spans.clear(); + } else { + self.matching_delim_spans.push( + (open_brace, open_brace_span, self.span), + ); + } // Parse the close delimiter. self.real_token(); } @@ -155,10 +163,11 @@ impl<'a> StringReader<'a> { _ => {} } - Ok(TokenTree::Delimited(delim_span, Delimited { + Ok(TokenTree::Delimited( + delim_span, delim, - tts: tts.into(), - }).into()) + tts.into(), + ).into()) }, token::CloseDelim(_) => { // An unexpected closing delimiter (i.e., there is no diff --git a/src/libsyntax/parse/lexer/unicode_chars.rs b/src/libsyntax/parse/lexer/unicode_chars.rs index 03bf1b5a4e1..8a620c8067d 100644 --- a/src/libsyntax/parse/lexer/unicode_chars.rs +++ b/src/libsyntax/parse/lexer/unicode_chars.rs @@ -306,7 +306,7 @@ const UNICODE_ARRAY: &[(char, &str, char)] = &[ ('>', "Fullwidth Greater-Than Sign", '>'), ]; -const ASCII_ARRAY: &'static [(char, &'static str)] = &[ +const ASCII_ARRAY: &[(char, &str)] = &[ (' ', "Space"), ('_', "Underscore"), ('-', "Minus/Hyphen"), diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index ac972f20f94..200b1cecc03 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -15,11 +15,10 @@ use ast::{self, CrateConfig, NodeId}; use early_buffered_lints::{BufferedEarlyLint, BufferedEarlyLintId}; use source_map::{SourceMap, FilePathMapping}; use syntax_pos::{Span, SourceFile, FileName, MultiSpan}; -use errors::{Handler, ColorConfig, Diagnostic, DiagnosticBuilder}; +use errors::{FatalError, Level, Handler, ColorConfig, Diagnostic, DiagnosticBuilder}; use feature_gate::UnstableFeatures; use parse::parser::Parser; use ptr::P; -use str::char_at; use symbol::Symbol; use tokenstream::{TokenStream, TokenTree}; use diagnostics::plugin::ErrorMap; @@ -82,6 +81,7 @@ impl ParseSess { } } + #[inline] pub fn source_map(&self) -> &SourceMap { &self.source_map } @@ -193,6 +193,14 @@ pub fn new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path) -> Parser<'a> source_file_to_parser(sess, file_to_source_file(sess, path, None)) } +/// Create a new parser, returning buffered diagnostics if the file doesn't +/// exist or from lexing the initial token stream. +pub fn maybe_new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path) + -> Result, Vec> { + let file = try_file_to_source_file(sess, path, None).map_err(|db| vec![db])?; + maybe_source_file_to_parser(sess, file) +} + /// Given a session, a crate config, a path, and a span, add /// the file at the given path to the source_map, and return a parser. /// On an error, use the given span as the source of the problem. @@ -237,18 +245,31 @@ pub fn new_parser_from_tts(sess: &ParseSess, tts: Vec) -> Parser { // base abstractions +/// Given a session and a path and an optional span (for error reporting), +/// add the path to the session's source_map and return the new source_file or +/// error when a file can't be read. +fn try_file_to_source_file(sess: &ParseSess, path: &Path, spanopt: Option) + -> Result, Diagnostic> { + sess.source_map().load_file(path) + .map_err(|e| { + let msg = format!("couldn't read {}: {}", path.display(), e); + let mut diag = Diagnostic::new(Level::Fatal, &msg); + if let Some(sp) = spanopt { + diag.set_span(sp); + } + diag + }) +} + /// Given a session and a path and an optional span (for error reporting), /// add the path to the session's source_map and return the new source_file. fn file_to_source_file(sess: &ParseSess, path: &Path, spanopt: Option) -> Lrc { - match sess.source_map().load_file(path) { + match try_file_to_source_file(sess, path, spanopt) { Ok(source_file) => source_file, - Err(e) => { - let msg = format!("couldn't read {}: {}", path.display(), e); - match spanopt { - Some(sp) => sess.span_diagnostic.span_fatal(sp, &msg).raise(), - None => sess.span_diagnostic.fatal(&msg).raise() - } + Err(d) => { + DiagnosticBuilder::new_diagnostic(&sess.span_diagnostic, d).emit(); + FatalError.raise(); } } } @@ -436,9 +457,7 @@ fn raw_str_lit(lit: &str) -> String { // check if `s` looks like i32 or u1234 etc. fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool { - s.len() > 1 && - first_chars.contains(&char_at(s, 0)) && - s[1..].chars().all(|c| '0' <= c && c <= '9') + s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit()) } macro_rules! err { @@ -645,11 +664,11 @@ fn integer_lit(s: &str, suffix: Option, diag: Option<(Span, &Handler)>) let orig = s; let mut ty = ast::LitIntType::Unsuffixed; - if char_at(s, 0) == '0' && s.len() > 1 { - match char_at(s, 1) { - 'x' => base = 16, - 'o' => base = 8, - 'b' => base = 2, + if s.starts_with('0') && s.len() > 1 { + match s.as_bytes()[1] { + b'x' => base = 16, + b'o' => base = 8, + b'b' => base = 2, _ => { } } } @@ -767,7 +786,7 @@ mod tests { use attr::first_attr_value_str_by_name; use parse; use print::pprust::item_to_string; - use tokenstream::{self, DelimSpan, TokenTree}; + use tokenstream::{DelimSpan, TokenTree}; use util::parser_testing::string_to_stream; use util::parser_testing::{string_to_expr, string_to_item}; use with_globals; @@ -798,42 +817,41 @@ mod tests { Some(&TokenTree::Token(_, token::Ident(name_macro_rules, false))), Some(&TokenTree::Token(_, token::Not)), Some(&TokenTree::Token(_, token::Ident(name_zip, false))), - Some(&TokenTree::Delimited(_, ref macro_delimed)), + Some(&TokenTree::Delimited(_, macro_delim, ref macro_tts)), ) if name_macro_rules.name == "macro_rules" && name_zip.name == "zip" => { - let tts = ¯o_delimed.stream().trees().collect::>(); + let tts = ¯o_tts.stream().trees().collect::>(); match (tts.len(), tts.get(0), tts.get(1), tts.get(2)) { ( 3, - Some(&TokenTree::Delimited(_, ref first_delimed)), + Some(&TokenTree::Delimited(_, first_delim, ref first_tts)), Some(&TokenTree::Token(_, token::FatArrow)), - Some(&TokenTree::Delimited(_, ref second_delimed)), + Some(&TokenTree::Delimited(_, second_delim, ref second_tts)), ) - if macro_delimed.delim == token::Paren => { - let tts = &first_delimed.stream().trees().collect::>(); + if macro_delim == token::Paren => { + let tts = &first_tts.stream().trees().collect::>(); match (tts.len(), tts.get(0), tts.get(1)) { ( 2, Some(&TokenTree::Token(_, token::Dollar)), Some(&TokenTree::Token(_, token::Ident(ident, false))), ) - if first_delimed.delim == token::Paren && ident.name == "a" => {}, - _ => panic!("value 3: {:?}", *first_delimed), + if first_delim == token::Paren && ident.name == "a" => {}, + _ => panic!("value 3: {:?} {:?}", first_delim, first_tts), } - let tts = &second_delimed.stream().trees().collect::>(); + let tts = &second_tts.stream().trees().collect::>(); match (tts.len(), tts.get(0), tts.get(1)) { ( 2, Some(&TokenTree::Token(_, token::Dollar)), Some(&TokenTree::Token(_, token::Ident(ident, false))), ) - if second_delimed.delim == token::Paren - && ident.name == "a" => {}, - _ => panic!("value 4: {:?}", *second_delimed), + if second_delim == token::Paren && ident.name == "a" => {}, + _ => panic!("value 4: {:?} {:?}", second_delim, second_tts), } }, - _ => panic!("value 2: {:?}", *macro_delimed), + _ => panic!("value 2: {:?} {:?}", macro_delim, macro_tts), } }, _ => panic!("value: {:?}",tts), @@ -846,31 +864,29 @@ mod tests { with_globals(|| { let tts = string_to_stream("fn a (b : i32) { b; }".to_string()); - let expected = TokenStream::concat(vec![ + let expected = TokenStream::new(vec![ TokenTree::Token(sp(0, 2), token::Ident(Ident::from_str("fn"), false)).into(), TokenTree::Token(sp(3, 4), token::Ident(Ident::from_str("a"), false)).into(), TokenTree::Delimited( DelimSpan::from_pair(sp(5, 6), sp(13, 14)), - tokenstream::Delimited { - delim: token::DelimToken::Paren, - tts: TokenStream::concat(vec![ - TokenTree::Token(sp(6, 7), - token::Ident(Ident::from_str("b"), false)).into(), - TokenTree::Token(sp(8, 9), token::Colon).into(), - TokenTree::Token(sp(10, 13), - token::Ident(Ident::from_str("i32"), false)).into(), - ]).into(), - }).into(), + token::DelimToken::Paren, + TokenStream::new(vec![ + TokenTree::Token(sp(6, 7), + token::Ident(Ident::from_str("b"), false)).into(), + TokenTree::Token(sp(8, 9), token::Colon).into(), + TokenTree::Token(sp(10, 13), + token::Ident(Ident::from_str("i32"), false)).into(), + ]).into(), + ).into(), TokenTree::Delimited( DelimSpan::from_pair(sp(15, 16), sp(20, 21)), - tokenstream::Delimited { - delim: token::DelimToken::Brace, - tts: TokenStream::concat(vec![ - TokenTree::Token(sp(17, 18), - token::Ident(Ident::from_str("b"), false)).into(), - TokenTree::Token(sp(18, 19), token::Semi).into(), - ]).into(), - }).into() + token::DelimToken::Brace, + TokenStream::new(vec![ + TokenTree::Token(sp(17, 18), + token::Ident(Ident::from_str("b"), false)).into(), + TokenTree::Token(sp(18, 19), token::Semi).into(), + ]).into(), + ).into() ]); assert_eq!(tts, expected); @@ -977,23 +993,25 @@ mod tests { with_globals(|| { let sess = ParseSess::new(FilePathMapping::empty()); - let name = FileName::Custom("source".to_string()); + let name_1 = FileName::Custom("crlf_source_1".to_string()); let source = "/// doc comment\r\nfn foo() {}".to_string(); - let item = parse_item_from_source_str(name.clone(), source, &sess) + let item = parse_item_from_source_str(name_1, source, &sess) .unwrap().unwrap(); let doc = first_attr_value_str_by_name(&item.attrs, "doc").unwrap(); assert_eq!(doc, "/// doc comment"); + let name_2 = FileName::Custom("crlf_source_2".to_string()); let source = "/// doc comment\r\n/// line 2\r\nfn foo() {}".to_string(); - let item = parse_item_from_source_str(name.clone(), source, &sess) + let item = parse_item_from_source_str(name_2, source, &sess) .unwrap().unwrap(); let docs = item.attrs.iter().filter(|a| a.path == "doc") .map(|a| a.value_str().unwrap().to_string()).collect::>(); let b: &[_] = &["/// doc comment".to_string(), "/// line 2".to_string()]; assert_eq!(&docs[..], b); + let name_3 = FileName::Custom("clrf_source_3".to_string()); let source = "/** doc comment\r\n * with CRLF */\r\nfn foo() {}".to_string(); - let item = parse_item_from_source_str(name, source, &sess).unwrap().unwrap(); + let item = parse_item_from_source_str(name_3, source, &sess).unwrap().unwrap(); let doc = first_attr_value_str_by_name(&item.attrs, "doc").unwrap(); assert_eq!(doc, "/** doc comment\n * with CRLF */"); }); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 1cd5006f330..5a51b629826 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -48,13 +48,14 @@ use errors::{self, Applicability, DiagnosticBuilder, DiagnosticId}; use parse::{self, SeqSep, classify, token}; use parse::lexer::TokenAndSpan; use parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration}; +use parse::token::DelimToken; use parse::{new_sub_parser_from_file, ParseSess, Directory, DirectoryOwnership}; use util::parser::{AssocOp, Fixity}; use print::pprust; use ptr::P; use parse::PResult; use ThinVec; -use tokenstream::{self, Delimited, DelimSpan, ThinTokenStream, TokenTree, TokenStream}; +use tokenstream::{self, DelimSpan, ThinTokenStream, TokenTree, TokenStream}; use symbol::{Symbol, keywords}; use std::borrow::Cow; @@ -92,12 +93,12 @@ pub enum PathStyle { /// `x` - comparisons, `x::` - unambiguously a path. Expr, /// In other contexts, notably in types, no ambiguity exists and paths can be written - /// without the disambiguator, e.g. `x` - unambiguously a path. + /// without the disambiguator, e.g., `x` - unambiguously a path. /// Paths with disambiguators are still accepted, `x::` - unambiguously a path too. Type, - /// A path with generic arguments disallowed, e.g. `foo::bar::Baz`, used in imports, + /// A path with generic arguments disallowed, e.g., `foo::bar::Baz`, used in imports, /// visibilities or attributes. - /// Technically, this variant is unnecessary and e.g. `Expr` can be used instead + /// Technically, this variant is unnecessary and e.g., `Expr` can be used instead /// (paths in "mod" contexts have to be checked later for absence of generic arguments /// anyway, due to macros), but it is used to avoid weird suggestions about expected /// tokens when something goes wrong. @@ -293,13 +294,13 @@ enum LastToken { } impl TokenCursorFrame { - fn new(sp: DelimSpan, delimited: &Delimited) -> Self { + fn new(sp: DelimSpan, delim: DelimToken, tts: &ThinTokenStream) -> Self { TokenCursorFrame { - delim: delimited.delim, + delim: delim, span: sp, - open_delim: delimited.delim == token::NoDelim, - tree_cursor: delimited.stream().into_trees(), - close_delim: delimited.delim == token::NoDelim, + open_delim: delim == token::NoDelim, + tree_cursor: tts.stream().into_trees(), + close_delim: delim == token::NoDelim, last_token: LastToken::Was(None), } } @@ -310,14 +311,12 @@ impl TokenCursor { loop { let tree = if !self.frame.open_delim { self.frame.open_delim = true; - Delimited { delim: self.frame.delim, tts: TokenStream::empty().into() } - .open_tt(self.frame.span.open) + TokenTree::open_tt(self.frame.span.open, self.frame.delim) } else if let Some(tree) = self.frame.tree_cursor.next() { tree } else if !self.frame.close_delim { self.frame.close_delim = true; - Delimited { delim: self.frame.delim, tts: TokenStream::empty().into() } - .close_tt(self.frame.span.close) + TokenTree::close_tt(self.frame.span.close, self.frame.delim) } else if let Some(frame) = self.stack.pop() { self.frame = frame; continue @@ -332,8 +331,8 @@ impl TokenCursor { match tree { TokenTree::Token(sp, tok) => return TokenAndSpan { tok: tok, sp: sp }, - TokenTree::Delimited(sp, ref delimited) => { - let frame = TokenCursorFrame::new(sp, delimited); + TokenTree::Delimited(sp, delim, tts) => { + let frame = TokenCursorFrame::new(sp, delim, &tts); self.stack.push(mem::replace(&mut self.frame, frame)); } } @@ -362,25 +361,28 @@ impl TokenCursor { } let delim_span = DelimSpan::from_single(sp); - let body = TokenTree::Delimited(delim_span, Delimited { - delim: token::Bracket, - tts: [TokenTree::Token(sp, token::Ident(ast::Ident::from_str("doc"), false)), - TokenTree::Token(sp, token::Eq), - TokenTree::Token(sp, token::Literal( - token::StrRaw(Symbol::intern(&stripped), num_of_hashes), None))] - .iter().cloned().collect::().into(), - }); + let body = TokenTree::Delimited( + delim_span, + token::Bracket, + [TokenTree::Token(sp, token::Ident(ast::Ident::from_str("doc"), false)), + TokenTree::Token(sp, token::Eq), + TokenTree::Token(sp, token::Literal( + token::StrRaw(Symbol::intern(&stripped), num_of_hashes), None)) + ] + .iter().cloned().collect::().into(), + ); - self.stack.push(mem::replace(&mut self.frame, TokenCursorFrame::new(delim_span, &Delimited { - delim: token::NoDelim, - tts: if doc_comment_style(&name.as_str()) == AttrStyle::Inner { + self.stack.push(mem::replace(&mut self.frame, TokenCursorFrame::new( + delim_span, + token::NoDelim, + &if doc_comment_style(&name.as_str()) == AttrStyle::Inner { [TokenTree::Token(sp, token::Pound), TokenTree::Token(sp, token::Not), body] .iter().cloned().collect::().into() } else { [TokenTree::Token(sp, token::Pound), body] .iter().cloned().collect::().into() }, - }))); + ))); self.next() } @@ -561,10 +563,11 @@ impl<'a> Parser<'a> { root_module_name: None, expected_tokens: Vec::new(), token_cursor: TokenCursor { - frame: TokenCursorFrame::new(DelimSpan::dummy(), &Delimited { - delim: token::NoDelim, - tts: tokens.into(), - }), + frame: TokenCursorFrame::new( + DelimSpan::dummy(), + token::NoDelim, + &tokens.into(), + ), stack: Vec::new(), }, desugar_doc_comments, @@ -1238,7 +1241,7 @@ impl<'a> Parser<'a> { f(&match self.token_cursor.frame.tree_cursor.look_ahead(dist - 1) { Some(tree) => match tree { TokenTree::Token(_, tok) => tok, - TokenTree::Delimited(_, delimited) => token::OpenDelim(delimited.delim), + TokenTree::Delimited(_, delim, _) => token::OpenDelim(delim), }, None => token::CloseDelim(self.token_cursor.frame.delim), }) @@ -1251,7 +1254,7 @@ impl<'a> Parser<'a> { match self.token_cursor.frame.tree_cursor.look_ahead(dist - 1) { Some(TokenTree::Token(span, _)) => span, - Some(TokenTree::Delimited(span, _)) => span.entire(), + Some(TokenTree::Delimited(span, ..)) => span.entire(), None => self.look_ahead_span(dist - 1), } } @@ -1404,7 +1407,7 @@ impl<'a> Parser<'a> { // definition... // We don't allow argument names to be left off in edition 2018. - p.parse_arg_general(p.span.rust_2018()) + p.parse_arg_general(p.span.rust_2018(), true) })?; generics.where_clause = self.parse_where_clause()?; @@ -1817,7 +1820,7 @@ impl<'a> Parser<'a> { /// This version of parse arg doesn't necessarily require /// identifier names. - fn parse_arg_general(&mut self, require_name: bool) -> PResult<'a, Arg> { + fn parse_arg_general(&mut self, require_name: bool, is_trait_item: bool) -> PResult<'a, Arg> { maybe_whole!(self, NtArg, |x| x); if let Ok(Some(_)) = self.parse_self_arg() { @@ -1849,6 +1852,17 @@ impl<'a> Parser<'a> { String::from(": "), Applicability::HasPlaceholders, ); + } else if require_name && is_trait_item { + if let PatKind::Ident(_, ident, _) = pat.node { + err.span_suggestion_with_applicability( + pat.span, + "explicitly ignore parameter", + format!("_: {}", ident), + Applicability::MachineApplicable, + ); + } + + err.note("anonymous parameters are removed in the 2018 edition (see RFC 1685)"); } return Err(err); @@ -1914,10 +1928,10 @@ impl<'a> Parser<'a> { /// Parse a single function argument crate fn parse_arg(&mut self) -> PResult<'a, Arg> { - self.parse_arg_general(true) + self.parse_arg_general(true, false) } - /// Parse an argument in a lambda header e.g. |arg, arg| + /// Parse an argument in a lambda header e.g., |arg, arg| fn parse_fn_block_arg(&mut self) -> PResult<'a, Arg> { let pat = self.parse_pat(Some("argument name"))?; let t = if self.eat(&token::Colon) { @@ -2017,6 +2031,17 @@ impl<'a> Parser<'a> { } } + fn parse_ident_or_underscore(&mut self) -> PResult<'a, ast::Ident> { + match self.token { + token::Ident(ident, false) if ident.name == keywords::Underscore.name() => { + let span = self.span; + self.bump(); + Ok(Ident::new(ident.name, span)) + } + _ => self.parse_ident(), + } + } + /// Parses qualified path. /// Assumes that the leading `<` has been parsed already. /// @@ -2082,7 +2107,7 @@ impl<'a> Parser<'a> { let mut segments = Vec::new(); let mod_sep_ctxt = self.span.ctxt(); if self.eat(&token::ModSep) { - segments.push(PathSegment::crate_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt))); + segments.push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt))); } self.parse_path_segments(&mut segments, style, enable_warning)?; @@ -2306,8 +2331,8 @@ impl<'a> Parser<'a> { return Err(err) } }; - let delimited = match self.parse_token_tree() { - TokenTree::Delimited(_, delimited) => delimited, + let tts = match self.parse_token_tree() { + TokenTree::Delimited(_, _, tts) => tts, _ => unreachable!(), }; let delim = match delim { @@ -2316,14 +2341,14 @@ impl<'a> Parser<'a> { token::Brace => MacDelimiter::Brace, token::NoDelim => self.bug("unexpected no delimiter"), }; - Ok((delim, delimited.stream().into())) + Ok((delim, tts.stream().into())) } /// At the bottom (top?) of the precedence hierarchy, /// parse things like parenthesized exprs, /// macros, return, etc. /// - /// NB: This does not parse outer attributes, + /// N.B., this does not parse outer attributes, /// and is private because it only works /// correctly if called from parse_dot_or_call_expr(). fn parse_bottom_expr(&mut self) -> PResult<'a, P> { @@ -2881,10 +2906,11 @@ impl<'a> Parser<'a> { self.token_cursor.stack.pop().unwrap()); self.span = frame.span.entire(); self.bump(); - TokenTree::Delimited(frame.span, Delimited { - delim: frame.delim, - tts: frame.tree_cursor.original_stream().into(), - }) + TokenTree::Delimited( + frame.span, + frame.delim, + frame.tree_cursor.original_stream().into(), + ) }, token::CloseDelim(_) | token::Eof => unreachable!(), _ => { @@ -2913,7 +2939,7 @@ impl<'a> Parser<'a> { _ => result.push(self.parse_token_tree().into()), } } - TokenStream::concat(result) + TokenStream::new(result) } /// Parse a prefix-unary-operator expr @@ -3036,6 +3062,7 @@ impl<'a> Parser<'a> { /// /// This parses an expression accounting for associativity and precedence of the operators in /// the expression. + #[inline] fn parse_assoc_expr(&mut self, already_parsed_attrs: Option>) -> PResult<'a, P> { @@ -3696,6 +3723,7 @@ impl<'a> Parser<'a> { } /// Parse an expression + #[inline] pub fn parse_expr(&mut self) -> PResult<'a, P> { self.parse_expr_res(Restrictions::empty(), None) } @@ -3715,13 +3743,14 @@ impl<'a> Parser<'a> { } /// Parse an expression, subject to the given restrictions + #[inline] fn parse_expr_res(&mut self, r: Restrictions, already_parsed_attrs: Option>) -> PResult<'a, P> { self.with_res(r, |this| this.parse_assoc_expr(already_parsed_attrs)) } - /// Parse the RHS of a local variable declaration (e.g. '= 14;') + /// Parse the RHS of a local variable declaration (e.g., '= 14;') fn parse_initializer(&mut self, skip_eq: bool) -> PResult<'a, Option>> { if self.eat(&token::Eq) { Ok(Some(self.parse_expr()?)) @@ -4103,7 +4132,7 @@ impl<'a> Parser<'a> { self.parse_pat_with_range_pat(true, expected) } - /// Parse a pattern, with a setting whether modern range patterns e.g. `a..=b`, `a..b` are + /// Parse a pattern, with a setting whether modern range patterns e.g., `a..=b`, `a..b` are /// allowed. fn parse_pat_with_range_pat( &mut self, @@ -4445,7 +4474,7 @@ impl<'a> Parser<'a> { } /// Parse a statement. This stops just before trailing semicolons on everything but items. - /// e.g. a `StmtKind::Semi` parses to a `StmtKind::Expr`, leaving the trailing `;` unconsumed. + /// e.g., a `StmtKind::Semi` parses to a `StmtKind::Expr`, leaving the trailing `;` unconsumed. pub fn parse_stmt(&mut self) -> PResult<'a, Option> { Ok(self.parse_stmt_(true)) } @@ -4598,7 +4627,7 @@ impl<'a> Parser<'a> { let ident = self.parse_ident()?; let tokens = if self.check(&token::OpenDelim(token::Brace)) { match self.parse_token_tree() { - TokenTree::Delimited(_, ref delimited) => delimited.stream(), + TokenTree::Delimited(_, _, tts) => tts.stream(), _ => unreachable!(), } } else if self.check(&token::OpenDelim(token::Paren)) { @@ -4609,7 +4638,7 @@ impl<'a> Parser<'a> { self.unexpected()?; unreachable!() }; - TokenStream::concat(vec![ + TokenStream::new(vec![ args.into(), TokenTree::Token(token_lo.to(self.prev_span), token::FatArrow).into(), body.into(), @@ -5042,9 +5071,9 @@ impl<'a> Parser<'a> { // Parse bounds of a type parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`. // BOUND = TY_BOUND | LT_BOUND - // LT_BOUND = LIFETIME (e.g. `'a`) + // LT_BOUND = LIFETIME (e.g., `'a`) // TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN) - // TY_BOUND_NOPAREN = [?] [for] SIMPLE_PATH (e.g. `?for<'a: 'b> m::Trait<'a>`) + // TY_BOUND_NOPAREN = [?] [for] SIMPLE_PATH (e.g., `?for<'a: 'b> m::Trait<'a>`) fn parse_generic_bounds_common(&mut self, allow_plus: bool) -> PResult<'a, GenericBounds> { let mut bounds = Vec::new(); loop { @@ -5099,7 +5128,7 @@ impl<'a> Parser<'a> { } // Parse bounds of a lifetime parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`. - // BOUND = LT_BOUND (e.g. `'a`) + // BOUND = LT_BOUND (e.g., `'a`) fn parse_lt_param_bounds(&mut self) -> GenericBounds { let mut lifetimes = Vec::new(); while self.check_lifetime() { @@ -5458,7 +5487,7 @@ impl<'a> Parser<'a> { } } } else { - match p.parse_arg_general(named_args) { + match p.parse_arg_general(named_args, false) { Ok(arg) => Ok(Some(arg)), Err(mut e) => { e.emit(); @@ -5508,7 +5537,7 @@ impl<'a> Parser<'a> { _ => unreachable!() }; let isolated_self = |this: &mut Self, n| { - this.look_ahead(n, |t| t.is_keyword(keywords::SelfValue)) && + this.look_ahead(n, |t| t.is_keyword(keywords::SelfLower)) && this.look_ahead(n + 1, |t| t != &token::ModSep) }; @@ -5800,20 +5829,14 @@ impl<'a> Parser<'a> { } fn complain_if_pub_macro(&mut self, vis: &VisibilityKind, sp: Span) { - if let Err(mut err) = self.complain_if_pub_macro_diag(vis, sp) { - err.emit(); - } - } - - fn complain_if_pub_macro_diag(&mut self, vis: &VisibilityKind, sp: Span) -> PResult<'a, ()> { match *vis { - VisibilityKind::Inherited => Ok(()), + VisibilityKind::Inherited => {} _ => { let is_macro_rules: bool = match self.token { token::Ident(sid, _) => sid.name == Symbol::intern("macro_rules"), _ => false, }; - if is_macro_rules { + let mut err = if is_macro_rules { let mut err = self.diagnostic() .struct_span_err(sp, "can't qualify macro_rules invocation with `pub`"); err.span_suggestion_with_applicability( @@ -5822,13 +5845,14 @@ impl<'a> Parser<'a> { "#[macro_export]".to_owned(), Applicability::MaybeIncorrect // speculative ); - Err(err) + err } else { let mut err = self.diagnostic() .struct_span_err(sp, "can't qualify macro invocation with `pub`"); err.help("try adjusting the macro to put `pub` inside the invocation"); - Err(err) - } + err + }; + err.emit(); } } } @@ -6137,9 +6161,6 @@ impl<'a> Parser<'a> { fn consume_block(&mut self, delim: token::DelimToken) { let mut brace_depth = 0; - if !self.eat(&token::OpenDelim(delim)) { - return; - } loop { if self.eat(&token::OpenDelim(delim)) { brace_depth += 1; @@ -6150,7 +6171,7 @@ impl<'a> Parser<'a> { brace_depth -= 1; continue; } - } else if self.eat(&token::Eof) || self.eat(&token::CloseDelim(token::NoDelim)) { + } else if self.token == token::Eof || self.eat(&token::CloseDelim(token::NoDelim)) { return; } else { self.bump(); @@ -6282,7 +6303,7 @@ impl<'a> Parser<'a> { /// Parse `pub`, `pub(crate)` and `pub(in path)` plus shortcuts `crate` for `pub(crate)`, /// `pub(self)` for `pub(in self)` and `pub(super)` for `pub(in super)`. - /// If the following element can't be a tuple (i.e. it's a function definition, + /// If the following element can't be a tuple (i.e., it's a function definition, /// it's not a tuple struct field) and the contents within the parens /// isn't valid, emit a proper diagnostic. pub fn parse_visibility(&mut self, can_take_tuple: bool) -> PResult<'a, Visibility> { @@ -6330,7 +6351,7 @@ impl<'a> Parser<'a> { return Ok(vis) } else if self.look_ahead(2, |t| t == &token::CloseDelim(token::Paren)) && self.look_ahead(1, |t| t.is_keyword(keywords::Super) || - t.is_keyword(keywords::SelfValue)) + t.is_keyword(keywords::SelfLower)) { // `pub(self)` or `pub(super)` self.bump(); // `(` @@ -6434,13 +6455,7 @@ impl<'a> Parser<'a> { } fn parse_item_const(&mut self, m: Option) -> PResult<'a, ItemInfo> { - let id = match self.token { - token::Ident(ident, false) if ident.name == keywords::Underscore.name() => { - self.bump(); // `_` - ident.gensym() - }, - _ => self.parse_ident()?, - }; + let id = if m.is_none() { self.parse_ident_or_underscore() } else { self.parse_ident() }?; self.expect(&token::Colon)?; let ty = self.parse_ty()?; self.expect(&token::Eq)?; @@ -6782,7 +6797,7 @@ impl<'a> Parser<'a> { let error_msg = "crate name using dashes are not valid in `extern crate` statements"; let suggestion_msg = "if the original crate name uses dashes you need to use underscores \ in the code"; - let mut ident = if self.token.is_keyword(keywords::SelfValue) { + let mut ident = if self.token.is_keyword(keywords::SelfLower) { self.parse_path_segment_ident() } else { self.parse_ident() @@ -7405,17 +7420,27 @@ impl<'a> Parser<'a> { return Err(err); } else if self.look_ahead(1, |t| *t == token::OpenDelim(token::Paren)) { let ident = self.parse_ident().unwrap(); + self.bump(); // `(` + let kw_name = if let Ok(Some(_)) = self.parse_self_arg() { + "method" + } else { + "function" + }; self.consume_block(token::Paren); - let (kw, kw_name, ambiguous) = if self.check(&token::RArrow) || - self.check(&token::OpenDelim(token::Brace)) - { - ("fn", "method", false) + let (kw, kw_name, ambiguous) = if self.check(&token::RArrow) { + self.eat_to_tokens(&[&token::OpenDelim(token::Brace)]); + self.bump(); // `{` + ("fn", kw_name, false) + } else if self.check(&token::OpenDelim(token::Brace)) { + self.bump(); // `{` + ("fn", kw_name, false) } else if self.check(&token::Colon) { let kw = "struct"; (kw, kw, false) } else { - ("fn` or `struct", "method or struct", true) + ("fn` or `struct", "function or struct", true) }; + self.consume_block(token::Brace); let msg = format!("missing `{}` for {} definition", kw, kw_name); let mut err = self.diagnostic().struct_span_err(sp, &msg); @@ -7442,6 +7467,32 @@ impl<'a> Parser<'a> { } } return Err(err); + } else if self.look_ahead(1, |t| *t == token::Lt) { + let ident = self.parse_ident().unwrap(); + self.eat_to_tokens(&[&token::Gt]); + self.bump(); // `>` + let (kw, kw_name, ambiguous) = if self.eat(&token::OpenDelim(token::Paren)) { + if let Ok(Some(_)) = self.parse_self_arg() { + ("fn", "method", false) + } else { + ("fn", "function", false) + } + } else if self.check(&token::OpenDelim(token::Brace)) { + ("struct", "struct", false) + } else { + ("fn` or `struct", "function or struct", true) + }; + let msg = format!("missing `{}` for {} definition", kw, kw_name); + let mut err = self.diagnostic().struct_span_err(sp, &msg); + if !ambiguous { + err.span_suggestion_short_with_applicability( + sp, + &format!("add `{}` here to parse `{}` as a public {}", kw, ident, kw_name), + format!(" {} ", kw), + Applicability::MachineApplicable, + ); + } + return Err(err); } } self.parse_macro_use_or_failure(attrs, macros_allowed, attributes_allowed, lo, visibility) @@ -7685,7 +7736,7 @@ impl<'a> Parser<'a> { let mod_sep_ctxt = self.span.ctxt(); if self.eat(&token::ModSep) { prefix.segments.push( - PathSegment::crate_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)) + PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)) ); } @@ -7725,13 +7776,7 @@ impl<'a> Parser<'a> { fn parse_rename(&mut self) -> PResult<'a, Option> { if self.eat_keyword(keywords::As) { - match self.token { - token::Ident(ident, false) if ident.name == keywords::Underscore.name() => { - self.bump(); // `_` - Ok(Some(ident.gensym())) - } - _ => self.parse_ident().map(Some), - } + self.parse_ident_or_underscore().map(Some) } else { Ok(None) } diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 4a5f3e240da..badcc4ed876 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -207,6 +207,10 @@ pub enum Token { Eof, } +// `Token` is used a lot. Make sure it doesn't unintentionally get bigger. +#[cfg(target_arch = "x86_64")] +static_assert!(MEM_SIZE_OF_STATEMENT: mem::size_of::() == 16); + impl Token { pub fn interpolated(nt: Nonterminal) -> Token { Token::Interpolated(Lrc::new((nt, LazyTokenStream::new()))) @@ -545,11 +549,12 @@ impl Token { let tokens_for_real = nt.1.force(|| { // FIXME(#43081): Avoid this pretty-print + reparse hack let source = pprust::token_to_string(self); - parse_stream_from_source_str(FileName::MacroExpansion, source, sess, Some(span)) + let filename = FileName::macro_expansion_source_code(&source); + parse_stream_from_source_str(filename, source, sess, Some(span)) }); // During early phases of the compiler the AST could get modified - // directly (e.g. attributes added or removed) and the internal cache + // directly (e.g., attributes added or removed) and the internal cache // of tokens my not be invalidated or updated. Consequently if the // "lossless" token stream disagrees with our actual stringification // (which has historically been much more battle-tested) then we go @@ -628,7 +633,9 @@ impl Token { (&Shebang(a), &Shebang(b)) => a == b, (&Lifetime(a), &Lifetime(b)) => a.name == b.name, - (&Ident(a, b), &Ident(c, d)) => a.name == c.name && b == d, + (&Ident(a, b), &Ident(c, d)) => b == d && (a.name == c.name || + a.name == keywords::DollarCrate.name() || + c.name == keywords::DollarCrate.name()), (&Literal(ref a, b), &Literal(ref c, d)) => { b == d && a.probably_equal_for_proc_macro(c) @@ -781,10 +788,12 @@ fn prepend_attrs(sess: &ParseSess, assert_eq!(attr.style, ast::AttrStyle::Outer, "inner attributes should prevent cached tokens from existing"); + let source = pprust::attr_to_string(attr); + let macro_filename = FileName::macro_expansion_source_code(&source); if attr.is_sugared_doc { let stream = parse_stream_from_source_str( - FileName::MacroExpansion, - pprust::attr_to_string(attr), + macro_filename, + source, sess, Some(span), ); @@ -805,8 +814,8 @@ fn prepend_attrs(sess: &ParseSess, // should eventually be removed. } else { let stream = parse_stream_from_source_str( - FileName::MacroExpansion, - pprust::path_to_string(&attr.path), + macro_filename, + source, sess, Some(span), ); @@ -815,16 +824,13 @@ fn prepend_attrs(sess: &ParseSess, brackets.push(attr.tokens.clone()); - let tokens = tokenstream::Delimited { - delim: DelimToken::Bracket, - tts: brackets.build().into(), - }; // The span we list here for `#` and for `[ ... ]` are both wrong in // that it encompasses more than each token, but it hopefully is "good // enough" for now at least. builder.push(tokenstream::TokenTree::Token(attr.span, Pound)); let delim_span = DelimSpan::from_single(attr.span); - builder.push(tokenstream::TokenTree::Delimited(delim_span, tokens)); + builder.push(tokenstream::TokenTree::Delimited( + delim_span, DelimToken::Bracket, brackets.build().into())); } builder.push(tokens.clone()); Some(builder.build()) diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index aaed56da29d..0890be728f3 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -109,7 +109,7 @@ //! The buffered tokens go through a ring-buffer, 'tokens'. The 'left' and //! 'right' indices denote the active portion of the ring buffer as well as //! describing hypothetical points-in-the-infinite-stream at most 3N tokens -//! apart (i.e. "not wrapped to ring-buffer boundaries"). The paper will switch +//! apart (i.e., "not wrapped to ring-buffer boundaries"). The paper will switch //! between using 'left' and 'right' terms to denote the wrapped-to-ring-buffer //! and point-in-infinite-stream senses freely. //! diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index a9f08fdd411..5e7707f4e5c 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -16,7 +16,6 @@ use util::parser::{self, AssocOp, Fixity}; use attr; use source_map::{self, SourceMap, Spanned}; use syntax_pos::{self, BytePos}; -use syntax_pos::hygiene::{Mark, SyntaxContext}; use parse::token::{self, BinOpToken, Token}; use parse::lexer::comments; use parse::{self, ParseSess}; @@ -724,12 +723,12 @@ pub trait PrintState<'a> { if i > 0 { self.writer().word("::")? } - if segment.ident.name != keywords::CrateRoot.name() && - segment.ident.name != keywords::DollarCrate.name() - { - self.writer().word(segment.ident.as_str().get())?; - } else if segment.ident.name == keywords::DollarCrate.name() { - self.print_dollar_crate(segment.ident.span.ctxt())?; + if segment.ident.name != keywords::PathRoot.name() { + if segment.ident.name == keywords::DollarCrate.name() { + self.print_dollar_crate(segment.ident)?; + } else { + self.writer().word(segment.ident.as_str().get())?; + } } } Ok(()) @@ -815,12 +814,12 @@ pub trait PrintState<'a> { _ => Ok(()) } } - TokenTree::Delimited(_, ref delimed) => { - self.writer().word(token_to_string(&delimed.open_token()))?; + TokenTree::Delimited(_, delim, tts) => { + self.writer().word(token_to_string(&token::OpenDelim(delim)))?; self.writer().space()?; - self.print_tts(delimed.stream())?; + self.print_tts(tts.stream())?; self.writer().space()?; - self.writer().word(token_to_string(&delimed.close_token())) + self.writer().word(token_to_string(&token::CloseDelim(delim))) }, } } @@ -843,17 +842,19 @@ pub trait PrintState<'a> { fn nbsp(&mut self) -> io::Result<()> { self.writer().word(" ") } - fn print_dollar_crate(&mut self, mut ctxt: SyntaxContext) -> io::Result<()> { - if let Some(mark) = ctxt.adjust(Mark::root()) { - // Make a best effort to print something that complies - if mark.is_builtin() { - if let Some(name) = std_inject::injected_crate_name() { - self.writer().word("::")?; - self.writer().word(name)?; - } - } + // AST pretty-printer is used as a fallback for turning AST structures into token streams for + // proc macros. Additionally, proc macros may stringify their input and expect it survive the + // stringification (especially true for proc macro derives written between Rust 1.15 and 1.30). + // So we need to somehow pretty-print `$crate` in paths in a way preserving at least some of + // its hygiene data, most importantly name of the crate it refers to. + // As a result we print `$crate` as `crate` if it refers to the local crate + // and as `::other_crate_name` if it refers to some other crate. + fn print_dollar_crate(&mut self, ident: ast::Ident) -> io::Result<()> { + let name = ident.span.ctxt().dollar_crate_name(); + if !ast::Ident::with_empty_ctxt(name).is_path_segment_keyword() { + self.writer().word("::")?; } - Ok(()) + self.writer().word(name.as_str().get()) } } @@ -2463,14 +2464,15 @@ impl<'a> State<'a> { colons_before_params: bool) -> io::Result<()> { - if segment.ident.name != keywords::CrateRoot.name() && - segment.ident.name != keywords::DollarCrate.name() { - self.print_ident(segment.ident)?; + if segment.ident.name != keywords::PathRoot.name() { + if segment.ident.name == keywords::DollarCrate.name() { + self.print_dollar_crate(segment.ident)?; + } else { + self.print_ident(segment.ident)?; + } if let Some(ref args) = segment.args { self.print_generic_args(args, colons_before_params)?; } - } else if segment.ident.name == keywords::DollarCrate.name() { - self.print_dollar_crate(segment.ident.span.ctxt())?; } Ok(()) } diff --git a/src/libsyntax/ptr.rs b/src/libsyntax/ptr.rs index 9fbc64758da..17e7730120f 100644 --- a/src/libsyntax/ptr.rs +++ b/src/libsyntax/ptr.rs @@ -16,11 +16,11 @@ //! # Motivations and benefits //! //! * **Identity**: sharing AST nodes is problematic for the various analysis -//! passes (e.g. one may be able to bypass the borrow checker with a shared +//! passes (e.g., one may be able to bypass the borrow checker with a shared //! `ExprKind::AddrOf` node taking a mutable borrow). The only reason `@T` in the //! AST hasn't caused issues is because of inefficient folding passes which //! would always deduplicate any such shared nodes. Even if the AST were to -//! switch to an arena, this would still hold, i.e. it couldn't use `&'a T`, +//! switch to an arena, this would still hold, i.e., it couldn't use `&'a T`, //! but rather a wrapper like `P<'a, T>`. //! //! * **Immutability**: `P` disallows mutating its inner `T`, unlike `Box` @@ -34,7 +34,7 @@ //! * **Maintainability**: `P` provides a fixed interface - `Deref`, //! `and_then` and `map` - which can remain fully functional even if the //! implementation changes (using a special thread-local heap, for example). -//! Moreover, a switch to, e.g. `P<'a, T>` would be easy and mostly automated. +//! Moreover, a switch to, e.g., `P<'a, T>` would be easy and mostly automated. use std::fmt::{self, Display, Debug}; use std::iter::FromIterator; diff --git a/src/libsyntax/source_map.rs b/src/libsyntax/source_map.rs index e8cacc3b5af..9a343123f61 100644 --- a/src/libsyntax/source_map.rs +++ b/src/libsyntax/source_map.rs @@ -31,7 +31,7 @@ use std::path::{Path, PathBuf}; use std::env; use std::fs; -use std::io::{self, Read}; +use std::io; use errors::SourceMapper; /// Return the span itself if it doesn't come from a macro expansion, @@ -96,9 +96,7 @@ impl FileLoader for RealFileLoader { } fn read_file(&self, path: &Path) -> io::Result { - let mut src = String::new(); - fs::File::open(path)?.read_to_string(&mut src)?; - Ok(src) + fs::read_to_string(path) } } @@ -110,11 +108,19 @@ pub struct StableSourceFileId(u128); impl StableSourceFileId { pub fn new(source_file: &SourceFile) -> StableSourceFileId { + StableSourceFileId::new_from_pieces(&source_file.name, + source_file.name_was_remapped, + source_file.unmapped_path.as_ref()) + } + + pub fn new_from_pieces(name: &FileName, + name_was_remapped: bool, + unmapped_path: Option<&FileName>) -> StableSourceFileId { let mut hasher = StableHasher::new(); - source_file.name.hash(&mut hasher); - source_file.name_was_remapped.hash(&mut hasher); - source_file.unmapped_path.hash(&mut hasher); + name.hash(&mut hasher); + name_was_remapped.hash(&mut hasher); + unmapped_path.hash(&mut hasher); StableSourceFileId(hasher.finish()) } @@ -136,9 +142,6 @@ pub struct SourceMap { // This is used to apply the file path remapping as specified via // --remap-path-prefix to all SourceFiles allocated within this SourceMap. path_mapping: FilePathMapping, - /// In case we are in a doctest, replace all file names with the PathBuf, - /// and add the given offsets to the line info - doctest_offset: Option<(FileName, isize)>, } impl SourceMap { @@ -147,19 +150,9 @@ impl SourceMap { files: Default::default(), file_loader: Box::new(RealFileLoader), path_mapping, - doctest_offset: None, } } - pub fn new_doctest(path_mapping: FilePathMapping, - file: FileName, line: isize) -> SourceMap { - SourceMap { - doctest_offset: Some((file, line)), - ..SourceMap::new(path_mapping) - } - - } - pub fn with_file_loader(file_loader: Box, path_mapping: FilePathMapping) -> SourceMap { @@ -167,7 +160,6 @@ impl SourceMap { files: Default::default(), file_loader: file_loader, path_mapping, - doctest_offset: None, } } @@ -181,11 +173,7 @@ impl SourceMap { pub fn load_file(&self, path: &Path) -> io::Result> { let src = self.file_loader.read_file(path)?; - let filename = if let Some((ref name, _)) = self.doctest_offset { - name.clone() - } else { - path.to_owned().into() - }; + let filename = path.to_owned().into(); Ok(self.new_source_file(filename, src)) } @@ -208,7 +196,8 @@ impl SourceMap { } /// Creates a new source_file. - /// This does not ensure that only one SourceFile exists per file name. + /// If a file already exists in the source_map with the same id, that file is returned + /// unmodified pub fn new_source_file(&self, filename: FileName, src: String) -> Lrc { let start_pos = self.next_start_pos(); @@ -226,21 +215,30 @@ impl SourceMap { }, other => (other, false), }; - let source_file = Lrc::new(SourceFile::new( - filename, - was_remapped, - unmapped_path, - src, - Pos::from_usize(start_pos), - )); - let mut files = self.files.borrow_mut(); + let file_id = StableSourceFileId::new_from_pieces(&filename, + was_remapped, + Some(&unmapped_path)); - files.source_files.push(source_file.clone()); - files.stable_id_to_source_file.insert(StableSourceFileId::new(&source_file), - source_file.clone()); + return match self.source_file_by_stable_id(file_id) { + Some(lrc_sf) => lrc_sf, + None => { + let source_file = Lrc::new(SourceFile::new( + filename, + was_remapped, + unmapped_path, + src, + Pos::from_usize(start_pos), + )); - source_file + let mut files = self.files.borrow_mut(); + + files.source_files.push(source_file.clone()); + files.stable_id_to_source_file.insert(file_id, source_file.clone()); + + source_file + } + } } /// Allocates a new SourceFile representing a source file from an external @@ -310,15 +308,17 @@ impl SourceMap { } // If there is a doctest_offset, apply it to the line - pub fn doctest_offset_line(&self, mut orig: usize) -> usize { - if let Some((_, line)) = self.doctest_offset { - if line >= 0 { - orig = orig + line as usize; - } else { - orig = orig - (-line) as usize; - } + pub fn doctest_offset_line(&self, file: &FileName, orig: usize) -> usize { + return match file { + FileName::DocTest(_, offset) => { + return if *offset >= 0 { + orig + *offset as usize + } else { + orig - (-(*offset)) as usize + } + }, + _ => orig } - orig } /// Lookup source information about a BytePos @@ -579,7 +579,7 @@ impl SourceMap { match self.span_to_prev_source(sp) { Err(_) => None, Ok(source) => source.split('\n').last().map(|last_line| { - last_line.len() - last_line.trim_left().len() + last_line.len() - last_line.trim_start().len() }) } } @@ -593,7 +593,7 @@ impl SourceMap { /// if no character could be found or if an error occurred while retrieving the code snippet. pub fn span_extend_to_prev_char(&self, sp: Span, c: char) -> Span { if let Ok(prev_source) = self.span_to_prev_source(sp) { - let prev_source = prev_source.rsplit(c).nth(0).unwrap_or("").trim_left(); + let prev_source = prev_source.rsplit(c).nth(0).unwrap_or("").trim_start(); if !prev_source.is_empty() && !prev_source.contains('\n') { return sp.with_lo(BytePos(sp.lo().0 - prev_source.len() as u32)); } @@ -613,7 +613,7 @@ impl SourceMap { for ws in &[" ", "\t", "\n"] { let pat = pat.to_owned() + ws; if let Ok(prev_source) = self.span_to_prev_source(sp) { - let prev_source = prev_source.rsplit(&pat).nth(0).unwrap_or("").trim_left(); + let prev_source = prev_source.rsplit(&pat).nth(0).unwrap_or("").trim_start(); if !prev_source.is_empty() && (!prev_source.contains('\n') || accept_newlines) { return sp.with_lo(BytePos(sp.lo().0 - prev_source.len() as u32)); } @@ -627,7 +627,7 @@ impl SourceMap { pub fn span_until_char(&self, sp: Span, c: char) -> Span { match self.span_to_snippet(sp) { Ok(snippet) => { - let snippet = snippet.split(c).nth(0).unwrap_or("").trim_right(); + let snippet = snippet.split(c).nth(0).unwrap_or("").trim_end(); if !snippet.is_empty() && !snippet.contains('\n') { sp.with_hi(BytePos(sp.lo().0 + snippet.len() as u32)) } else { @@ -983,8 +983,8 @@ impl SourceMapper for SourceMap { } ) } - fn doctest_offset_line(&self, line: usize) -> usize { - self.doctest_offset_line(line) + fn doctest_offset_line(&self, file: &FileName, line: usize) -> usize { + self.doctest_offset_line(file, line) } } diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index 1210f331b28..5c994558ab0 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -112,7 +112,7 @@ pub fn maybe_inject_crates_ref( vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited), node: ast::ItemKind::Use(P(ast::UseTree { prefix: ast::Path { - segments: iter::once(keywords::CrateRoot.ident()) + segments: iter::once(keywords::PathRoot.ident()) .chain( [name, "prelude", "v1"].iter().cloned() .map(ast::Ident::from_str) diff --git a/src/libsyntax/str.rs b/src/libsyntax/str.rs deleted file mode 100644 index 281861918fd..00000000000 --- a/src/libsyntax/str.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2012-2014 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. - -#[inline] -pub fn char_at(s: &str, byte: usize) -> char { - s[byte..].chars().next().unwrap() -} diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 8ff4b0d025c..436a167e6a0 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -281,7 +281,7 @@ fn generate_test_harness(sess: &ParseSess, path: Vec::new(), test_cases: Vec::new(), reexport_test_harness_main, - // NB: doesn't consider the value of `--crate-name` passed on the command line. + // N.B., doesn't consider the value of `--crate-name` passed on the command line. is_libtest: attr::find_crate_name(&krate.attrs).map(|s| s == "test").unwrap_or(false), toplevel_reexport: None, ctxt: SyntaxContext::empty().apply_mark(mark), diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index 242299f1b1f..013ecd3d343 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -28,58 +28,12 @@ use ext::tt::{macro_parser, quoted}; use parse::Directory; use parse::token::{self, DelimToken, Token}; use print::pprust; +use rustc_data_structures::sync::Lrc; use serialize::{Decoder, Decodable, Encoder, Encodable}; -use util::RcVec; use std::borrow::Cow; use std::{fmt, iter, mem}; -/// A delimited sequence of token trees -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)] -pub struct Delimited { - /// The type of delimiter - pub delim: DelimToken, - /// The delimited sequence of token trees - pub tts: ThinTokenStream, -} - -impl Delimited { - /// Returns the opening delimiter as a token. - pub fn open_token(&self) -> token::Token { - token::OpenDelim(self.delim) - } - - /// Returns the closing delimiter as a token. - pub fn close_token(&self) -> token::Token { - token::CloseDelim(self.delim) - } - - /// Returns the opening delimiter as a token tree. - pub fn open_tt(&self, span: Span) -> TokenTree { - let open_span = if span.is_dummy() { - span - } else { - span.with_hi(span.lo() + BytePos(self.delim.len() as u32)) - }; - TokenTree::Token(open_span, self.open_token()) - } - - /// Returns the closing delimiter as a token tree. - pub fn close_tt(&self, span: Span) -> TokenTree { - let close_span = if span.is_dummy() { - span - } else { - span.with_lo(span.hi() - BytePos(self.delim.len() as u32)) - }; - TokenTree::Token(close_span, self.close_token()) - } - - /// Returns the token trees inside the delimiters. - pub fn stream(&self) -> TokenStream { - self.tts.clone().into() - } -} - /// When the main rust parser encounters a syntax-extension invocation, it /// parses the arguments to the invocation as a token-tree. This is a very /// loose structure, such that all sorts of different AST-fragments can @@ -97,7 +51,7 @@ pub enum TokenTree { /// A single token Token(Span, token::Token), /// A delimited sequence of token trees - Delimited(DelimSpan, Delimited), + Delimited(DelimSpan, DelimToken, ThinTokenStream), } impl TokenTree { @@ -116,9 +70,10 @@ impl TokenTree { pub fn eq_unspanned(&self, other: &TokenTree) -> bool { match (self, other) { (&TokenTree::Token(_, ref tk), &TokenTree::Token(_, ref tk2)) => tk == tk2, - (&TokenTree::Delimited(_, ref dl), &TokenTree::Delimited(_, ref dl2)) => { - dl.delim == dl2.delim && - dl.stream().eq_unspanned(&dl2.stream()) + (&TokenTree::Delimited(_, delim, ref tts), + &TokenTree::Delimited(_, delim2, ref tts2)) => { + delim == delim2 && + tts.stream().eq_unspanned(&tts2.stream()) } (_, _) => false, } @@ -134,9 +89,10 @@ impl TokenTree { (&TokenTree::Token(_, ref tk), &TokenTree::Token(_, ref tk2)) => { tk.probably_equal_for_proc_macro(tk2) } - (&TokenTree::Delimited(_, ref dl), &TokenTree::Delimited(_, ref dl2)) => { - dl.delim == dl2.delim && - dl.stream().probably_equal_for_proc_macro(&dl2.stream()) + (&TokenTree::Delimited(_, delim, ref tts), + &TokenTree::Delimited(_, delim2, ref tts2)) => { + delim == delim2 && + tts.stream().probably_equal_for_proc_macro(&tts2.stream()) } (_, _) => false, } @@ -146,7 +102,7 @@ impl TokenTree { pub fn span(&self) -> Span { match *self { TokenTree::Token(sp, _) => sp, - TokenTree::Delimited(sp, _) => sp.entire(), + TokenTree::Delimited(sp, ..) => sp.entire(), } } @@ -154,7 +110,7 @@ impl TokenTree { pub fn set_span(&mut self, span: Span) { match *self { TokenTree::Token(ref mut sp, _) => *sp = span, - TokenTree::Delimited(ref mut sp, _) => *sp = DelimSpan::from_single(span), + TokenTree::Delimited(ref mut sp, ..) => *sp = DelimSpan::from_single(span), } } @@ -167,7 +123,27 @@ impl TokenTree { } pub fn joint(self) -> TokenStream { - TokenStream { kind: TokenStreamKind::JointTree(self) } + TokenStream::JointTree(self) + } + + /// Returns the opening delimiter as a token tree. + pub fn open_tt(span: Span, delim: DelimToken) -> TokenTree { + let open_span = if span.is_dummy() { + span + } else { + span.with_hi(span.lo() + BytePos(delim.len() as u32)) + }; + TokenTree::Token(open_span, token::OpenDelim(delim)) + } + + /// Returns the closing delimiter as a token tree. + pub fn close_tt(span: Span, delim: DelimToken) -> TokenTree { + let close_span = if span.is_dummy() { + span + } else { + span.with_lo(span.hi() - BytePos(delim.len() as u32)) + }; + TokenTree::Token(close_span, token::CloseDelim(delim)) } } @@ -178,61 +154,57 @@ impl TokenTree { /// instead of a representation of the abstract syntax tree. /// Today's `TokenTree`s can still contain AST via `Token::Interpolated` for back-compat. #[derive(Clone, Debug)] -pub struct TokenStream { - kind: TokenStreamKind, +pub enum TokenStream { + Empty, + Tree(TokenTree), + JointTree(TokenTree), + Stream(Lrc>), } +// `TokenStream` is used a lot. Make sure it doesn't unintentionally get bigger. +#[cfg(target_arch = "x86_64")] +static_assert!(MEM_SIZE_OF_TOKEN_STREAM: mem::size_of::() == 32); + impl TokenStream { /// Given a `TokenStream` with a `Stream` of only two arguments, return a new `TokenStream` /// separating the two arguments with a comma for diagnostic suggestions. pub(crate) fn add_comma(&self) -> Option<(TokenStream, Span)> { // Used to suggest if a user writes `foo!(a b);` - if let TokenStreamKind::Stream(ref slice) = self.kind { + if let TokenStream::Stream(ref stream) = self { let mut suggestion = None; - let mut iter = slice.iter().enumerate().peekable(); + let mut iter = stream.iter().enumerate().peekable(); while let Some((pos, ts)) = iter.next() { if let Some((_, next)) = iter.peek() { - let sp = match (&ts.kind, &next.kind) { - (TokenStreamKind::Tree(TokenTree::Token(_, token::Token::Comma)), _) | - (_, TokenStreamKind::Tree(TokenTree::Token(_, token::Token::Comma))) => { + let sp = match (&ts, &next) { + (TokenStream::Tree(TokenTree::Token(_, token::Token::Comma)), _) | + (_, TokenStream::Tree(TokenTree::Token(_, token::Token::Comma))) => { continue; } - (TokenStreamKind::Tree(TokenTree::Token(sp, _)), _) => *sp, - (TokenStreamKind::Tree(TokenTree::Delimited(sp, _)), _) => sp.entire(), + (TokenStream::Tree(TokenTree::Token(sp, _)), _) => *sp, + (TokenStream::Tree(TokenTree::Delimited(sp, ..)), _) => sp.entire(), _ => continue, }; let sp = sp.shrink_to_hi(); - let comma = TokenStream { - kind: TokenStreamKind::Tree(TokenTree::Token(sp, token::Comma)), - }; + let comma = TokenStream::Tree(TokenTree::Token(sp, token::Comma)); suggestion = Some((pos, comma, sp)); } } if let Some((pos, comma, sp)) = suggestion { - let mut new_slice = vec![]; - let parts = slice.split_at(pos + 1); - new_slice.extend_from_slice(parts.0); - new_slice.push(comma); - new_slice.extend_from_slice(parts.1); - let slice = RcVec::new(new_slice); - return Some((TokenStream { kind: TokenStreamKind::Stream(slice) }, sp)); + let mut new_stream = vec![]; + let parts = stream.split_at(pos + 1); + new_stream.extend_from_slice(parts.0); + new_stream.push(comma); + new_stream.extend_from_slice(parts.1); + return Some((TokenStream::new(new_stream), sp)); } } None } } -#[derive(Clone, Debug)] -enum TokenStreamKind { - Empty, - Tree(TokenTree), - JointTree(TokenTree), - Stream(RcVec), -} - impl From for TokenStream { fn from(tt: TokenTree) -> TokenStream { - TokenStream { kind: TokenStreamKind::Tree(tt) } + TokenStream::Tree(tt) } } @@ -244,29 +216,29 @@ impl From for TokenStream { impl> iter::FromIterator for TokenStream { fn from_iter>(iter: I) -> Self { - TokenStream::concat(iter.into_iter().map(Into::into).collect::>()) + TokenStream::new(iter.into_iter().map(Into::into).collect::>()) } } impl Extend for TokenStream { fn extend>(&mut self, iter: I) { let iter = iter.into_iter(); - let kind = mem::replace(&mut self.kind, TokenStreamKind::Empty); + let this = mem::replace(self, TokenStream::Empty); // Vector of token streams originally in self. - let tts: Vec = match kind { - TokenStreamKind::Empty => { + let tts: Vec = match this { + TokenStream::Empty => { let mut vec = Vec::new(); vec.reserve(iter.size_hint().0); vec } - TokenStreamKind::Tree(_) | TokenStreamKind::JointTree(_) => { + TokenStream::Tree(_) | TokenStream::JointTree(_) => { let mut vec = Vec::new(); vec.reserve(1 + iter.size_hint().0); - vec.push(TokenStream { kind }); + vec.push(this); vec } - TokenStreamKind::Stream(rc_vec) => match RcVec::try_unwrap(rc_vec) { + TokenStream::Stream(rc_vec) => match Lrc::try_unwrap(rc_vec) { Ok(mut vec) => { // Extend in place using the existing capacity if possible. // This is the fast path for libraries like `quote` that @@ -293,12 +265,7 @@ impl Extend for TokenStream { // Build the resulting token stream. If it contains more than one token, // preserve capacity in the vector in anticipation of the caller // performing additional calls to extend. - let mut tts = builder.0; - *self = match tts.len() { - 0 => TokenStream::empty(), - 1 => tts.pop().unwrap(), - _ => TokenStream::concat_rc_vec(RcVec::new_preserving_capacity(tts)), - }; + *self = TokenStream::new(builder.0); } } @@ -312,7 +279,7 @@ impl PartialEq for TokenStream { impl TokenStream { pub fn len(&self) -> usize { - if let TokenStreamKind::Stream(ref slice) = self.kind { + if let TokenStream::Stream(ref slice) = self { slice.len() } else { 0 @@ -320,28 +287,24 @@ impl TokenStream { } pub fn empty() -> TokenStream { - TokenStream { kind: TokenStreamKind::Empty } + TokenStream::Empty } pub fn is_empty(&self) -> bool { - match self.kind { - TokenStreamKind::Empty => true, + match self { + TokenStream::Empty => true, _ => false, } } - pub fn concat(mut streams: Vec) -> TokenStream { + pub fn new(mut streams: Vec) -> TokenStream { match streams.len() { 0 => TokenStream::empty(), 1 => streams.pop().unwrap(), - _ => TokenStream::concat_rc_vec(RcVec::new(streams)), + _ => TokenStream::Stream(Lrc::new(streams)), } } - fn concat_rc_vec(streams: RcVec) -> TokenStream { - TokenStream { kind: TokenStreamKind::Stream(streams) } - } - pub fn trees(&self) -> Cursor { self.clone().into_trees() } @@ -385,7 +348,9 @@ impl TokenStream { | TokenTree::Token(_, Token::Semi) // The pretty printer collapses whitespace arbitrarily and can // introduce whitespace from `NoDelim`. - | TokenTree::Token(_, Token::Whitespace) => false, + | TokenTree::Token(_, Token::Whitespace) + // The pretty printer can turn `$crate` into `::crate_name` + | TokenTree::Token(_, Token::ModSep) => false, _ => true } } @@ -403,9 +368,9 @@ impl TokenStream { /// Precondition: `self` consists of a single token tree. /// Returns true if the token tree is a joint operation w.r.t. `proc_macro::TokenNode`. pub fn as_tree(self) -> (TokenTree, bool /* joint? */) { - match self.kind { - TokenStreamKind::Tree(tree) => (tree, false), - TokenStreamKind::JointTree(tree) => (tree, true), + match self { + TokenStream::Tree(tree) => (tree, false), + TokenStream::JointTree(tree) => (tree, true), _ => unreachable!(), } } @@ -415,43 +380,43 @@ impl TokenStream { let mut result = Vec::new(); let mut i = 0; while let Some(stream) = trees.next_as_stream() { - result.push(match stream.kind { - TokenStreamKind::Tree(tree) => f(i, tree).into(), - TokenStreamKind::JointTree(tree) => f(i, tree).joint(), + result.push(match stream { + TokenStream::Tree(tree) => f(i, tree).into(), + TokenStream::JointTree(tree) => f(i, tree).joint(), _ => unreachable!() }); i += 1; } - TokenStream::concat(result) + TokenStream::new(result) } pub fn map TokenTree>(self, mut f: F) -> TokenStream { let mut trees = self.into_trees(); let mut result = Vec::new(); while let Some(stream) = trees.next_as_stream() { - result.push(match stream.kind { - TokenStreamKind::Tree(tree) => f(tree).into(), - TokenStreamKind::JointTree(tree) => f(tree).joint(), + result.push(match stream { + TokenStream::Tree(tree) => f(tree).into(), + TokenStream::JointTree(tree) => f(tree).joint(), _ => unreachable!() }); } - TokenStream::concat(result) + TokenStream::new(result) } fn first_tree_and_joint(&self) -> Option<(TokenTree, bool)> { - match self.kind { - TokenStreamKind::Empty => None, - TokenStreamKind::Tree(ref tree) => Some((tree.clone(), false)), - TokenStreamKind::JointTree(ref tree) => Some((tree.clone(), true)), - TokenStreamKind::Stream(ref stream) => stream.first().unwrap().first_tree_and_joint(), + match self { + TokenStream::Empty => None, + TokenStream::Tree(ref tree) => Some((tree.clone(), false)), + TokenStream::JointTree(ref tree) => Some((tree.clone(), true)), + TokenStream::Stream(ref stream) => stream.first().unwrap().first_tree_and_joint(), } } fn last_tree_if_joint(&self) -> Option { - match self.kind { - TokenStreamKind::Empty | TokenStreamKind::Tree(..) => None, - TokenStreamKind::JointTree(ref tree) => Some(tree.clone()), - TokenStreamKind::Stream(ref stream) => stream.last().unwrap().last_tree_if_joint(), + match self { + TokenStream::Empty | TokenStream::Tree(..) => None, + TokenStream::JointTree(ref tree) => Some(tree.clone()), + TokenStream::Stream(ref stream) => stream.last().unwrap().last_tree_if_joint(), } } } @@ -494,28 +459,28 @@ impl TokenStreamBuilder { } pub fn build(self) -> TokenStream { - TokenStream::concat(self.0) + TokenStream::new(self.0) } fn push_all_but_last_tree(&mut self, stream: &TokenStream) { - if let TokenStreamKind::Stream(ref streams) = stream.kind { + if let TokenStream::Stream(ref streams) = stream { let len = streams.len(); match len { 1 => {} 2 => self.0.push(streams[0].clone().into()), - _ => self.0.push(TokenStream::concat_rc_vec(streams.sub_slice(0 .. len - 1))), + _ => self.0.push(TokenStream::new(streams[0 .. len - 1].to_vec())), } self.push_all_but_last_tree(&streams[len - 1]) } } fn push_all_but_first_tree(&mut self, stream: &TokenStream) { - if let TokenStreamKind::Stream(ref streams) = stream.kind { + if let TokenStream::Stream(ref streams) = stream { let len = streams.len(); match len { 1 => {} 2 => self.0.push(streams[1].clone().into()), - _ => self.0.push(TokenStream::concat_rc_vec(streams.sub_slice(1 .. len))), + _ => self.0.push(TokenStream::new(streams[1 .. len].to_vec())), } self.push_all_but_first_tree(&streams[0]) } @@ -535,13 +500,13 @@ enum CursorKind { #[derive(Clone)] struct StreamCursor { - stream: RcVec, + stream: Lrc>, index: usize, - stack: Vec<(RcVec, usize)>, + stack: Vec<(Lrc>, usize)>, } impl StreamCursor { - fn new(stream: RcVec) -> Self { + fn new(stream: Lrc>) -> Self { StreamCursor { stream: stream, index: 0, stack: Vec::new() } } @@ -550,10 +515,10 @@ impl StreamCursor { if self.index < self.stream.len() { self.index += 1; let next = self.stream[self.index - 1].clone(); - match next.kind { - TokenStreamKind::Tree(..) | TokenStreamKind::JointTree(..) => return Some(next), - TokenStreamKind::Stream(stream) => self.insert(stream), - TokenStreamKind::Empty => {} + match next { + TokenStream::Tree(..) | TokenStream::JointTree(..) => return Some(next), + TokenStream::Stream(stream) => self.insert(stream), + TokenStream::Empty => {} } } else if let Some((stream, index)) = self.stack.pop() { self.stream = stream; @@ -564,7 +529,7 @@ impl StreamCursor { } } - fn insert(&mut self, stream: RcVec) { + fn insert(&mut self, stream: Lrc>) { self.stack.push((mem::replace(&mut self.stream, stream), mem::replace(&mut self.index, 0))); } @@ -574,8 +539,8 @@ impl Iterator for Cursor { type Item = TokenTree; fn next(&mut self) -> Option { - self.next_as_stream().map(|stream| match stream.kind { - TokenStreamKind::Tree(tree) | TokenStreamKind::JointTree(tree) => tree, + self.next_as_stream().map(|stream| match stream { + TokenStream::Tree(tree) | TokenStream::JointTree(tree) => tree, _ => unreachable!() }) } @@ -583,11 +548,11 @@ impl Iterator for Cursor { impl Cursor { fn new(stream: TokenStream) -> Self { - Cursor(match stream.kind { - TokenStreamKind::Empty => CursorKind::Empty, - TokenStreamKind::Tree(tree) => CursorKind::Tree(tree, false), - TokenStreamKind::JointTree(tree) => CursorKind::JointTree(tree, false), - TokenStreamKind::Stream(stream) => CursorKind::Stream(StreamCursor::new(stream)), + Cursor(match stream { + TokenStream::Empty => CursorKind::Empty, + TokenStream::Tree(tree) => CursorKind::Tree(tree, false), + TokenStream::JointTree(tree) => CursorKind::JointTree(tree, false), + TokenStream::Stream(stream) => CursorKind::Stream(StreamCursor::new(stream)), }) } @@ -610,7 +575,7 @@ impl Cursor { _ if stream.is_empty() => return, CursorKind::Empty => *self = stream.trees(), CursorKind::Tree(_, consumed) | CursorKind::JointTree(_, consumed) => { - *self = TokenStream::concat(vec![self.original_stream(), stream]).trees(); + *self = TokenStream::new(vec![self.original_stream(), stream]).trees(); if consumed { self.next(); } @@ -626,21 +591,21 @@ impl Cursor { CursorKind::Empty => TokenStream::empty(), CursorKind::Tree(ref tree, _) => tree.clone().into(), CursorKind::JointTree(ref tree, _) => tree.clone().joint(), - CursorKind::Stream(ref cursor) => TokenStream::concat_rc_vec({ + CursorKind::Stream(ref cursor) => TokenStream::Stream( cursor.stack.get(0).cloned().map(|(stream, _)| stream) .unwrap_or_else(|| cursor.stream.clone()) - }), + ), } } pub fn look_ahead(&self, n: usize) -> Option { fn look_ahead(streams: &[TokenStream], mut n: usize) -> Result { for stream in streams { - n = match stream.kind { - TokenStreamKind::Tree(ref tree) | TokenStreamKind::JointTree(ref tree) + n = match stream { + TokenStream::Tree(ref tree) | TokenStream::JointTree(ref tree) if n == 0 => return Ok(tree.clone()), - TokenStreamKind::Tree(..) | TokenStreamKind::JointTree(..) => n - 1, - TokenStreamKind::Stream(ref stream) => match look_ahead(stream, n) { + TokenStream::Tree(..) | TokenStream::JointTree(..) => n - 1, + TokenStream::Stream(ref stream) => match look_ahead(stream, n) { Ok(tree) => return Ok(tree), Err(n) => n, }, @@ -676,22 +641,28 @@ impl Cursor { /// `ThinTokenStream` is smaller, but needs to allocate to represent a single `TokenTree`. /// We must use `ThinTokenStream` in `TokenTree::Delimited` to avoid infinite size due to recursion. #[derive(Debug, Clone)] -pub struct ThinTokenStream(Option>); +pub struct ThinTokenStream(Option>>); + +impl ThinTokenStream { + pub fn stream(&self) -> TokenStream { + self.clone().into() + } +} impl From for ThinTokenStream { fn from(stream: TokenStream) -> ThinTokenStream { - ThinTokenStream(match stream.kind { - TokenStreamKind::Empty => None, - TokenStreamKind::Tree(tree) => Some(RcVec::new(vec![tree.into()])), - TokenStreamKind::JointTree(tree) => Some(RcVec::new(vec![tree.joint()])), - TokenStreamKind::Stream(stream) => Some(stream), + ThinTokenStream(match stream { + TokenStream::Empty => None, + TokenStream::Tree(tree) => Some(Lrc::new(vec![tree.into()])), + TokenStream::JointTree(tree) => Some(Lrc::new(vec![tree.joint()])), + TokenStream::Stream(stream) => Some(stream), }) } } impl From for TokenStream { fn from(stream: ThinTokenStream) -> TokenStream { - stream.0.map(TokenStream::concat_rc_vec).unwrap_or_else(TokenStream::empty) + stream.0.map(TokenStream::Stream).unwrap_or_else(TokenStream::empty) } } @@ -790,7 +761,7 @@ mod tests { let test_res = string_to_ts("foo::bar::baz"); let test_fst = string_to_ts("foo::bar"); let test_snd = string_to_ts("::baz"); - let eq_res = TokenStream::concat(vec![test_fst, test_snd]); + let eq_res = TokenStream::new(vec![test_fst, test_snd]); assert_eq!(test_res.trees().count(), 5); assert_eq!(eq_res.trees().count(), 5); assert_eq!(test_res.eq_unspanned(&eq_res), true); diff --git a/src/libsyntax/util/lev_distance.rs b/src/libsyntax/util/lev_distance.rs index feee2422cb6..e6b81a59d86 100644 --- a/src/libsyntax/util/lev_distance.rs +++ b/src/libsyntax/util/lev_distance.rs @@ -20,7 +20,7 @@ pub fn lev_distance(a: &str, b: &str) -> usize { return a.chars().count(); } - let mut dcol: Vec<_> = (0..b.len() + 1).collect(); + let mut dcol: Vec<_> = (0..=b.len()).collect(); let mut t_last = 0; for (i, sc) in a.chars().enumerate() { @@ -38,7 +38,8 @@ pub fn lev_distance(a: &str, b: &str) -> usize { current = next; t_last = j; } - } dcol[t_last + 1] + } + dcol[t_last + 1] } /// Find the best match for a given word in the given iterator diff --git a/src/libsyntax/util/parser.rs b/src/libsyntax/util/parser.rs index 6866806cd7c..b7cd2acf8a5 100644 --- a/src/libsyntax/util/parser.rs +++ b/src/libsyntax/util/parser.rs @@ -340,8 +340,8 @@ impl ExprPrecedence { } -/// Expressions that syntactically contain an "exterior" struct literal i.e. not surrounded by any -/// parens or other delimiters, e.g. `X { y: 1 }`, `X { y: 1 }.method()`, `foo == X { y: 1 }` and +/// Expressions that syntactically contain an "exterior" struct literal i.e., not surrounded by any +/// parens or other delimiters, e.g., `X { y: 1 }`, `X { y: 1 }.method()`, `foo == X { y: 1 }` and /// `X { y: 1 } == foo` all do, but `(X { y: 1 }) == foo` does not. pub fn contains_exterior_struct_lit(value: &ast::Expr) -> bool { match value.node { diff --git a/src/libsyntax/util/rc_slice.rs b/src/libsyntax/util/rc_slice.rs deleted file mode 100644 index 520b7a48e30..00000000000 --- a/src/libsyntax/util/rc_slice.rs +++ /dev/null @@ -1,64 +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. - -use std::fmt; -use std::ops::{Deref, Range}; -use rustc_data_structures::sync::Lrc; - -use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult, - HashStable}; - -#[derive(Clone)] -pub struct RcSlice { - data: Lrc>, - offset: u32, - len: u32, -} - -impl RcSlice { - pub fn new(vec: Vec) -> Self { - RcSlice { - offset: 0, - len: vec.len() as u32, - data: Lrc::new(vec.into_boxed_slice()), - } - } - - pub fn sub_slice(&self, range: Range) -> Self { - RcSlice { - data: self.data.clone(), - offset: self.offset + range.start as u32, - len: (range.end - range.start) as u32, - } - } -} - -impl Deref for RcSlice { - type Target = [T]; - fn deref(&self) -> &[T] { - &self.data[self.offset as usize .. (self.offset + self.len) as usize] - } -} - -impl fmt::Debug for RcSlice { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(self.deref(), f) - } -} - -impl HashStable for RcSlice - where T: HashStable -{ - fn hash_stable(&self, - hcx: &mut CTX, - hasher: &mut StableHasher) { - (**self).hash_stable(hcx, hasher); - } -} diff --git a/src/libsyntax/util/rc_vec.rs b/src/libsyntax/util/rc_vec.rs deleted file mode 100644 index 99fbce1ad91..00000000000 --- a/src/libsyntax/util/rc_vec.rs +++ /dev/null @@ -1,90 +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. - -use std::fmt; -use std::ops::{Deref, Range}; - -use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; -use rustc_data_structures::sync::Lrc; - -#[derive(Clone)] -pub struct RcVec { - data: Lrc>, - offset: u32, - len: u32, -} - -impl RcVec { - pub fn new(mut vec: Vec) -> Self { - // By default, constructing RcVec from Vec gives it just enough capacity - // to hold the initial elements. Callers that anticipate needing to - // extend the vector may prefer RcVec::new_preserving_capacity. - vec.shrink_to_fit(); - Self::new_preserving_capacity(vec) - } - - pub fn new_preserving_capacity(vec: Vec) -> Self { - RcVec { - offset: 0, - len: vec.len() as u32, - data: Lrc::new(vec), - } - } - - pub fn sub_slice(&self, range: Range) -> Self { - RcVec { - data: self.data.clone(), - offset: self.offset + range.start as u32, - len: (range.end - range.start) as u32, - } - } - - /// If this RcVec has exactly one strong reference, returns ownership of the - /// underlying vector. Otherwise returns self unmodified. - pub fn try_unwrap(self) -> Result, Self> { - match Lrc::try_unwrap(self.data) { - // If no other RcVec shares ownership of this data. - Ok(mut vec) => { - // Drop any elements after our view of the data. - vec.truncate(self.offset as usize + self.len as usize); - // Drop any elements before our view of the data. Do this after - // the `truncate` so that elements past the end of our view do - // not need to be copied around. - vec.drain(..self.offset as usize); - Ok(vec) - } - - // If the data is shared. - Err(data) => Err(RcVec { data, ..self }), - } - } -} - -impl Deref for RcVec { - type Target = [T]; - fn deref(&self) -> &[T] { - &self.data[self.offset as usize..(self.offset + self.len) as usize] - } -} - -impl fmt::Debug for RcVec { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(self.deref(), f) - } -} - -impl HashStable for RcVec -where - T: HashStable, -{ - fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { - (**self).hash_stable(hcx, hasher); - } -} diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 77311bf53fd..6747598f375 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -43,7 +43,7 @@ pub enum FnKind<'a> { /// Each method of the Visitor trait is a hook to be potentially /// overridden. Each method's default implementation recursively visits /// the substructure of the input via the corresponding `walk` method; -/// e.g. the `visit_mod` method by default calls `visit::walk_mod`. +/// e.g., the `visit_mod` method by default calls `visit::walk_mod`. /// /// If you want to ensure that your code handles every variant /// explicitly, you need to override each method. (And you also need @@ -110,7 +110,7 @@ pub trait Visitor<'ast>: Sized { } fn visit_mac(&mut self, _mac: &'ast Mac) { panic!("visit_mac disabled by default"); - // NB: see note about macros above. + // N.B., see note about macros above. // if you really want a visitor that // works on macros, use this // definition in your trait impl: @@ -841,7 +841,7 @@ pub fn walk_attribute<'a, V: Visitor<'a>>(visitor: &mut V, attr: &'a Attribute) pub fn walk_tt<'a, V: Visitor<'a>>(visitor: &mut V, tt: TokenTree) { match tt { TokenTree::Token(_, tok) => visitor.visit_token(tok), - TokenTree::Delimited(_, delimed) => visitor.visit_tts(delimed.stream()), + TokenTree::Delimited(_, _, tts) => visitor.visit_tts(tts.stream()), } } diff --git a/src/libsyntax_ext/Cargo.toml b/src/libsyntax_ext/Cargo.toml index 4979d0b3e92..7ad08f75e8b 100644 --- a/src/libsyntax_ext/Cargo.toml +++ b/src/libsyntax_ext/Cargo.toml @@ -15,5 +15,5 @@ syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_target = { path = "../librustc_target" } -smallvec = { version = "0.6.5", features = ["union"] } +smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } log = "0.4" diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs index 026ddccd7be..2ff9fb487c4 100644 --- a/src/libsyntax_ext/asm.rs +++ b/src/libsyntax_ext/asm.rs @@ -47,7 +47,7 @@ impl State { } } -const OPTIONS: &'static [&'static str] = &["volatile", "alignstack", "intel"]; +const OPTIONS: &[&str] = &["volatile", "alignstack", "intel"]; pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, diff --git a/src/libsyntax_ext/assert.rs b/src/libsyntax_ext/assert.rs index e3bd2ca0131..a2384b59048 100644 --- a/src/libsyntax_ext/assert.rs +++ b/src/libsyntax_ext/assert.rs @@ -24,6 +24,14 @@ pub fn expand_assert<'cx>( tts: &[TokenTree], ) -> Box { let mut parser = cx.new_parser_from_tts(tts); + + if parser.token == token::Eof { + cx.struct_span_err(sp, "macro requires a boolean expression as an argument") + .span_label(sp, "boolean expression required") + .emit(); + return DummyResult::expr(sp); + } + let cond_expr = panictry!(parser.parse_expr()); let custom_msg_args = if parser.eat(&token::Comma) { let ts = parser.parse_tokens(); diff --git a/src/libsyntax_ext/deriving/clone.rs b/src/libsyntax_ext/deriving/clone.rs index ec935b3e72f..b9e0933331c 100644 --- a/src/libsyntax_ext/deriving/clone.rs +++ b/src/libsyntax_ext/deriving/clone.rs @@ -140,7 +140,7 @@ fn cs_clone_shallow(name: &str, let mut stmts = Vec::new(); if is_union { // let _: AssertParamIsCopy; - let self_ty = cx.ty_path(cx.path_ident(trait_span, keywords::SelfType.ident())); + let self_ty = cx.ty_path(cx.path_ident(trait_span, keywords::SelfUpper.ident())); assert_ty_bounds(cx, &mut stmts, self_ty, trait_span, "AssertParamIsCopy"); } else { match *substr.fields { diff --git a/src/libsyntax_ext/deriving/cmp/partial_ord.rs b/src/libsyntax_ext/deriving/cmp/partial_ord.rs index 32a58de3529..196cfa5fe35 100644 --- a/src/libsyntax_ext/deriving/cmp/partial_ord.rs +++ b/src/libsyntax_ext/deriving/cmp/partial_ord.rs @@ -227,7 +227,7 @@ fn cs_op(less: bool, let fold = cs_fold1(false, // need foldr |cx, span, subexpr, self_f, other_fs| { // build up a series of `partial_cmp`s from the inside - // out (hence foldr) to get lexical ordering, i.e. for op == + // out (hence foldr) to get lexical ordering, i.e., for op == // `ast::lt` // // ``` diff --git a/src/libsyntax_ext/deriving/custom.rs b/src/libsyntax_ext/deriving/custom.rs index 5c82d191138..cc2fa685687 100644 --- a/src/libsyntax_ext/deriving/custom.rs +++ b/src/libsyntax_ext/deriving/custom.rs @@ -74,7 +74,6 @@ impl MultiItemModifier for ProcMacroDerive { // Mark attributes as known, and used. MarkAttrs(&self.attrs).visit_item(&item); - let item = ecx.resolver.eliminate_crate_var(item); let token = Token::interpolated(token::NtItem(item)); let input = tokenstream::TokenTree::Token(DUMMY_SP, token).into(); diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index a5b12ce4c4d..443fd48120e 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -18,7 +18,7 @@ //! - Methods taking any number of parameters of any type, and returning //! any type, other than vectors, bottom and closures. //! - Generating `impl`s for types with type parameters and lifetimes -//! (e.g. `Option`), the parameters are automatically given the +//! (e.g., `Option`), the parameters are automatically given the //! current trait as a bound. (This includes separate type parameters //! and lifetimes for methods.) //! - Additional bounds on the type parameters (`TraitDef.additional_bounds`) @@ -30,9 +30,9 @@ //! - `Struct`, when `Self` is a struct (including tuple structs, e.g //! `struct T(i32, char)`). //! - `EnumMatching`, when `Self` is an enum and all the arguments are the -//! same variant of the enum (e.g. `Some(1)`, `Some(3)` and `Some(4)`) +//! same variant of the enum (e.g., `Some(1)`, `Some(3)` and `Some(4)`) //! - `EnumNonMatchingCollapsed` when `Self` is an enum and the arguments -//! are not the same variant (e.g. `None`, `Some(1)` and `None`). +//! are not the same variant (e.g., `None`, `Some(1)` and `None`). //! - `StaticEnum` and `StaticStruct` for static methods, where the type //! being derived upon is either an enum or struct respectively. (Any //! argument with type Self is just grouped among the non-self @@ -224,7 +224,7 @@ pub struct TraitDef<'a> { /// other than the current trait pub additional_bounds: Vec>, - /// Any extra lifetimes and/or bounds, e.g. `D: serialize::Decoder` + /// Any extra lifetimes and/or bounds, e.g., `D: serialize::Decoder` pub generics: LifetimeBounds<'a>, /// Is it an `unsafe` trait? @@ -242,10 +242,10 @@ pub struct TraitDef<'a> { pub struct MethodDef<'a> { /// name of the method pub name: &'a str, - /// List of generics, e.g. `R: rand::Rng` + /// List of generics, e.g., `R: rand::Rng` pub generics: LifetimeBounds<'a>, - /// Whether there is a self argument (outer Option) i.e. whether + /// Whether there is a self argument (outer Option) i.e., whether /// this is a static function, and whether it is a pointer (inner /// Option) pub explicit_self: Option>>, @@ -938,7 +938,7 @@ impl<'a> MethodDef<'a> { let args = { let self_args = explicit_self.map(|explicit_self| { ast::Arg::from_self(explicit_self, - keywords::SelfValue.ident().with_span_pos(trait_.span)) + keywords::SelfLower.ident().with_span_pos(trait_.span)) }); let nonself_args = arg_types.into_iter() .map(|(name, ty)| cx.arg(trait_.span, name, ty)); @@ -1371,7 +1371,7 @@ impl<'a> MethodDef<'a> { // that type. Otherwise casts to `i32` (the default repr // type). // - // i.e. for `enum E { A, B(1), C(T, T) }`, and a deriving + // i.e., for `enum E { A, B(1), C(T, T) }`, and a deriving // with three Self args, builds three statements: // // ``` @@ -1489,8 +1489,8 @@ impl<'a> MethodDef<'a> { // // (See also #4499 and #12609; note that some of the // discussions there influence what choice we make here; - // e.g. if we feature-gate `match x { ... }` when x refers - // to an uninhabited type (e.g. a zero-variant enum or a + // e.g., if we feature-gate `match x { ... }` when x refers + // to an uninhabited type (e.g., a zero-variant enum or a // type holding such an enum), but do not feature-gate // zero-variant enums themselves, then attempting to // derive Debug on such a type could here generate code diff --git a/src/libsyntax_ext/deriving/generic/ty.rs b/src/libsyntax_ext/deriving/generic/ty.rs index fa284f4ab0e..11689a98a79 100644 --- a/src/libsyntax_ext/deriving/generic/ty.rs +++ b/src/libsyntax_ext/deriving/generic/ty.rs @@ -32,7 +32,7 @@ pub enum PtrTy<'a> { Raw(ast::Mutability), } -/// A path, e.g. `::std::option::Option::` (global). Has support +/// A path, e.g., `::std::option::Option::` (global). Has support /// for type parameters and a lifetime. #[derive(Clone)] pub struct Path<'a> { diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 31e608de1f8..41799eede9e 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -158,28 +158,15 @@ fn parse_args(ecx: &mut ExtCtxt, } // accept trailing commas if named || (p.token.is_ident() && p.look_ahead(1, |t| *t == token::Eq)) { named = true; - let ident = match p.token { - token::Ident(i, _) => { - p.bump(); - i - } - _ if named => { - ecx.span_err( - p.span, - "expected ident, positional arguments cannot follow named arguments", - ); - return None; - } - _ => { - ecx.span_err( - p.span, - &format!( - "expected ident for named argument, found `{}`", - p.this_token_to_string() - ), - ); - return None; - } + let ident = if let token::Ident(i, _) = p.token { + p.bump(); + i + } else { + ecx.span_err( + p.span, + "expected ident, positional arguments cannot follow named arguments", + ); + return None; }; let name: &str = &ident.as_str(); @@ -209,7 +196,7 @@ fn parse_args(ecx: &mut ExtCtxt, impl<'a, 'b> Context<'a, 'b> { fn resolve_name_inplace(&self, p: &mut parse::Piece) { // NOTE: the `unwrap_or` branch is needed in case of invalid format - // arguments, e.g. `format_args!("{foo}")`. + // arguments, e.g., `format_args!("{foo}")`. let lookup = |s| *self.names.get(s).unwrap_or(&0); match *p { @@ -286,11 +273,11 @@ impl<'a, 'b> Context<'a, 'b> { } else { MultiSpan::from_span(self.fmtsp) }; - let mut refs: Vec<_> = self + let refs_len = self.invalid_refs.len(); + let mut refs = self .invalid_refs .iter() - .map(|(r, pos)| (r.to_string(), self.arg_spans.get(*pos))) - .collect(); + .map(|(r, pos)| (r.to_string(), self.arg_spans.get(*pos))); if self.names.is_empty() && !numbered_position_args { e = self.ecx.mut_span_err( @@ -303,28 +290,24 @@ impl<'a, 'b> Context<'a, 'b> { ), ); } else { - let (arg_list, mut sp) = match refs.len() { - 1 => { - let (reg, pos) = refs.pop().unwrap(); - ( - format!("argument {}", reg), - MultiSpan::from_span(*pos.unwrap_or(&self.fmtsp)), - ) - } - _ => { - let pos = - MultiSpan::from_spans(refs.iter().map(|(_, p)| *p.unwrap()).collect()); - let mut refs: Vec = refs.iter().map(|(s, _)| s.to_owned()).collect(); - let reg = refs.pop().unwrap(); - ( - format!( - "arguments {head} and {tail}", - tail = reg, - head = refs.join(", ") - ), - pos, - ) - } + let (arg_list, mut sp) = if refs_len == 1 { + let (reg, pos) = refs.next().unwrap(); + ( + format!("argument {}", reg), + MultiSpan::from_span(*pos.unwrap_or(&self.fmtsp)), + ) + } else { + let (mut refs, spans): (Vec<_>, Vec<_>) = refs.unzip(); + let pos = MultiSpan::from_spans(spans.into_iter().map(|s| *s.unwrap()).collect()); + let reg = refs.pop().unwrap(); + ( + format!( + "arguments {head} and {tail}", + head = refs.join(", "), + tail = reg, + ), + pos, + ) }; if !self.is_literal { sp = MultiSpan::from_span(self.fmtsp); @@ -353,33 +336,30 @@ impl<'a, 'b> Context<'a, 'b> { Placeholder(_) => { // record every (position, type) combination only once let ref mut seen_ty = self.arg_unique_types[arg]; - let i = match seen_ty.iter().position(|x| *x == ty) { - Some(i) => i, - None => { - let i = seen_ty.len(); - seen_ty.push(ty); - i - } - }; + let i = seen_ty.iter().position(|x| *x == ty).unwrap_or_else(|| { + let i = seen_ty.len(); + seen_ty.push(ty); + i + }); self.arg_types[arg].push(i); } Count => { - match self.count_positions.entry(arg) { - Entry::Vacant(e) => { - let i = self.count_positions_count; - e.insert(i); - self.count_args.push(Exact(arg)); - self.count_positions_count += 1; - } - Entry::Occupied(_) => {} + if let Entry::Vacant(e) = self.count_positions.entry(arg) { + let i = self.count_positions_count; + e.insert(i); + self.count_args.push(Exact(arg)); + self.count_positions_count += 1; } } } } Named(name) => { - let idx = match self.names.get(&name) { - Some(e) => *e, + match self.names.get(&name) { + Some(idx) => { + // Treat as positional arg. + self.verify_arg_type(Exact(*idx), ty) + } None => { let msg = format!("there is no argument named `{}`", name); let sp = if self.is_literal { @@ -389,11 +369,8 @@ impl<'a, 'b> Context<'a, 'b> { }; let mut err = self.ecx.struct_span_err(sp, &msg[..]); err.emit(); - return; } - }; - // Treat as positional arg. - self.verify_arg_type(Exact(idx), ty) + } } } } @@ -436,12 +413,10 @@ impl<'a, 'b> Context<'a, 'b> { parse::CountIs(i) => count("Is", Some(self.ecx.expr_usize(sp, i))), parse::CountIsParam(i) => { // This needs mapping too, as `i` is referring to a macro - // argument. - let i = match self.count_positions.get(&i) { - Some(&i) => i, - None => 0, // error already emitted elsewhere - }; - let i = i + self.count_args_index_offset; + // argument. If `i` is not found in `count_positions` then + // the error had already been emitted elsewhere. + let i = self.count_positions.get(&i).cloned().unwrap_or(0) + + self.count_args_index_offset; count("Param", Some(self.ecx.expr_usize(sp, i))) } parse::CountImplied => count("Implied", None), @@ -526,10 +501,7 @@ impl<'a, 'b> Context<'a, 'b> { }, }; - let fill = match arg.format.fill { - Some(c) => c, - None => ' ', - }; + let fill = arg.format.fill.unwrap_or(' '); if *arg != simple_arg || fill != ' ' { self.all_pieces_simple = false; @@ -828,8 +800,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, if !parser.errors.is_empty() { let err = parser.errors.remove(0); let sp = fmt.span.from_inner_byte_pos(err.start, err.end); - let mut e = ecx.struct_span_err(sp, &format!("invalid format string: {}", - err.description)); + let mut e = ecx.struct_span_err(sp, &format!("invalid format string: {}", err.description)); e.span_label(sp, err.label + " in format string"); if let Some(note) = err.note { e.note(¬e); diff --git a/src/libsyntax_ext/global_asm.rs b/src/libsyntax_ext/global_asm.rs index 1130a50537d..000bede7348 100644 --- a/src/libsyntax_ext/global_asm.rs +++ b/src/libsyntax_ext/global_asm.rs @@ -28,7 +28,7 @@ use syntax::symbol::Symbol; use syntax_pos::Span; use syntax::tokenstream; -pub const MACRO: &'static str = "global_asm"; +pub const MACRO: &str = "global_asm"; pub fn expand_global_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index 1d814a67876..c49d5772531 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -39,10 +39,6 @@ extern crate log; mod diagnostics; -#[macro_use] -// for custom_derive -pub mod deriving; - mod asm; mod assert; mod cfg; @@ -54,13 +50,14 @@ mod format; mod format_foreign; mod global_asm; mod log_syntax; -mod trace_macros; +mod proc_macro_server; mod test; mod test_case; +mod trace_macros; +pub mod deriving; pub mod proc_macro_decls; pub mod proc_macro_impl; -mod proc_macro_server; use rustc_data_structures::sync::Lrc; use syntax::ast; diff --git a/src/libsyntax_ext/proc_macro_decls.rs b/src/libsyntax_ext/proc_macro_decls.rs index c859275ed02..f4ff0989b5d 100644 --- a/src/libsyntax_ext/proc_macro_decls.rs +++ b/src/libsyntax_ext/proc_macro_decls.rs @@ -30,8 +30,7 @@ use syntax_pos::{Span, DUMMY_SP}; use deriving; -const PROC_MACRO_KINDS: [&'static str; 3] = - ["proc_macro_derive", "proc_macro_attribute", "proc_macro"]; +const PROC_MACRO_KINDS: [&str; 3] = ["proc_macro_derive", "proc_macro_attribute", "proc_macro"]; struct ProcMacroDerive { trait_name: ast::Name, diff --git a/src/libsyntax_ext/proc_macro_server.rs b/src/libsyntax_ext/proc_macro_server.rs index 4babc2e612f..ca960cbe41b 100644 --- a/src/libsyntax_ext/proc_macro_server.rs +++ b/src/libsyntax_ext/proc_macro_server.rs @@ -64,11 +64,11 @@ impl FromInternal<(TokenStream, &'_ ParseSess, &'_ mut Vec)> let (tree, joint) = stream.as_tree(); let (span, token) = match tree { - tokenstream::TokenTree::Delimited(span, delimed) => { - let delimiter = Delimiter::from_internal(delimed.delim); + tokenstream::TokenTree::Delimited(span, delim, tts) => { + let delimiter = Delimiter::from_internal(delim); return TokenTree::Group(Group { delimiter, - stream: delimed.tts.into(), + stream: tts.into(), span, }); } @@ -81,29 +81,23 @@ impl FromInternal<(TokenStream, &'_ ParseSess, &'_ mut Vec)> $($field $(: $value)*,)* span, }) - ) + ); + ($ty:ident::$method:ident($($value:expr),*)) => ( + TokenTree::$ty(self::$ty::$method($($value,)* span)) + ); } macro_rules! op { ($a:expr) => { - tt!(Punct { ch: $a, joint }) + tt!(Punct::new($a, joint)) }; ($a:expr, $b:expr) => {{ - stack.push(tt!(Punct { ch: $b, joint })); - tt!(Punct { - ch: $a, - joint: true - }) + stack.push(tt!(Punct::new($b, joint))); + tt!(Punct::new($a, true)) }}; ($a:expr, $b:expr, $c:expr) => {{ - stack.push(tt!(Punct { ch: $c, joint })); - stack.push(tt!(Punct { - ch: $b, - joint: true - })); - tt!(Punct { - ch: $a, - joint: true - }) + stack.push(tt!(Punct::new($c, joint))); + stack.push(tt!(Punct::new($b, true))); + tt!(Punct::new($a, true)) }}; } @@ -156,20 +150,13 @@ impl FromInternal<(TokenStream, &'_ ParseSess, &'_ mut Vec)> Question => op!('?'), SingleQuote => op!('\''), - Ident(ident, is_raw) => tt!(Ident { - sym: ident.name, - is_raw - }), + Ident(ident, false) if ident.name == keywords::DollarCrate.name() => + tt!(Ident::dollar_crate()), + Ident(ident, is_raw) => tt!(Ident::new(ident.name, is_raw)), Lifetime(ident) => { let ident = ident.without_first_quote(); - stack.push(tt!(Ident { - sym: ident.name, - is_raw: false - })); - tt!(Punct { - ch: '\'', - joint: true - }) + stack.push(tt!(Ident::new(ident.name, false))); + tt!(Punct::new('\'', true)) } Literal(lit, suffix) => tt!(Literal { lit, suffix }), DocComment(c) => { @@ -193,15 +180,9 @@ impl FromInternal<(TokenStream, &'_ ParseSess, &'_ mut Vec)> span: DelimSpan::from_single(span), })); if style == ast::AttrStyle::Inner { - stack.push(tt!(Punct { - ch: '!', - joint: false - })); + stack.push(tt!(Punct::new('!', false))); } - tt!(Punct { - ch: '#', - joint: false - }) + tt!(Punct::new('#', false)) } Interpolated(_) => { @@ -232,14 +213,12 @@ impl ToInternal for TokenTree { }) => { return tokenstream::TokenTree::Delimited( span, - tokenstream::Delimited { - delim: delimiter.to_internal(), - tts: stream.into(), - }, + delimiter.to_internal(), + stream.into(), ) .into(); } - TokenTree::Ident(self::Ident { sym, span, is_raw }) => { + TokenTree::Ident(self::Ident { sym, is_raw, span }) => { let token = Ident(ast::Ident::new(sym, span), is_raw); return tokenstream::TokenTree::Token(span, token).into(); } @@ -340,11 +319,52 @@ pub struct Punct { span: Span, } +impl Punct { + fn new(ch: char, joint: bool, span: Span) -> Punct { + const LEGAL_CHARS: &[char] = &['=', '<', '>', '!', '~', '+', '-', '*', '/', '%', '^', + '&', '|', '@', '.', ',', ';', ':', '#', '$', '?', '\'']; + if !LEGAL_CHARS.contains(&ch) { + panic!("unsupported character `{:?}`", ch) + } + Punct { ch, joint, span } + } +} + #[derive(Copy, Clone, PartialEq, Eq, Hash)] pub struct Ident { sym: Symbol, - span: Span, is_raw: bool, + span: Span, +} + +impl Ident { + fn is_valid(string: &str) -> bool { + let mut chars = string.chars(); + if let Some(start) = chars.next() { + (start == '_' || start.is_xid_start()) + && chars.all(|cont| cont == '_' || cont.is_xid_continue()) + } else { + false + } + } + fn new(sym: Symbol, is_raw: bool, span: Span) -> Ident { + let string = sym.as_str().get(); + if !Self::is_valid(string) { + panic!("`{:?}` is not a valid identifier", string) + } + if is_raw { + let normalized_sym = Symbol::intern(string); + if normalized_sym == keywords::Underscore.name() || + ast::Ident::with_empty_ctxt(normalized_sym).is_path_segment_keyword() { + panic!("`{:?}` is not a valid raw identifier", string) + } + } + Ident { sym, is_raw, span } + } + fn dollar_crate(span: Span) -> Ident { + // `$crate` is accepted as an ident only if it comes from the compiler. + Ident { sym: keywords::DollarCrate.name(), is_raw: false, span } + } } // FIXME(eddyb) `Literal` should not expose internal `Debug` impls. @@ -402,7 +422,7 @@ impl server::TokenStream for Rustc<'_> { } fn from_str(&mut self, src: &str) -> Self::TokenStream { parse::parse_stream_from_source_str( - FileName::ProcMacroSourceCode, + FileName::proc_macro_source_code(src.clone()), src.to_string(), self.sess, Some(self.call_site), @@ -494,11 +514,7 @@ impl server::Group for Rustc<'_> { impl server::Punct for Rustc<'_> { fn new(&mut self, ch: char, spacing: Spacing) -> Self::Punct { - Punct { - ch, - joint: spacing == Spacing::Joint, - span: server::Span::call_site(self), - } + Punct::new(ch, spacing == Spacing::Joint, server::Span::call_site(self)) } fn as_char(&mut self, punct: Self::Punct) -> char { punct.ch @@ -520,14 +536,7 @@ impl server::Punct for Rustc<'_> { impl server::Ident for Rustc<'_> { fn new(&mut self, string: &str, span: Self::Span, is_raw: bool) -> Self::Ident { - let sym = Symbol::intern(string); - if is_raw - && (sym == keywords::Underscore.name() - || ast::Ident::with_empty_ctxt(sym).is_path_segment_keyword()) - { - panic!("`{:?}` is not a valid raw identifier", string) - } - Ident { sym, span, is_raw } + Ident::new(Symbol::intern(string), is_raw, span) } fn span(&mut self, ident: Self::Ident) -> Self::Span { ident.span diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs index b8a171b52ad..1f2e6fc81c8 100644 --- a/src/libsyntax_ext/test.rs +++ b/src/libsyntax_ext/test.rs @@ -318,7 +318,7 @@ fn has_test_signature(cx: &ExtCtxt, i: &ast::Item) -> bool { fn has_bench_signature(cx: &ExtCtxt, i: &ast::Item) -> bool { let has_sig = if let ast::ItemKind::Fn(ref decl, _, _, _) = i.node { - // NB: inadequate check, but we're running + // N.B., inadequate check, but we're running // well before resolve, can't get too deep. decl.inputs.len() == 1 } else { diff --git a/src/libsyntax_pos/analyze_source_file.rs b/src/libsyntax_pos/analyze_source_file.rs index 7bc9a1af62c..f9cf0a95721 100644 --- a/src/libsyntax_pos/analyze_source_file.rs +++ b/src/libsyntax_pos/analyze_source_file.rs @@ -47,8 +47,7 @@ pub fn analyze_source_file( } cfg_if! { - if #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), - not(stage0)))] { + if #[cfg(all(any(target_arch = "x86", target_arch = "x86_64")))] { fn analyze_source_file_dispatch(src: &str, source_file_start_pos: BytePos, lines: &mut Vec, diff --git a/src/libsyntax_pos/edition.rs b/src/libsyntax_pos/edition.rs index 5819cd7f480..127dc43fdab 100644 --- a/src/libsyntax_pos/edition.rs +++ b/src/libsyntax_pos/edition.rs @@ -13,7 +13,6 @@ use std::str::FromStr; /// The edition of the compiler (RFC 2052) #[derive(Clone, Copy, Hash, PartialEq, PartialOrd, Debug, RustcEncodable, RustcDecodable, Eq)] -#[non_exhaustive] pub enum Edition { // editions must be kept in order, oldest to newest @@ -33,7 +32,7 @@ pub enum Edition { // must be in order from oldest to newest pub const ALL_EDITIONS: &[Edition] = &[Edition::Edition2015, Edition::Edition2018]; -pub const EDITION_NAME_LIST: &'static str = "2015|2018"; +pub const EDITION_NAME_LIST: &str = "2015|2018"; pub const DEFAULT_EDITION: Edition = Edition::Edition2015; diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index bc52a3e1c7c..3dc884a94c0 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -17,12 +17,12 @@ use GLOBALS; use Span; -use edition::Edition; -use symbol::Symbol; +use edition::{Edition, DEFAULT_EDITION}; +use symbol::{keywords, Symbol}; use serialize::{Encodable, Decodable, Encoder, Decoder}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use std::fmt; +use std::{fmt, mem}; /// A SyntaxContext represents a chain of macro expansions (represented by marks). #[derive(Clone, Copy, PartialEq, Eq, Default, PartialOrd, Ord, Hash)] @@ -37,6 +37,8 @@ struct SyntaxContextData { opaque: SyntaxContext, // This context, but with all transparent marks filtered away. opaque_and_semitransparent: SyntaxContext, + // Name of the crate to which `$crate` with this context would resolve. + dollar_crate_name: Symbol, } /// A mark is a unique id associated with a macro expansion. @@ -47,7 +49,6 @@ pub struct Mark(u32); struct MarkData { parent: Mark, default_transparency: Transparency, - is_builtin: bool, expn_info: Option, } @@ -77,7 +78,6 @@ impl Mark { parent, // By default expansions behave like `macro_rules`. default_transparency: Transparency::SemiTransparent, - is_builtin: false, expn_info: None, }); Mark(data.marks.len() as u32 - 1) @@ -121,18 +121,6 @@ impl Mark { HygieneData::with(|data| data.marks[self.0 as usize].default_transparency = transparency) } - #[inline] - pub fn is_builtin(self) -> bool { - assert_ne!(self, Mark::root()); - HygieneData::with(|data| data.marks[self.0 as usize].is_builtin) - } - - #[inline] - pub fn set_is_builtin(self, is_builtin: bool) { - assert_ne!(self, Mark::root()); - HygieneData::with(|data| data.marks[self.0 as usize].is_builtin = is_builtin) - } - pub fn is_descendant_of(mut self, ancestor: Mark) -> bool { HygieneData::with(|data| { while self != ancestor { @@ -206,7 +194,6 @@ impl HygieneData { // If the root is opaque, then loops searching for an opaque mark // will automatically stop after reaching it. default_transparency: Transparency::Opaque, - is_builtin: true, expn_info: None, }], syntax_contexts: vec![SyntaxContextData { @@ -215,9 +202,10 @@ impl HygieneData { prev_ctxt: SyntaxContext(0), opaque: SyntaxContext(0), opaque_and_semitransparent: SyntaxContext(0), + dollar_crate_name: keywords::DollarCrate.name(), }], markings: FxHashMap::default(), - default_edition: Edition::Edition2015, + default_edition: DEFAULT_EDITION, } } @@ -262,7 +250,6 @@ impl SyntaxContext { data.marks.push(MarkData { parent: Mark::root(), default_transparency: Transparency::SemiTransparent, - is_builtin: false, expn_info: Some(expansion_info), }); @@ -274,6 +261,7 @@ impl SyntaxContext { prev_ctxt: SyntaxContext::empty(), opaque: SyntaxContext::empty(), opaque_and_semitransparent: SyntaxContext::empty(), + dollar_crate_name: keywords::DollarCrate.name(), }); SyntaxContext(data.syntax_contexts.len() as u32 - 1) }) @@ -308,11 +296,11 @@ impl SyntaxContext { } // Otherwise, `mark` is a macros 1.0 definition and the call site is in a - // macros 2.0 expansion, i.e. a macros 1.0 invocation is in a macros 2.0 definition. + // macros 2.0 expansion, i.e., a macros 1.0 invocation is in a macros 2.0 definition. // // In this case, the tokens from the macros 1.0 definition inherit the hygiene // at their invocation. That is, we pretend that the macros 1.0 definition - // was defined at its invocation (i.e. inside the macros 2.0 definition) + // was defined at its invocation (i.e., inside the macros 2.0 definition) // so that the macros 2.0 definition remains hygienic. // // See the example at `test/run-pass/hygiene/legacy_interaction.rs`. @@ -340,6 +328,7 @@ impl SyntaxContext { prev_ctxt, opaque: new_opaque, opaque_and_semitransparent: new_opaque, + dollar_crate_name: keywords::DollarCrate.name(), }); new_opaque }); @@ -357,6 +346,7 @@ impl SyntaxContext { prev_ctxt, opaque, opaque_and_semitransparent: new_opaque_and_semitransparent, + dollar_crate_name: keywords::DollarCrate.name(), }); new_opaque_and_semitransparent }); @@ -372,6 +362,7 @@ impl SyntaxContext { prev_ctxt, opaque, opaque_and_semitransparent, + dollar_crate_name: keywords::DollarCrate.name(), }); new_opaque_and_semitransparent_and_transparent }) @@ -438,7 +429,7 @@ impl SyntaxContext { /// } /// ``` /// This returns the expansion whose definition scope we use to privacy check the resolution, - /// or `None` if we privacy check as usual (i.e. not w.r.t. a macro definition scope). + /// or `None` if we privacy check as usual (i.e., not w.r.t. a macro definition scope). pub fn adjust(&mut self, expansion: Mark) -> Option { let mut scope = None; while !expansion.is_descendant_of(self.outer()) { @@ -526,6 +517,21 @@ impl SyntaxContext { pub fn outer(self) -> Mark { HygieneData::with(|data| data.syntax_contexts[self.0 as usize].outer_mark) } + + pub fn dollar_crate_name(self) -> Symbol { + HygieneData::with(|data| data.syntax_contexts[self.0 as usize].dollar_crate_name) + } + + pub fn set_dollar_crate_name(self, dollar_crate_name: Symbol) { + HygieneData::with(|data| { + let prev_dollar_crate_name = mem::replace( + &mut data.syntax_contexts[self.0 as usize].dollar_crate_name, dollar_crate_name + ); + assert!(dollar_crate_name == prev_dollar_crate_name || + prev_dollar_crate_name == keywords::DollarCrate.name(), + "$crate name is reset for a syntax context"); + }) + } } impl fmt::Debug for SyntaxContext { @@ -540,7 +546,7 @@ pub struct ExpnInfo { /// The location of the actual macro invocation or syntax sugar , e.g. /// `let x = foo!();` or `if let Some(y) = x {}` /// - /// This may recursively refer to other macro invocations, e.g. if + /// This may recursively refer to other macro invocations, e.g., if /// `foo!()` invoked `bar!()` internally, and there was an /// expression inside `bar!`; the call_site of the expression in /// the expansion would point to the `bar!` invocation; that @@ -548,7 +554,7 @@ pub struct ExpnInfo { /// pointing to the `foo!` invocation. pub call_site: Span, /// The span of the macro definition itself. The macro may not - /// have a sensible definition span (e.g. something defined + /// have a sensible definition span (e.g., something defined /// completely inside libsyntax) in which case this is None. /// This span serves only informational purpose and is not used for resolution. pub def_site: Option, @@ -571,9 +577,9 @@ pub struct ExpnInfo { /// The source of expansion. #[derive(Clone, Hash, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)] pub enum ExpnFormat { - /// e.g. #[derive(...)] + /// e.g., #[derive(...)] MacroAttribute(Symbol), - /// e.g. `format!()` + /// e.g., `format!()` MacroBang(Symbol), /// Desugaring done by the compiler during HIR lowering. CompilerDesugaring(CompilerDesugaringKind) diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 34fb71e4ddf..9aafb9fc549 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! The source positions and related helper functions +//! The source positions and related helper functions. //! -//! # Note +//! ## Note //! //! This API is completely unstable and subject to change. @@ -24,21 +24,13 @@ #![feature(nll)] #![feature(non_exhaustive)] #![feature(optin_builtin_traits)] +#![feature(rustc_attrs)] #![feature(specialization)] +#![feature(step_trait)] #![cfg_attr(not(stage0), feature(stdsimd))] -use std::borrow::Cow; -use std::cell::Cell; -use std::cmp::{self, Ordering}; -use std::fmt; -use std::hash::{Hasher, Hash}; -use std::ops::{Add, Sub}; -use std::path::PathBuf; - -use rustc_data_structures::stable_hasher::StableHasher; -use rustc_data_structures::sync::{Lrc, Lock}; - extern crate arena; +#[macro_use] extern crate rustc_data_structures; #[macro_use] @@ -65,6 +57,17 @@ pub mod symbol; mod analyze_source_file; +use rustc_data_structures::stable_hasher::StableHasher; +use rustc_data_structures::sync::{Lrc, Lock}; + +use std::borrow::Cow; +use std::cell::Cell; +use std::cmp::{self, Ordering}; +use std::fmt; +use std::hash::{Hasher, Hash}; +use std::ops::{Add, Sub}; +use std::path::PathBuf; + pub struct Globals { symbol_interner: Lock, span_interner: Lock, @@ -83,26 +86,27 @@ impl Globals { scoped_thread_local!(pub static GLOBALS: Globals); -/// Differentiates between real files and common virtual files +/// Differentiates between real files and common virtual files. #[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash, RustcDecodable, RustcEncodable)] pub enum FileName { Real(PathBuf), /// A macro. This includes the full name of the macro, so that there are no clashes. Macros(String), - /// call to `quote!` - QuoteExpansion, - /// Command line - Anon, - /// Hack in src/libsyntax/parse.rs - /// FIXME(jseyfried) - MacroExpansion, - ProcMacroSourceCode, - /// Strings provided as --cfg [cfgspec] stored in a crate_cfg - CfgSpec, - /// Strings provided as crate attributes in the CLI - CliCrateAttr, - /// Custom sources for explicit parser calls from plugins and drivers + /// Call to `quote!`. + QuoteExpansion(u64), + /// Command line. + Anon(u64), + /// Hack in `src/libsyntax/parse.rs`. + // FIXME(jseyfried) + MacroExpansion(u64), + ProcMacroSourceCode(u64), + /// Strings provided as `--cfg [cfgspec]` stored in a `crate_cfg`. + CfgSpec(u64), + /// Strings provided as crate attributes in the CLI. + CliCrateAttr(u64), + /// Custom sources for explicit parser calls from plugins and drivers. Custom(String), + DocTest(PathBuf, isize), } impl std::fmt::Display for FileName { @@ -111,13 +115,15 @@ impl std::fmt::Display for FileName { match *self { Real(ref path) => write!(fmt, "{}", path.display()), Macros(ref name) => write!(fmt, "<{} macros>", name), - QuoteExpansion => write!(fmt, ""), - MacroExpansion => write!(fmt, ""), - Anon => write!(fmt, ""), - ProcMacroSourceCode => write!(fmt, ""), - CfgSpec => write!(fmt, "cfgspec"), - CliCrateAttr => write!(fmt, ""), + QuoteExpansion(_) => write!(fmt, ""), + MacroExpansion(_) => write!(fmt, ""), + Anon(_) => write!(fmt, ""), + ProcMacroSourceCode(_) => + write!(fmt, ""), + CfgSpec(_) => write!(fmt, ""), + CliCrateAttr(_) => write!(fmt, ""), Custom(ref s) => write!(fmt, "<{}>", s), + DocTest(ref path, _) => write!(fmt, "{}", path.display()), } } } @@ -135,13 +141,14 @@ impl FileName { match *self { Real(_) => true, Macros(_) | - Anon | - MacroExpansion | - ProcMacroSourceCode | - CfgSpec | - CliCrateAttr | + Anon(_) | + MacroExpansion(_) | + ProcMacroSourceCode(_) | + CfgSpec(_) | + CliCrateAttr(_) | Custom(_) | - QuoteExpansion => false, + QuoteExpansion(_) | + DocTest(_, _) => false, } } @@ -149,25 +156,66 @@ impl FileName { use self::FileName::*; match *self { Real(_) | - Anon | - MacroExpansion | - ProcMacroSourceCode | - CfgSpec | - CliCrateAttr | + Anon(_) | + MacroExpansion(_) | + ProcMacroSourceCode(_) | + CfgSpec(_) | + CliCrateAttr(_) | Custom(_) | - QuoteExpansion => false, + QuoteExpansion(_) | + DocTest(_, _) => false, Macros(_) => true, } } + + pub fn quote_expansion_source_code(src: &str) -> FileName { + let mut hasher = StableHasher::new(); + src.hash(&mut hasher); + FileName::QuoteExpansion(hasher.finish()) + } + + pub fn macro_expansion_source_code(src: &str) -> FileName { + let mut hasher = StableHasher::new(); + src.hash(&mut hasher); + FileName::MacroExpansion(hasher.finish()) + } + + pub fn anon_source_code(src: &str) -> FileName { + let mut hasher = StableHasher::new(); + src.hash(&mut hasher); + FileName::Anon(hasher.finish()) + } + + pub fn proc_macro_source_code(src: &str) -> FileName { + let mut hasher = StableHasher::new(); + src.hash(&mut hasher); + FileName::ProcMacroSourceCode(hasher.finish()) + } + + pub fn cfg_spec_source_code(src: &str) -> FileName { + let mut hasher = StableHasher::new(); + src.hash(&mut hasher); + FileName::QuoteExpansion(hasher.finish()) + } + + pub fn cli_crate_attr_source_code(src: &str) -> FileName { + let mut hasher = StableHasher::new(); + src.hash(&mut hasher); + FileName::CliCrateAttr(hasher.finish()) + } + + pub fn doc_test_source_code(path: PathBuf, line: isize) -> FileName{ + FileName::DocTest(path, line) + } } /// Spans represent a region of code, used for error reporting. Positions in spans /// are *absolute* positions from the beginning of the source_map, not positions -/// relative to SourceFiles. Methods on the SourceMap can be used to relate spans back +/// relative to `SourceFile`s. Methods on the `SourceMap` can be used to relate spans back /// to the original source. /// You must be careful if the span crosses more than one file - you will not be /// able to use many of the functions on spans in source_map and you cannot assume -/// that the length of the span = hi - lo; there may be space in the BytePos +/// that the length of the `span = hi - lo`; there may be space in the `BytePos` /// range between files. /// /// `SpanData` is public because `Span` uses a thread-local interner and can't be @@ -198,7 +246,7 @@ impl SpanData { } // The interner is pointed to by a thread local value which is only set on the main thread -// with parallelization is disabled. So we don't allow Span to transfer between threads +// with parallelization is disabled. So we don't allow `Span` to transfer between threads // to avoid panics and other errors, even though it would be memory safe to do so. #[cfg(not(parallel_queries))] impl !Send for Span {} @@ -218,9 +266,9 @@ impl Ord for Span { /// A collection of spans. Spans have two orthogonal attributes: /// -/// - they can be *primary spans*. In this case they are the locus of +/// - They can be *primary spans*. In this case they are the locus of /// the error, and would be rendered with `^^^`. -/// - they can have a *label*. In this case, the label is written next +/// - They can have a *label*. In this case, the label is written next /// to the mark in the snippet when we render. #[derive(Clone, Debug, Hash, PartialEq, Eq, RustcEncodable, RustcDecodable)] pub struct MultiSpan { @@ -267,7 +315,7 @@ impl Span { let span = self.data(); span.with_hi(span.lo) } - /// Returns a new span representing an empty span at the end of this span + /// Returns a new span representing an empty span at the end of this span. #[inline] pub fn shrink_to_hi(self) -> Span { let span = self.data(); @@ -279,7 +327,7 @@ impl Span { if self.is_dummy() { other } else { self } } - /// Return true if `self` fully encloses `other`. + /// Return `true` if `self` fully encloses `other`. pub fn contains(self, other: Span) -> bool { let span = self.data(); let other = other.data(); @@ -296,7 +344,7 @@ impl Span { span.lo == other.lo && span.hi == other.hi } - /// Returns `Some(span)`, where the start is trimmed by the end of `other` + /// Returns `Some(span)`, where the start is trimmed by the end of `other`. pub fn trim_start(self, other: Span) -> Option { let span = self.data(); let other = other.data(); @@ -307,14 +355,14 @@ impl Span { } } - /// Return the source span - this is either the supplied span, or the span for + /// Return the source span -- this is either the supplied span, or the span for /// the macro callsite that expanded to it. pub fn source_callsite(self) -> Span { self.ctxt().outer().expn_info().map(|info| info.call_site.source_callsite()).unwrap_or(self) } /// The `Span` for the tokens in the previous macro expansion from which `self` was generated, - /// if any + /// if any. pub fn parent(self) -> Option { self.ctxt().outer().expn_info().map(|i| i.call_site) } @@ -350,7 +398,7 @@ impl Span { self.ctxt().outer().expn_info().map(source_callee) } - /// Check if a span is "internal" to a macro in which #[unstable] + /// Check if a span is "internal" to a macro in which `#[unstable]` /// items can be used (that is, a macro marked with /// `#[allow_internal_unstable]`). pub fn allows_unstable(&self) -> bool { @@ -371,7 +419,7 @@ impl Span { } } - /// Return the compiler desugaring that created this span, or None + /// Return the compiler desugaring that created this span, or `None` /// if this span is not from a desugaring. pub fn compiler_desugaring_kind(&self) -> Option { match self.ctxt().outer().expn_info() { @@ -397,7 +445,7 @@ impl Span { let mut prev_span = DUMMY_SP; let mut result = vec![]; while let Some(info) = self.ctxt().outer().expn_info() { - // Don't print recursive invocations + // Don't print recursive invocations. if !info.call_site.source_equal(&prev_span) { let (pre, post) = match info.format { ExpnFormat::MacroAttribute(..) => ("#[", "]"), @@ -421,7 +469,7 @@ impl Span { pub fn to(self, end: Span) -> Span { let span_data = self.data(); let end_data = end.data(); - // FIXME(jseyfried): self.ctxt should always equal end.ctxt here (c.f. issue #23480) + // FIXME(jseyfried): `self.ctxt` should always equal `end.ctxt` here (cf. issue #23480). // Return the macro span on its own to avoid weird diagnostic output. It is preferable to // have an incomplete span than a completely nonsensical one. if span_data.ctxt != end_data.ctxt { @@ -430,8 +478,8 @@ impl Span { } else if end_data.ctxt == SyntaxContext::empty() { return self; } - // both span fall within a macro - // FIXME(estebank) check if it is the *same* macro + // Both spans fall within a macro. + // FIXME(estebank): check if it is the *same* macro. } Span::new( cmp::min(span_data.lo, end_data.lo), @@ -566,7 +614,7 @@ impl serialize::UseSpecializedDecodable for Span { } } -fn default_span_debug(span: Span, f: &mut fmt::Formatter) -> fmt::Result { +pub fn default_span_debug(span: Span, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Span") .field("lo", &span.lo()) .field("hi", &span.hi()) @@ -613,7 +661,7 @@ impl MultiSpan { self.span_labels.push((span, label)); } - /// Selects the first primary span (if any) + /// Selects the first primary span (if any). pub fn primary_span(&self) -> Option { self.primary_spans.first().cloned() } @@ -634,7 +682,7 @@ impl MultiSpan { is_dummy } - /// Replaces all occurrences of one Span with another. Used to move Spans in areas that don't + /// Replaces all occurrences of one Span with another. Used to move `Span`s in areas that don't /// display well (like std macros). Returns true if replacements occurred. pub fn replace(&mut self, before: Span, after: Span) -> bool { let mut replacements_occurred = false; @@ -655,7 +703,7 @@ impl MultiSpan { /// Returns the strings to highlight. We always ensure that there /// is an entry for each of the primary spans -- for each primary - /// span P, if there is at least one label with span P, we return + /// span `P`, if there is at least one label with span `P`, we return /// those labels (marked as primary). But otherwise we return /// `SpanLabel` instances with empty labels. pub fn span_labels(&self) -> Vec { @@ -697,23 +745,23 @@ impl From> for MultiSpan { pub const NO_EXPANSION: SyntaxContext = SyntaxContext::empty(); -/// Identifies an offset of a multi-byte character in a SourceFile +/// Identifies an offset of a multi-byte character in a `SourceFile`. #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Eq, PartialEq, Debug)] pub struct MultiByteChar { - /// The absolute offset of the character in the SourceMap + /// The absolute offset of the character in the `SourceMap`. pub pos: BytePos, - /// The number of bytes, >=2 + /// The number of bytes, `>= 2`. pub bytes: u8, } -/// Identifies an offset of a non-narrow character in a SourceFile +/// Identifies an offset of a non-narrow character in a `SourceFile`. #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Eq, PartialEq, Debug)] pub enum NonNarrowChar { - /// Represents a zero-width character + /// Represents a zero-width character. ZeroWidth(BytePos), - /// Represents a wide (fullwidth) character + /// Represents a wide (full-width) character. Wide(BytePos), - /// Represents a tab character, represented visually with a width of 4 characters + /// Represents a tab character, represented visually with a width of 4 characters. Tab(BytePos), } @@ -727,7 +775,7 @@ impl NonNarrowChar { } } - /// Returns the absolute offset of the character in the SourceMap + /// Returns the absolute offset of the character in the `SourceMap`. pub fn pos(&self) -> BytePos { match *self { NonNarrowChar::ZeroWidth(p) | @@ -736,7 +784,7 @@ impl NonNarrowChar { } } - /// Returns the width of the character, 0 (zero-width) or 2 (wide) + /// Returns the width of the character, 0 (zero-width) or 2 (wide). pub fn width(&self) -> usize { match *self { NonNarrowChar::ZeroWidth(_) => 0, @@ -770,7 +818,7 @@ impl Sub for NonNarrowChar { } } -/// The state of the lazy external source loading mechanism of a SourceFile. +/// The state of the lazy external source loading mechanism of a `SourceFile`. #[derive(PartialEq, Eq, Clone)] pub enum ExternalSource { /// The external source has been loaded already. @@ -779,7 +827,7 @@ pub enum ExternalSource { AbsentOk, /// A failed attempt has been made to load the external source. AbsentErr, - /// No external source has to be loaded, since the SourceFile represents a local crate. + /// No external source has to be loaded, since the `SourceFile` represents a local crate. Unneeded, } @@ -799,38 +847,38 @@ impl ExternalSource { } } -/// A single source in the SourceMap. +/// A single source in the `SourceMap`. #[derive(Clone)] pub struct SourceFile { /// The name of the file that the source came from, source that doesn't - /// originate from files has names between angle brackets by convention, - /// e.g. `` + /// originate from files has names between angle brackets by convention + /// (e.g., ``). pub name: FileName, - /// True if the `name` field above has been modified by --remap-path-prefix + /// True if the `name` field above has been modified by `--remap-path-prefix`. pub name_was_remapped: bool, /// The unmapped path of the file that the source came from. - /// Set to `None` if the SourceFile was imported from an external crate. + /// Set to `None` if the `SourceFile` was imported from an external crate. pub unmapped_path: Option, - /// Indicates which crate this SourceFile was imported from. + /// Indicates which crate this `SourceFile` was imported from. pub crate_of_origin: u32, - /// The complete source code + /// The complete source code. pub src: Option>, - /// The source code's hash + /// The source code's hash. pub src_hash: u128, /// The external source code (used for external crates, which will have a `None` /// value as `self.src`. pub external_src: Lock, - /// The start position of this source in the SourceMap + /// The start position of this source in the `SourceMap`. pub start_pos: BytePos, - /// The end position of this source in the SourceMap + /// The end position of this source in the `SourceMap`. pub end_pos: BytePos, - /// Locations of lines beginnings in the source code + /// Locations of lines beginnings in the source code. pub lines: Vec, - /// Locations of multi-byte characters in the source code + /// Locations of multi-byte characters in the source code. pub multibyte_chars: Vec, - /// Width of characters that are not narrow in the source code + /// Width of characters that are not narrow in the source code. pub non_narrow_chars: Vec, - /// A hash of the filename, used for speeding up the incr. comp. hashing. + /// A hash of the filename, used for speeding up hashing in incremental compilation. pub name_hash: u128, } @@ -844,7 +892,7 @@ impl Encodable for SourceFile { s.emit_struct_field("end_pos", 5, |s| self.end_pos.encode(s))?; s.emit_struct_field("lines", 6, |s| { let lines = &self.lines[..]; - // store the length + // Store the length. s.emit_u32(lines.len() as u32)?; if !lines.is_empty() { @@ -1015,7 +1063,7 @@ impl SourceFile { } } - /// Return the BytePos of the beginning of the current line. + /// Return the `BytePos` of the beginning of the current line. pub fn line_begin_pos(&self, pos: BytePos) -> BytePos { let line_index = self.lookup_line(pos).unwrap(); self.lines[line_index] @@ -1103,9 +1151,9 @@ impl SourceFile { } /// Find the line containing the given position. The return value is the - /// index into the `lines` array of this SourceFile, not the 1-based line + /// index into the `lines` array of this `SourceFile`, not the 1-based line /// number. If the source_file is empty or the position is located before the - /// first line, None is returned. + /// first line, `None` is returned. pub fn lookup_line(&self, pos: BytePos) -> Option { if self.lines.len() == 0 { return None; @@ -1162,14 +1210,14 @@ pub trait Pos { #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] pub struct BytePos(pub u32); -/// A character offset. Because of multibyte utf8 characters, a byte offset -/// is not equivalent to a character offset. The SourceMap will convert BytePos -/// values to CharPos values as necessary. +/// A character offset. Because of multibyte UTF-8 characters, a byte offset +/// is not equivalent to a character offset. The `SourceMap` will convert `BytePos` +/// values to `CharPos` values as necessary. #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] pub struct CharPos(pub usize); -// FIXME: Lots of boilerplate in these impls, but so far my attempts to fix -// have been unsuccessful +// FIXME: lots of boilerplate in these impls, but so far my attempts to fix +// have been unsuccessful. impl Pos for BytePos { #[inline(always)] @@ -1251,20 +1299,20 @@ impl Sub for CharPos { // Loc, LocWithOpt, SourceFileAndLine, SourceFileAndBytePos // -/// A source code location used for error reporting +/// A source code location used for error reporting. #[derive(Debug, Clone)] pub struct Loc { - /// Information about the original source + /// Information about the original source. pub file: Lrc, - /// The (1-based) line number + /// The (1-based) line number. pub line: usize, - /// The (0-based) column offset + /// The (0-based) column offset. pub col: CharPos, - /// The (0-based) column offset when displayed + /// The (0-based) column offset when displayed. pub col_display: usize, } -/// A source code location used as the result of lookup_char_pos_adj +/// A source code location used as the result of `lookup_char_pos_adj`. // Actually, *none* of the clients use the filename *or* file field; // perhaps they should just be removed. #[derive(Debug)] @@ -1275,7 +1323,7 @@ pub struct LocWithOpt { pub file: Option>, } -// used to be structural records. Better names, anyone? +// Used to be structural records. #[derive(Debug)] pub struct SourceFileAndLine { pub sf: Lrc, pub line: usize } #[derive(Debug)] diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 741877bb4c8..b720db899a1 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -9,20 +9,22 @@ // except according to those terms. //! An "interner" is a data structure that associates values with usize tags and -//! allows bidirectional lookup; i.e. given a value, one can easily find the +//! allows bidirectional lookup; i.e., given a value, one can easily find the //! type, and vice versa. -use hygiene::SyntaxContext; -use {Span, DUMMY_SP, GLOBALS}; - -use rustc_data_structures::fx::FxHashMap; use arena::DroplessArena; +use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::indexed_vec::Idx; use serialize::{Decodable, Decoder, Encodable, Encoder}; + use std::fmt; use std::str; use std::cmp::{PartialEq, Ordering, PartialOrd, Ord}; use std::hash::{Hash, Hasher}; +use hygiene::SyntaxContext; +use {Span, DUMMY_SP, GLOBALS}; + #[derive(Copy, Clone, Eq)] pub struct Ident { pub name: Symbol, @@ -34,6 +36,7 @@ impl Ident { pub const fn new(name: Symbol, span: Span) -> Ident { Ident { name, span } } + #[inline] pub const fn with_empty_ctxt(name: Symbol) -> Ident { Ident::new(name, DUMMY_SP) @@ -55,12 +58,12 @@ impl Ident { } pub fn without_first_quote(self) -> Ident { - Ident::new(Symbol::intern(self.as_str().trim_left_matches('\'')), self.span) + Ident::new(Symbol::intern(self.as_str().trim_start_matches('\'')), self.span) } /// "Normalize" ident for use in comparisons using "item hygiene". /// Identifiers with same string value become same if they came from the same "modern" macro - /// (e.g. `macro` item, but not `macro_rules` item) and stay different if they came from + /// (e.g., `macro` item, but not `macro_rules` item) and stay different if they came from /// different "modern" macros. /// Technically, this operation strips all non-opaque marks from ident's syntactic context. pub fn modern(self) -> Ident { @@ -69,7 +72,7 @@ impl Ident { /// "Normalize" ident for use in comparisons using "local variable hygiene". /// Identifiers with same string value become same if they came from the same non-transparent - /// macro (e.g. `macro` or `macro_rules!` items) and stay different if they came from different + /// macro (e.g., `macro` or `macro_rules!` items) and stay different if they came from different /// non-transparent macros. /// Technically, this operation strips all transparent marks from ident's syntactic context. pub fn modern_and_legacy(self) -> Ident { @@ -80,6 +83,10 @@ impl Ident { Ident::new(self.name.gensymed(), self.span) } + pub fn gensym_if_underscore(self) -> Ident { + if self.name == keywords::Underscore.name() { self.gensym() } else { self } + } + pub fn as_str(self) -> LocalInternedString { self.name.as_str() } @@ -118,7 +125,7 @@ impl Encodable for Ident { fn encode(&self, s: &mut S) -> Result<(), S::Error> { if self.span.ctxt().modern() == SyntaxContext::empty() { s.emit_str(&self.as_str()) - } else { // FIXME(jseyfried) intercrate hygiene + } else { // FIXME(jseyfried): intercrate hygiene let mut string = "#".to_owned(); string.push_str(&self.as_str()); s.emit_str(&string) @@ -131,18 +138,27 @@ impl Decodable for Ident { let string = d.read_str()?; Ok(if !string.starts_with('#') { Ident::from_str(&string) - } else { // FIXME(jseyfried) intercrate hygiene + } else { // FIXME(jseyfried): intercrate hygiene Ident::with_empty_ctxt(Symbol::gensym(&string[1..])) }) } } -/// A symbol is an interned or gensymed string. +/// A symbol is an interned or gensymed string. The use of newtype_index! means +/// that Option only takes up 4 bytes, because newtype_index! reserves +/// the last 256 values for tagging purposes. +/// +/// Note that Symbol cannot be a newtype_index! directly because it implements +/// fmt::Debug, Encodable, and Decodable in special ways. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct Symbol(u32); +pub struct Symbol(SymbolIndex); + +newtype_index! { + pub struct SymbolIndex { .. } +} // The interner is pointed to by a thread local value which is only set on the main thread -// with parallelization is disabled. So we don't allow Symbol to transfer between threads +// with parallelization is disabled. So we don't allow `Symbol` to transfer between threads // to avoid panics and other errors, even though it would be memory safe to do so. #[cfg(not(parallel_queries))] impl !Send for Symbol { } @@ -150,6 +166,10 @@ impl !Send for Symbol { } impl !Sync for Symbol { } impl Symbol { + const fn new(n: u32) -> Self { + Symbol(SymbolIndex::from_u32_const(n)) + } + /// Maps a string to its interned representation. pub fn intern(string: &str) -> Self { with_interner(|interner| interner.intern(string)) @@ -159,7 +179,7 @@ impl Symbol { with_interner(|interner| interner.interned(self)) } - /// gensym's a new usize, using the current interner. + /// Gensyms a new usize, using the current interner. pub fn gensym(string: &str) -> Self { with_interner(|interner| interner.gensym(string)) } @@ -183,7 +203,7 @@ impl Symbol { } pub fn as_u32(self) -> u32 { - self.0 + self.0.as_u32() } } @@ -191,7 +211,7 @@ impl fmt::Debug for Symbol { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let is_gensymed = with_interner(|interner| interner.is_gensymed(*self)); if is_gensymed { - write!(f, "{}({})", self, self.0) + write!(f, "{}({:?})", self, self.0) } else { write!(f, "{}", self) } @@ -222,7 +242,10 @@ impl> PartialEq for Symbol { } } -// The &'static strs in this type actually point into the arena +// The `&'static str`s in this type actually point into the arena. +// +// Note that normal symbols are indexed upward from 0, and gensyms are indexed +// downward from SymbolIndex::MAX_AS_U32. #[derive(Default)] pub struct Interner { arena: DroplessArena, @@ -236,8 +259,8 @@ impl Interner { let mut this = Interner::default(); for &string in init { if string == "" { - // We can't allocate empty strings in the arena, so handle this here - let name = Symbol(this.strings.len() as u32); + // We can't allocate empty strings in the arena, so handle this here. + let name = Symbol::new(this.strings.len() as u32); this.names.insert("", name); this.strings.push(""); } else { @@ -252,14 +275,15 @@ impl Interner { return name; } - let name = Symbol(self.strings.len() as u32); + let name = Symbol::new(self.strings.len() as u32); - // from_utf8_unchecked is safe since we just allocated a &str which is known to be utf8 + // `from_utf8_unchecked` is safe since we just allocated a `&str` which is known to be + // UTF-8. let string: &str = unsafe { str::from_utf8_unchecked(self.arena.alloc_slice(string.as_bytes())) }; - // It is safe to extend the arena allocation to 'static because we only access - // these while the arena is still alive + // It is safe to extend the arena allocation to `'static` because we only access + // these while the arena is still alive. let string: &'static str = unsafe { &*(string as *const str) }; @@ -269,10 +293,10 @@ impl Interner { } pub fn interned(&self, symbol: Symbol) -> Symbol { - if (symbol.0 as usize) < self.strings.len() { + if (symbol.0.as_usize()) < self.strings.len() { symbol } else { - self.interned(self.gensyms[(!0 - symbol.0) as usize]) + self.interned(self.gensyms[(SymbolIndex::MAX_AS_U32 - symbol.0.as_u32()) as usize]) } } @@ -283,17 +307,17 @@ impl Interner { fn gensymed(&mut self, symbol: Symbol) -> Symbol { self.gensyms.push(symbol); - Symbol(!0 - self.gensyms.len() as u32 + 1) + Symbol::new(SymbolIndex::MAX_AS_U32 - self.gensyms.len() as u32 + 1) } fn is_gensymed(&mut self, symbol: Symbol) -> bool { - symbol.0 as usize >= self.strings.len() + symbol.0.as_usize() >= self.strings.len() } pub fn get(&self, symbol: Symbol) -> &str { - match self.strings.get(symbol.0 as usize) { + match self.strings.get(symbol.0.as_usize()) { Some(string) => string, - None => self.get(self.gensyms[(!0 - symbol.0) as usize]), + None => self.get(self.gensyms[(SymbolIndex::MAX_AS_U32 - symbol.0.as_u32()) as usize]), } } } @@ -317,7 +341,7 @@ macro_rules! declare_keywords {( $( #[allow(non_upper_case_globals)] pub const $konst: Keyword = Keyword { - ident: Ident::with_empty_ctxt(super::Symbol($index)) + ident: Ident::with_empty_ctxt(super::Symbol::new($index)) }; )* @@ -340,7 +364,7 @@ macro_rules! declare_keywords {( } }} -// NB: leaving holes in the ident table is bad! a different ident will get +// N.B., leaving holes in the ident table is bad! a different ident will get // interned with the id from the hole, but it will be between the min and max // of the reserved words, and thus tagged as "reserved". // After modifying this list adjust `is_special`, `is_used_keyword`/`is_unused_keyword`, @@ -349,11 +373,11 @@ declare_keywords! { // Special reserved identifiers used internally for elided lifetimes, // unnamed method parameters, crate root module, error recovery etc. (0, Invalid, "") - (1, CrateRoot, "{{root}}") + (1, PathRoot, "{{root}}") (2, DollarCrate, "$crate") (3, Underscore, "_") - // Keywords used in the language. + // Keywords that are used in stable Rust. (4, As, "as") (5, Box, "box") (6, Break, "break") @@ -378,8 +402,8 @@ declare_keywords! { (25, Pub, "pub") (26, Ref, "ref") (27, Return, "return") - (28, SelfValue, "self") - (29, SelfType, "Self") + (28, SelfLower, "self") + (29, SelfUpper, "Self") (30, Static, "static") (31, Struct, "struct") (32, Super, "super") @@ -391,7 +415,7 @@ declare_keywords! { (38, Where, "where") (39, While, "while") - // Keywords reserved for future use. + // Keywords that are used in unstable Rust or reserved for future use. (40, Abstract, "abstract") (41, Become, "become") (42, Do, "do") @@ -404,9 +428,11 @@ declare_keywords! { (49, Virtual, "virtual") (50, Yield, "yield") - // Edition-specific keywords reserved for future use. - (51, Async, "async") // >= 2018 Edition only - (52, Dyn, "dyn") // >= 2018 Edition only + // Edition-specific keywords that are used in stable Rust. + (51, Dyn, "dyn") // >= 2018 Edition only + + // Edition-specific keywords that are used in unstable Rust or reserved for future use. + (52, Async, "async") // >= 2018 Edition only (53, Try, "try") // >= 2018 Edition only // Special lifetime names @@ -417,18 +443,22 @@ declare_keywords! { (56, Auto, "auto") (57, Catch, "catch") (58, Default, "default") - (59, Union, "union") - (60, Existential, "existential") + (59, Existential, "existential") + (60, Union, "union") } impl Symbol { + fn is_used_keyword_2018(self) -> bool { + self == keywords::Dyn.name() + } + fn is_unused_keyword_2018(self) -> bool { self >= keywords::Async.name() && self <= keywords::Try.name() } } impl Ident { - // Returns true for reserved identifiers used internally for elided lifetimes, + // Returns `true` for reserved identifiers used internally for elided lifetimes, // unnamed method parameters, crate root module, error recovery etc. pub fn is_special(self) -> bool { self.name <= keywords::Underscore.name() @@ -436,7 +466,9 @@ impl Ident { /// Returns `true` if the token is a keyword used in the language. pub fn is_used_keyword(self) -> bool { - self.name >= keywords::As.name() && self.name <= keywords::While.name() + // Note: `span.edition()` is relatively expensive, don't call it unless necessary. + self.name >= keywords::As.name() && self.name <= keywords::While.name() || + self.name.is_used_keyword_2018() && self.span.rust_2018() } /// Returns `true` if the token is a keyword reserved for possible future use. @@ -454,18 +486,18 @@ impl Ident { /// A keyword or reserved identifier that can be used as a path segment. pub fn is_path_segment_keyword(self) -> bool { self.name == keywords::Super.name() || - self.name == keywords::SelfValue.name() || - self.name == keywords::SelfType.name() || + self.name == keywords::SelfLower.name() || + self.name == keywords::SelfUpper.name() || self.name == keywords::Extern.name() || self.name == keywords::Crate.name() || - self.name == keywords::CrateRoot.name() || + self.name == keywords::PathRoot.name() || self.name == keywords::DollarCrate.name() } // We see this identifier in a normal identifier position, like variable name or a type. // How was it written originally? Did it use the raw form? Let's try to guess. pub fn is_raw_guess(self) -> bool { - self.name != keywords::Invalid.name() && + self.name != keywords::Invalid.name() && self.name != keywords::Underscore.name() && self.is_reserved() && !self.is_path_segment_keyword() } } @@ -479,8 +511,8 @@ fn with_interner T>(f: F) -> T { /// Represents a string stored in the interner. Because the interner outlives any thread /// which uses this type, we can safely treat `string` which points to interner data, /// as an immortal string, as long as this type never crosses between threads. -// FIXME: Ensure that the interner outlives any thread which uses LocalInternedString, -// by creating a new thread right after constructing the interner +// FIXME: ensure that the interner outlives any thread which uses `LocalInternedString`, +// by creating a new thread right after constructing the interner. #[derive(Clone, Copy, Hash, PartialOrd, Eq, Ord)] pub struct LocalInternedString { string: &'static str, @@ -569,7 +601,7 @@ impl Encodable for LocalInternedString { } } -/// Represents a string stored in the string interner +/// Represents a string stored in the string interner. #[derive(Clone, Copy, Eq)] pub struct InternedString { symbol: Symbol, @@ -694,19 +726,19 @@ mod tests { fn interner_tests() { let mut i: Interner = Interner::default(); // first one is zero: - assert_eq!(i.intern("dog"), Symbol(0)); + assert_eq!(i.intern("dog"), Symbol::new(0)); // re-use gets the same entry: - assert_eq!(i.intern("dog"), Symbol(0)); + assert_eq!(i.intern("dog"), Symbol::new(0)); // different string gets a different #: - assert_eq!(i.intern("cat"), Symbol(1)); - assert_eq!(i.intern("cat"), Symbol(1)); + assert_eq!(i.intern("cat"), Symbol::new(1)); + assert_eq!(i.intern("cat"), Symbol::new(1)); // dog is still at zero - assert_eq!(i.intern("dog"), Symbol(0)); - assert_eq!(i.gensym("zebra"), Symbol(4294967295)); - // gensym of same string gets new number : - assert_eq!(i.gensym("zebra"), Symbol(4294967294)); + assert_eq!(i.intern("dog"), Symbol::new(0)); + assert_eq!(i.gensym("zebra"), Symbol::new(SymbolIndex::MAX_AS_U32)); + // gensym of same string gets new number: + assert_eq!(i.gensym("zebra"), Symbol::new(SymbolIndex::MAX_AS_U32 - 1)); // gensym of *existing* string gets new number: - assert_eq!(i.gensym("dog"), Symbol(4294967293)); + assert_eq!(i.gensym("dog"), Symbol::new(SymbolIndex::MAX_AS_U32 - 2)); } #[test] diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs index 5ac46c2c5eb..b28e62f16fd 100644 --- a/src/libterm/lib.rs +++ b/src/libterm/lib.rs @@ -198,7 +198,7 @@ pub trait Terminal: Write { /// *Note: This does not flush.* /// /// That means the reset command may get buffered so, if you aren't planning on doing anything - /// else that might flush stdout's buffer (e.g. writing a line of text), you should flush after + /// else that might flush stdout's buffer (e.g., writing a line of text), you should flush after /// calling reset. fn reset(&mut self) -> io::Result; diff --git a/src/libterm/terminfo/searcher.rs b/src/libterm/terminfo/searcher.rs index 492d26e625c..426dc4db87b 100644 --- a/src/libterm/terminfo/searcher.rs +++ b/src/libterm/terminfo/searcher.rs @@ -64,7 +64,7 @@ pub fn get_dbpath_for_term(term: &str) -> Option { p.pop(); // on some installations the dir is named after the hex of the char - // (e.g. macOS) + // (e.g., macOS) p.push(&format!("{:x}", first_char as usize)); p.push(term); if fs::metadata(&p).is_ok() { @@ -79,7 +79,7 @@ pub fn get_dbpath_for_term(term: &str) -> Option { #[ignore(reason = "buildbots don't have ncurses installed and I can't mock everything I need")] fn test_get_dbpath_for_term() { // woefully inadequate test coverage - // note: current tests won't work with non-standard terminfo hierarchies (e.g. macOS's) + // note: current tests won't work with non-standard terminfo hierarchies (e.g., macOS's) use std::env; // FIXME (#9639): This needs to handle non-utf8 paths fn x(t: &str) -> String { diff --git a/src/libtest/formatters/terse.rs b/src/libtest/formatters/terse.rs index 6f7dfee53fa..cf15c89fac2 100644 --- a/src/libtest/formatters/terse.rs +++ b/src/libtest/formatters/terse.rs @@ -66,7 +66,7 @@ impl TerseFormatter { self.write_pretty(result, color)?; if self.test_count % QUIET_MODE_MAX_COLUMN == QUIET_MODE_MAX_COLUMN - 1 { // we insert a new line every 100 dots in order to flush the - // screen when dealing with line-buffered output (e.g. piping to + // screen when dealing with line-buffered output (e.g., piping to // `stamp` in the rust CI). let out = format!(" {}/{}\n", self.test_count+1, self.total_test_count); self.write_plain(&out)?; diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 7c26d042a7c..1c8734913c7 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -23,7 +23,7 @@ // running tests while providing a base that other test frameworks may // build off of. -// NB: this is also specified in this crate's Cargo.toml, but libsyntax contains logic specific to +// N.B., this is also specified in this crate's Cargo.toml, but libsyntax contains logic specific to // this crate, which relies on this attribute (rather than the value of `--crate-name` passed by // cargo) to detect this crate. @@ -99,8 +99,12 @@ mod formatters; use formatters::{JsonFormatter, OutputFormatter, PrettyFormatter, TerseFormatter}; +/// Whether to execute tests concurrently or not +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum Concurrent { Yes, No } + // The name of a test. By convention this follows the rules for rust -// paths; i.e. it should be a series of identifiers separated by double +// paths; i.e., it should be a series of identifiers separated by double // colons. This way if some test runner wants to arrange the tests // hierarchically it may. @@ -515,7 +519,7 @@ Test Attributes: // FIXME: Copied from libsyntax until linkage errors are resolved. Issue #47566 fn is_nightly() -> bool { - // Whether this is a feature-staged build, i.e. on the beta or stable channel + // Whether this is a feature-staged build, i.e., on the beta or stable channel let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some(); // Whether we should enable unstable features for bootstrapping let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok(); @@ -1018,10 +1022,12 @@ fn use_color(opts: &TestOpts) -> bool { } } -#[cfg(any(target_os = "cloudabi", target_os = "redox", - all(target_arch = "wasm32", not(target_os = "emscripten"))))] +#[cfg(any(target_os = "cloudabi", + target_os = "redox", + all(target_arch = "wasm32", not(target_os = "emscripten")), + target_env = "sgx"))] fn stdout_isatty() -> bool { - // FIXME: Implement isatty on Redox + // FIXME: Implement isatty on Redox and SGX false } #[cfg(unix)] @@ -1071,8 +1077,12 @@ pub fn run_tests(opts: &TestOpts, tests: Vec, mut callback: F) where F: FnMut(TestEvent) -> io::Result<()>, { - use std::collections::HashMap; + use std::collections::{self, HashMap}; + use std::hash::BuildHasherDefault; use std::sync::mpsc::RecvTimeoutError; + // Use a deterministic hasher + type TestMap = + HashMap>; let tests_len = tests.len(); @@ -1111,9 +1121,9 @@ where let (tx, rx) = channel::(); - let mut running_tests: HashMap = HashMap::new(); + let mut running_tests: TestMap = HashMap::default(); - fn get_timed_out_tests(running_tests: &mut HashMap) -> Vec { + fn get_timed_out_tests(running_tests: &mut TestMap) -> Vec { let now = Instant::now(); let timed_out = running_tests .iter() @@ -1131,7 +1141,7 @@ where timed_out }; - fn calc_timeout(running_tests: &HashMap) -> Option { + fn calc_timeout(running_tests: &TestMap) -> Option { running_tests.values().min().map(|next_timeout| { let now = Instant::now(); if *next_timeout >= now { @@ -1146,7 +1156,7 @@ where while !remaining.is_empty() { let test = remaining.pop().unwrap(); callback(TeWait(test.desc.clone()))?; - run_test(opts, !opts.run_tests, test, tx.clone()); + run_test(opts, !opts.run_tests, test, tx.clone(), Concurrent::No); let (test, result, stdout) = rx.recv().unwrap(); callback(TeResult(test, result, stdout))?; } @@ -1157,7 +1167,7 @@ where let timeout = Instant::now() + Duration::from_secs(TEST_WARN_TIMEOUT_S); running_tests.insert(test.desc.clone(), timeout); callback(TeWait(test.desc.clone()))?; //here no pad - run_test(opts, !opts.run_tests, test, tx.clone()); + run_test(opts, !opts.run_tests, test, tx.clone(), Concurrent::Yes); pending += 1; } @@ -1189,7 +1199,7 @@ where // All benchmarks run at the end, in serial. for b in filtered_benchs { callback(TeWait(b.desc.clone()))?; - run_test(opts, false, b, tx.clone()); + run_test(opts, false, b, tx.clone(), Concurrent::No); let (test, result, stdout) = rx.recv().unwrap(); callback(TeResult(test, result, stdout))?; } @@ -1246,7 +1256,7 @@ fn get_concurrency() -> usize { 1 } - #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] + #[cfg(any(all(target_arch = "wasm32", not(target_os = "emscripten")), target_env = "sgx"))] fn num_cpus() -> usize { 1 } @@ -1391,6 +1401,7 @@ pub fn run_test( force_ignore: bool, test: TestDescAndFn, monitor_ch: Sender, + concurrency: Concurrent, ) { let TestDescAndFn { desc, testfn } = test; @@ -1407,6 +1418,7 @@ pub fn run_test( monitor_ch: Sender, nocapture: bool, testfn: Box, + concurrency: Concurrent, ) { // Buffer for capturing standard I/O let data = Arc::new(Mutex::new(Vec::new())); @@ -1441,7 +1453,7 @@ pub fn run_test( // the test synchronously, regardless of the concurrency // level. let supports_threads = !cfg!(target_os = "emscripten") && !cfg!(target_arch = "wasm32"); - if supports_threads { + if concurrency == Concurrent::Yes && supports_threads { let cfg = thread::Builder::new().name(name.as_slice().to_owned()); cfg.spawn(runtest).unwrap(); } else { @@ -1462,13 +1474,14 @@ pub fn run_test( } DynTestFn(f) => { let cb = move || __rust_begin_short_backtrace(f); - run_test_inner(desc, monitor_ch, opts.nocapture, Box::new(cb)) + run_test_inner(desc, monitor_ch, opts.nocapture, Box::new(cb), concurrency) } StaticTestFn(f) => run_test_inner( desc, monitor_ch, opts.nocapture, Box::new(move || __rust_begin_short_backtrace(f)), + concurrency, ), } } @@ -1612,7 +1625,7 @@ where // be left doing 0 iterations on every loop. The unfortunate // side effect of not being able to do as many runs is // automatically handled by the statistical analysis below - // (i.e. larger error bars). + // (i.e., larger error bars). n = cmp::max(1, n); let mut total_run = Duration::new(0, 0); @@ -1751,6 +1764,7 @@ mod tests { use std::sync::mpsc::channel; use bench; use Bencher; + use Concurrent; fn one_ignored_one_unignored_test() -> Vec { @@ -1791,7 +1805,7 @@ mod tests { testfn: DynTestFn(Box::new(f)), }; let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, desc, tx); + run_test(&TestOpts::new(), false, desc, tx, Concurrent::No); let (_, res, _) = rx.recv().unwrap(); assert!(res != TrOk); } @@ -1809,7 +1823,7 @@ mod tests { testfn: DynTestFn(Box::new(f)), }; let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, desc, tx); + run_test(&TestOpts::new(), false, desc, tx, Concurrent::No); let (_, res, _) = rx.recv().unwrap(); assert!(res == TrIgnored); } @@ -1829,7 +1843,7 @@ mod tests { testfn: DynTestFn(Box::new(f)), }; let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, desc, tx); + run_test(&TestOpts::new(), false, desc, tx, Concurrent::No); let (_, res, _) = rx.recv().unwrap(); assert!(res == TrOk); } @@ -1849,7 +1863,7 @@ mod tests { testfn: DynTestFn(Box::new(f)), }; let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, desc, tx); + run_test(&TestOpts::new(), false, desc, tx, Concurrent::No); let (_, res, _) = rx.recv().unwrap(); assert!(res == TrOk); } @@ -1871,7 +1885,7 @@ mod tests { testfn: DynTestFn(Box::new(f)), }; let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, desc, tx); + run_test(&TestOpts::new(), false, desc, tx, Concurrent::No); let (_, res, _) = rx.recv().unwrap(); assert!(res == TrFailedMsg(format!("{} '{}'", failed_msg, expected))); } @@ -1889,7 +1903,7 @@ mod tests { testfn: DynTestFn(Box::new(f)), }; let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, desc, tx); + run_test(&TestOpts::new(), false, desc, tx, Concurrent::No); let (_, res, _) = rx.recv().unwrap(); assert!(res == TrFailed); } diff --git a/src/libtest/stats.rs b/src/libtest/stats.rs index 9a8749712c3..1fad612b946 100644 --- a/src/libtest/stats.rs +++ b/src/libtest/stats.rs @@ -224,7 +224,7 @@ impl Stats for [f64] { let x = *s - mean; v = v + x * x; } - // NB: this is _supposed to be_ len-1, not len. If you + // N.B., this is _supposed to be_ len-1, not len. If you // change it back to len, you will be calculating a // population variance, not a sample variance. let denom = (self.len() - 1) as f64; diff --git a/src/libunwind/Cargo.toml b/src/libunwind/Cargo.toml index 4760461df64..2577d6dd31d 100644 --- a/src/libunwind/Cargo.toml +++ b/src/libunwind/Cargo.toml @@ -13,5 +13,5 @@ doc = false [dependencies] core = { path = "../libcore" } -libc = { path = "../rustc/libc_shim" } -compiler_builtins = { path = "../rustc/compiler_builtins_shim" } +libc = { version = "0.2.43", features = ['rustc-dep-of-std'], default-features = false } +compiler_builtins = "0.1.0" diff --git a/src/llvm b/src/llvm index a784eca10d2..f4728ed8fa2 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit a784eca10d2c1f09e65d67e16eca266485e1eac3 +Subproject commit f4728ed8fa2296c5b009bb85550e157e1e57ed0b diff --git a/src/rtstartup/rsbegin.rs b/src/rtstartup/rsbegin.rs index 8ff401164c1..4ec0857f051 100644 --- a/src/rtstartup/rsbegin.rs +++ b/src/rtstartup/rsbegin.rs @@ -96,7 +96,7 @@ pub mod eh_frames { pub mod ms_init { // .CRT$X?? sections are roughly analogous to ELF's .init_array and .fini_array, // except that they exploit the fact that linker will sort them alphabitically, - // so e.g. sections with names between .CRT$XIA and .CRT$XIZ are guaranteed to be + // so e.g., sections with names between .CRT$XIA and .CRT$XIZ are guaranteed to be // placed between those two, without requiring any ordering of objects on the linker // command line. // Note that ordering of same-named sections from different objects is not guaranteed. diff --git a/src/rustc/compiler_builtins_shim/Cargo.toml b/src/rustc/compiler_builtins_shim/Cargo.toml deleted file mode 100644 index 9804177280f..00000000000 --- a/src/rustc/compiler_builtins_shim/Cargo.toml +++ /dev/null @@ -1,40 +0,0 @@ -[package] -name = "compiler_builtins" -authors = ["The Rust Project Developers"] -version = "0.0.0" -build = "../../libcompiler_builtins/build.rs" - -[lib] -path = "../../libcompiler_builtins/src/lib.rs" -test = false -doctest = false - -[dependencies] -# Specify the path to libcore; at the time of writing, removing this shim in -# favor of using compiler-builtins from git results in a compilation failure: -# -# Building stage0 std artifacts (x86_64-apple-darwin -> x86_64-apple-darwin) -# Compiling compiler_builtins v0.1.0 (https://github.com/rust-lang-nursery/compiler-builtins.git#23f14d3f) -# error[E0463]: can't find crate for `core` -# -# error: aborting due to previous error -# -# error: Could not compile `compiler_builtins`. -# -# Caused by: -# process didn't exit successfully: `/Users/tamird/src/rust/build/bootstrap/debug/rustc --crate-name compiler_builtins /Users/tamird/.cargo/git/checkouts/compiler-builtins-ec094dc45a0179c8/23f14d3/src/lib.rs --error-format json --crate-type lib --emit=dep-info,link -C opt-level=2 --cfg feature="c" --cfg feature="compiler-builtins" --cfg feature="default" --cfg feature="gcc" -C metadata=876d429e8d7eae1f -C extra-filename=-876d429e8d7eae1f --out-dir /Users/tamird/src/rust/build/x86_64-apple-darwin/stage0-std/x86_64-apple-darwin/release/deps --target x86_64-apple-darwin -L dependency=/Users/tamird/src/rust/build/x86_64-apple-darwin/stage0-std/x86_64-apple-darwin/release/deps -L dependency=/Users/tamird/src/rust/build/x86_64-apple-darwin/stage0-std/release/deps --cap-lints allow -L native=/Users/tamird/src/rust/build/x86_64-apple-darwin/stage0-std/x86_64-apple-darwin/release/build/compiler_builtins-f18fab55928102ad/out -l static=compiler-rt` (exit code: 101) -# thread 'main' panicked at 'command did not execute successfully: "/Users/tamird/src/rust/build/x86_64-apple-darwin/stage0/bin/cargo" "build" "-j" "4" "--target" "x86_64-apple-darwin" "--release" "--features" "panic-unwind jemalloc backtrace" "--manifest-path" "/Users/tamird/src/rust/src/libstd/Cargo.toml" "--message-format" "json" -# expected success, got: exit code: 101', src/bootstrap/compile.rs:883:8 -# -# See https://github.com/rust-lang/rfcs/pull/1133. -core = { path = "../../libcore" } - -[build-dependencies] -cc = "1.0.1" - -[features] -c = [] -default = ["rustbuild", "compiler-builtins"] -mem = [] -rustbuild = [] -compiler-builtins = [] diff --git a/src/rustc/compiler_builtins_shim/build.rs b/src/rustc/compiler_builtins_shim/build.rs deleted file mode 100644 index b37543e5f67..00000000000 --- a/src/rustc/compiler_builtins_shim/build.rs +++ /dev/null @@ -1,15 +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. - -// This file is left intentionally empty (and not removed) to avoid an issue -// where this crate is always considered dirty due to compiler-builtins' -// `cargo:rerun-if-changed=build.rs` directive; since the path is relative, it -// refers to this file when this shim crate is being built, and the absence of -// this file is considered by cargo to be equivalent to it having changed. diff --git a/src/rustc/dlmalloc_shim/Cargo.toml b/src/rustc/dlmalloc_shim/Cargo.toml deleted file mode 100644 index b6f8550829f..00000000000 --- a/src/rustc/dlmalloc_shim/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "dlmalloc" -version = "0.0.0" -authors = ["The Rust Project Developers"] - -[lib] -path = "../../dlmalloc/src/lib.rs" -test = false -bench = false -doc = false - -[dependencies] -core = { path = "../../libcore" } -compiler_builtins = { path = "../../rustc/compiler_builtins_shim" } diff --git a/src/rustc/libc_shim/Cargo.toml b/src/rustc/libc_shim/Cargo.toml deleted file mode 100644 index ee037ac68c5..00000000000 --- a/src/rustc/libc_shim/Cargo.toml +++ /dev/null @@ -1,40 +0,0 @@ -[package] -name = "libc" -version = "0.0.0" -authors = ["The Rust Project Developers"] - -[lib] -name = "libc" -path = "../../liblibc/src/lib.rs" -test = false -bench = false -doc = false - -[dependencies] -# Specify the path to libcore; at the time of writing, removing this shim in -# favor of using libc from git results in a compilation failure: -# -# Building stage0 std artifacts (x86_64-apple-darwin -> x86_64-apple-darwin) -# Compiling libc v0.0.0 (file:///Users/tamird/src/rust/src/rustc/libc_shim) -# error[E0463]: can't find crate for `core` -# -# error: aborting due to previous error -# -# error: Could not compile `libc`. -# -# Caused by: -# process didn't exit successfully: `/Users/tamird/src/rust/build/bootstrap/debug/rustc --crate-name libc src/rustc/libc_shim/../../liblibc/src/lib.rs --error-format json --crate-type lib --emit=dep-info,link -C opt-level=2 --cfg feature="default" --cfg feature="no_std" --cfg feature="stdbuild" -C metadata=d758f87058112d7d -C extra-filename=-d758f87058112d7d --out-dir /Users/tamird/src/rust/build/x86_64-apple-darwin/stage0-std/x86_64-apple-darwin/release/deps --target x86_64-apple-darwin -L dependency=/Users/tamird/src/rust/build/x86_64-apple-darwin/stage0-std/x86_64-apple-darwin/release/deps -L dependency=/Users/tamird/src/rust/build/x86_64-apple-darwin/stage0-std/release/deps` (exit code: 101) -# thread 'main' panicked at 'command did not execute successfully: "/Users/tamird/src/rust/build/x86_64-apple-darwin/stage0/bin/cargo" "build" "-j" "4" "--target" "x86_64-apple-darwin" "--release" "--features" "panic-unwind jemalloc backtrace" "--manifest-path" "/Users/tamird/src/rust/src/libstd/Cargo.toml" "--message-format" "json" -# expected success, got: exit code: 101', src/bootstrap/compile.rs:883:8 -# -# See https://github.com/rust-lang/rfcs/pull/1133. -core = { path = "../../libcore" } -compiler_builtins = { path = "../compiler_builtins_shim" } - - -[features] -# Certain parts of libc are conditionally compiled differently than when used -# outside rustc. See https://github.com/rust-lang/libc/search?l=Rust&q=stdbuild&type=&utf8=%E2%9C%93. -stdbuild = [] -default = ["stdbuild", "align"] -align = [] diff --git a/src/rustllvm/ArchiveWrapper.cpp b/src/rustllvm/ArchiveWrapper.cpp index 1355c0377ce..2f8dc0d466f 100644 --- a/src/rustllvm/ArchiveWrapper.cpp +++ b/src/rustllvm/ArchiveWrapper.cpp @@ -216,16 +216,11 @@ LLVMRustWriteArchive(char *Dst, size_t NumMembers, Members.push_back(std::move(*MOrErr)); } } + auto Result = writeArchive(Dst, Members, WriteSymbtab, Kind, true, false); -#if LLVM_VERSION_GE(6, 0) if (!Result) return LLVMRustResult::Success; LLVMRustSetLastError(toString(std::move(Result)).c_str()); -#else - if (!Result.second) - return LLVMRustResult::Success; - LLVMRustSetLastError(Result.second.message().c_str()); -#endif return LLVMRustResult::Failure; } diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index aa420bf6100..4d95368c00f 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -17,21 +17,15 @@ #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/IR/AutoUpgrade.h" #include "llvm/IR/AssemblyAnnotationWriter.h" +#include "llvm/IR/IntrinsicInst.h" #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Host.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/IPO/PassManagerBuilder.h" - -#if LLVM_VERSION_GE(6, 0) -#include "llvm/CodeGen/TargetSubtargetInfo.h" -#include "llvm/IR/IntrinsicInst.h" -#else -#include "llvm/Target/TargetSubtargetInfo.h" -#endif - #include "llvm/Transforms/IPO/AlwaysInliner.h" #include "llvm/Transforms/IPO/FunctionImport.h" #include "llvm/Transforms/Utils/FunctionImportUtils.h" @@ -198,13 +192,9 @@ GEN_SUBTARGETS extern "C" bool LLVMRustHasFeature(LLVMTargetMachineRef TM, const char *Feature) { -#if LLVM_VERSION_GE(6, 0) TargetMachine *Target = unwrap(TM); const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo(); return MCInfo->checkFeatures(std::string("+") + Feature); -#else - return false; -#endif } enum class LLVMRustCodeModel { @@ -392,13 +382,9 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( Options.ThreadModel = ThreadModel::Single; } -#if LLVM_VERSION_GE(6, 0) Options.EmitStackSizeSection = EmitStackSizeSection; Optional CM; -#else - CodeModel::Model CM = CodeModel::Model::Default; -#endif if (RustCM != LLVMRustCodeModel::None) CM = fromRust(RustCM); TargetMachine *TM = TheTarget->createTargetMachine( diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index b9a0b435d3e..86c5dfcfb98 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -297,11 +297,7 @@ extern "C" void LLVMRustRemoveFunctionAttributes(LLVMValueRef Fn, // enable fpmath flag UnsafeAlgebra extern "C" void LLVMRustSetHasUnsafeAlgebra(LLVMValueRef V) { if (auto I = dyn_cast(unwrap(V))) { -#if LLVM_VERSION_GE(6, 0) I->setFast(true); -#else - I->setHasUnsafeAlgebra(true); -#endif } } @@ -1437,7 +1433,6 @@ LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) { return wrap(unwrap(B)->CreateFPMaxReduce(unwrap(Src), NoNaN)); } -#if LLVM_VERSION_GE(6, 0) extern "C" LLVMValueRef LLVMRustBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) { return wrap(unwrap(B)->CreateMinNum(unwrap(LHS),unwrap(RHS))); @@ -1446,13 +1441,3 @@ extern "C" LLVMValueRef LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) { return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS),unwrap(RHS))); } -#else -extern "C" LLVMValueRef -LLVMRustBuildMinNum(LLVMBuilderRef, LLVMValueRef, LLVMValueRef) { - return nullptr; -} -extern "C" LLVMValueRef -LLVMRustBuildMaxNum(LLVMBuilderRef, LLVMValueRef, LLVMValueRef) { - return nullptr; -} -#endif diff --git a/src/rustllvm/llvm-rebuild-trigger b/src/rustllvm/llvm-rebuild-trigger index 9cf17c45e87..a268838de45 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-11-28 +2018-12-13 diff --git a/src/stage0.txt b/src/stage0.txt index 9326e22090c..843ecae1ce3 100644 --- a/src/stage0.txt +++ b/src/stage0.txt @@ -12,7 +12,7 @@ # source tarball for a stable release you'll likely see `1.x.0` for rustc and # `0.x.0` for Cargo where they were released on `date`. -date: 2018-10-30 +date: 2018-12-09 rustc: beta cargo: beta diff --git a/src/stdsimd b/src/stdsimd index 0309be1ade6..3c0503db843 160000 --- a/src/stdsimd +++ b/src/stdsimd @@ -1 +1 @@ -Subproject commit 0309be1ade6bf61066f2c69f77ac3567b7dc31b5 +Subproject commit 3c0503db8439928e42c1175f0009c506fc874ae9 diff --git a/src/test/codegen-units/item-collection/unreferenced-inline-function.rs b/src/test/codegen-units/item-collection/unreferenced-inline-function.rs index 829b4fbf3c9..28c1f0a54bf 100644 --- a/src/test/codegen-units/item-collection/unreferenced-inline-function.rs +++ b/src/test/codegen-units/item-collection/unreferenced-inline-function.rs @@ -11,7 +11,7 @@ // ignore-tidy-linelength // compile-flags:-Zprint-mono-items=lazy -// NB: We do not expect *any* monomorphization to be generated here. +// N.B., we do not expect *any* monomorphization to be generated here. #![deny(dead_code)] #![crate_type = "rlib"] diff --git a/src/test/codegen/external-no-mangle-fns.rs b/src/test/codegen/external-no-mangle-fns.rs index 58232852596..e6b952ec9f6 100644 --- a/src/test/codegen/external-no-mangle-fns.rs +++ b/src/test/codegen/external-no-mangle-fns.rs @@ -9,7 +9,7 @@ // except according to those terms. // compile-flags: -C no-prepopulate-passes -// `#[no_mangle]`d functions always have external linkage, i.e. no `internal` in their `define`s +// `#[no_mangle]`d functions always have external linkage, i.e., no `internal` in their `define`s #![crate_type = "lib"] #![no_std] diff --git a/src/test/codegen/external-no-mangle-statics.rs b/src/test/codegen/external-no-mangle-statics.rs index 59d829633e5..b1488e3b8d0 100644 --- a/src/test/codegen/external-no-mangle-statics.rs +++ b/src/test/codegen/external-no-mangle-statics.rs @@ -9,7 +9,7 @@ // except according to those terms. // compile-flags: -O -// `#[no_mangle]`d static variables always have external linkage, i.e. no `internal` in their +// `#[no_mangle]`d static variables always have external linkage, i.e., no `internal` in their // definitions #![crate_type = "lib"] diff --git a/src/test/codegen/function-arguments.rs b/src/test/codegen/function-arguments.rs index 5061d9a915e..52bdb1b103a 100644 --- a/src/test/codegen/function-arguments.rs +++ b/src/test/codegen/function-arguments.rs @@ -10,7 +10,6 @@ // compile-flags: -C no-prepopulate-passes // ignore-tidy-linelength -// min-llvm-version 6.0 #![crate_type = "lib"] #![feature(custom_attribute)] diff --git a/src/test/codegen/issue-44056-macos-tls-align.rs b/src/test/codegen/issue-44056-macos-tls-align.rs index b146e106aa1..ebd436cc647 100644 --- a/src/test/codegen/issue-44056-macos-tls-align.rs +++ b/src/test/codegen/issue-44056-macos-tls-align.rs @@ -11,7 +11,6 @@ // ignore-tidy-linelength // only-macos // no-system-llvm -// min-llvm-version 6.0 // compile-flags: -O #![crate_type = "rlib"] diff --git a/src/test/codegen/issue-45222.rs b/src/test/codegen/issue-45222.rs index 3544786e2e6..a6e633bf285 100644 --- a/src/test/codegen/issue-45222.rs +++ b/src/test/codegen/issue-45222.rs @@ -9,7 +9,6 @@ // except according to those terms. // compile-flags: -O -// min-llvm-version 6.0 #![crate_type = "lib"] diff --git a/src/test/codegen/issue-45466.rs b/src/test/codegen/issue-45466.rs index 14954763944..f916c1a0640 100644 --- a/src/test/codegen/issue-45466.rs +++ b/src/test/codegen/issue-45466.rs @@ -9,7 +9,6 @@ // except according to those terms. // compile-flags: -O -// min-llvm-version 6.0 #![crate_type="rlib"] diff --git a/src/test/ui/feature-gate-exhaustive_integer_patterns.rs b/src/test/codegen/nounwind-extern.rs similarity index 78% rename from src/test/ui/feature-gate-exhaustive_integer_patterns.rs rename to src/test/codegen/nounwind-extern.rs index 3aa15229455..ed07cf1d6b2 100644 --- a/src/test/ui/feature-gate-exhaustive_integer_patterns.rs +++ b/src/test/codegen/nounwind-extern.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn main() { - let x: u8 = 0; - match x { //~ ERROR non-exhaustive patterns: `_` not covered - 0 ..= 255 => {} - } -} +// compile-flags: -O + +#![crate_type = "lib"] + +// CHECK: Function Attrs: norecurse nounwind +pub extern fn foo() {} diff --git a/src/test/codegen/packed.rs b/src/test/codegen/packed.rs index b50f5b6f16f..fb6507fd22a 100644 --- a/src/test/codegen/packed.rs +++ b/src/test/codegen/packed.rs @@ -13,7 +13,6 @@ // min-llvm-version 7.0 #![crate_type = "lib"] -#![feature(repr_packed)] #[repr(packed)] pub struct Packed1 { diff --git a/src/test/codegen/simd-intrinsic-generic-gather.rs b/src/test/codegen/simd-intrinsic-generic-gather.rs index 6c47bf3e321..605a952e8ff 100644 --- a/src/test/codegen/simd-intrinsic-generic-gather.rs +++ b/src/test/codegen/simd-intrinsic-generic-gather.rs @@ -10,7 +10,6 @@ // ignore-emscripten // ignore-tidy-linelength -// min-llvm-version 6.0 // compile-flags: -C no-prepopulate-passes diff --git a/src/test/codegen/simd-intrinsic-generic-scatter.rs b/src/test/codegen/simd-intrinsic-generic-scatter.rs index 7b5b2e55e29..6645778468c 100644 --- a/src/test/codegen/simd-intrinsic-generic-scatter.rs +++ b/src/test/codegen/simd-intrinsic-generic-scatter.rs @@ -10,7 +10,6 @@ // ignore-emscripten // ignore-tidy-linelength -// min-llvm-version 6.0 // compile-flags: -C no-prepopulate-passes diff --git a/src/test/codegen/simd-intrinsic-generic-select.rs b/src/test/codegen/simd-intrinsic-generic-select.rs index 8a64d7437d8..24a4b2b1b05 100644 --- a/src/test/codegen/simd-intrinsic-generic-select.rs +++ b/src/test/codegen/simd-intrinsic-generic-select.rs @@ -19,12 +19,17 @@ #[derive(Copy, Clone, PartialEq, Debug)] pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x8(f32, f32, f32, f32, f32, f32, f32, f32); + #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] pub struct b8x4(pub i8, pub i8, pub i8, pub i8); extern "platform-intrinsic" { fn simd_select(x: T, a: U, b: U) -> U; + fn simd_select_bitmask(x: T, a: U, b: U) -> U; } // CHECK-LABEL: @select @@ -33,3 +38,10 @@ pub unsafe fn select(m: b8x4, a: f32x4, b: f32x4) -> f32x4 { // CHECK: select <4 x i1> simd_select(m, a, b) } + +// CHECK-LABEL: @select_bitmask +#[no_mangle] +pub unsafe fn select_bitmask(m: i8, a: f32x8, b: f32x8) -> f32x8 { + // CHECK: select <8 x i1> + simd_select_bitmask(m, a, b) +} diff --git a/src/test/codegen/vtabletype.rs b/src/test/codegen/vtabletype.rs index abd1eb3e2cc..cb96a844341 100644 --- a/src/test/codegen/vtabletype.rs +++ b/src/test/codegen/vtabletype.rs @@ -14,7 +14,6 @@ // ignore-tidy-linelength // ignore-windows // ignore-macos -// min-llvm-version 6.0 // compile-flags: -g -C no-prepopulate-passes diff --git a/src/test/compile-fail-fulldeps/auxiliary/lint_group_plugin_test.rs b/src/test/compile-fail-fulldeps/auxiliary/lint_group_plugin_test.rs deleted file mode 100644 index f697642f843..00000000000 --- a/src/test/compile-fail-fulldeps/auxiliary/lint_group_plugin_test.rs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2014 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 - -#![feature(plugin_registrar)] -#![feature(box_syntax, rustc_private)] - -// Load rustc as a plugin to get macros -#[macro_use] -extern crate rustc; -extern crate rustc_plugin; - -use rustc::hir; -use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LateLintPassObject, LintArray}; -use rustc_plugin::Registry; - -declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); - -declare_lint!(PLEASE_LINT, Warn, "Warn about items named 'pleaselintme'"); - -struct Pass; - -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(TEST_LINT, PLEASE_LINT) - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { - fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { - match &*it.name.as_str() { - "lintme" => cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'"), - "pleaselintme" => cx.span_lint(PLEASE_LINT, it.span, "item is named 'pleaselintme'"), - _ => {} - } - } -} - -#[plugin_registrar] -pub fn plugin_registrar(reg: &mut Registry) { - reg.register_late_lint_pass(box Pass); - reg.register_lint_group("lint_me", None, vec![TEST_LINT, PLEASE_LINT]); -} diff --git a/src/test/compile-fail-fulldeps/auxiliary/lint_plugin_test.rs b/src/test/compile-fail-fulldeps/auxiliary/lint_plugin_test.rs deleted file mode 100644 index 8647797270f..00000000000 --- a/src/test/compile-fail-fulldeps/auxiliary/lint_plugin_test.rs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2014 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 - -#![feature(plugin_registrar)] -#![feature(box_syntax, rustc_private)] - -extern crate syntax; - -// Load rustc as a plugin to get macros -#[macro_use] -extern crate rustc; -extern crate rustc_plugin; - -use rustc::lint::{EarlyContext, LintContext, LintPass, EarlyLintPass, - EarlyLintPassObject, LintArray}; -use rustc_plugin::Registry; -use syntax::ast; -declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); - -struct Pass; - -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(TEST_LINT) - } -} - -impl EarlyLintPass for Pass { - fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) { - if it.ident.name == "lintme" { - cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'"); - } - } -} - -#[plugin_registrar] -pub fn plugin_registrar(reg: &mut Registry) { - reg.register_early_lint_pass(box Pass as EarlyLintPassObject); -} diff --git a/src/test/compile-fail/const-fn-error.rs b/src/test/compile-fail/const-fn-error.rs index 17dc9f94fe1..397bc7efd63 100644 --- a/src/test/compile-fail/const-fn-error.rs +++ b/src/test/compile-fail/const-fn-error.rs @@ -8,14 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(const_fn)] +#![feature(const_fn, const_let)] const X : usize = 2; const fn f(x: usize) -> usize { let mut sum = 0; - //~^ let bindings in constant functions are unstable - //~| statements in constant functions are unstable for i in 0..x { //~^ ERROR E0015 //~| ERROR E0019 diff --git a/src/test/compile-fail/issue-10755.rs b/src/test/compile-fail/issue-10755.rs index 57915bce456..bb77748a416 100644 --- a/src/test/compile-fail/issue-10755.rs +++ b/src/test/compile-fail/issue-10755.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -C linker=llllll -Z linker-flavor=ld +// compile-flags: -C linker=llllll -C linker-flavor=ld // error-pattern: linker `llllll` not found fn main() { diff --git a/src/test/compile-fail/must_use-in-stdlib-traits.rs b/src/test/compile-fail/must_use-in-stdlib-traits.rs new file mode 100644 index 00000000000..4bb5c59722a --- /dev/null +++ b/src/test/compile-fail/must_use-in-stdlib-traits.rs @@ -0,0 +1,47 @@ +#![deny(unused_must_use)] +#![feature(futures_api, pin, arbitrary_self_types)] + +use std::iter::Iterator; +use std::future::Future; + +use std::task::{Poll, LocalWaker}; +use std::pin::Pin; +use std::unimplemented; + +struct MyFuture; + +impl Future for MyFuture { + type Output = u32; + + fn poll(self: Pin<&mut Self>, lw: &LocalWaker) -> Poll { + Poll::Pending + } +} + +fn iterator() -> impl Iterator { + std::iter::empty::() +} + +fn future() -> impl Future { + MyFuture +} + +fn square_fn_once() -> impl FnOnce(u32) -> u32 { + |x| x * x +} + +fn square_fn_mut() -> impl FnMut(u32) -> u32 { + |x| x * x +} + +fn square_fn() -> impl Fn(u32) -> u32 { + |x| x * x +} + +fn main() { + iterator(); //~ ERROR unused implementer of `std::iter::Iterator` that must be used + future(); //~ ERROR unused implementer of `std::future::Future` that must be used + square_fn_once(); //~ ERROR unused implementer of `std::ops::FnOnce` that must be used + square_fn_mut(); //~ ERROR unused implementer of `std::ops::FnMut` that must be used + square_fn(); //~ ERROR unused implementer of `std::ops::Fn` that must be used +} diff --git a/src/test/compile-fail/nolink-with-link-args.rs b/src/test/compile-fail/nolink-with-link-args.rs index 6dfd74f541e..95f827ecb63 100644 --- a/src/test/compile-fail/nolink-with-link-args.rs +++ b/src/test/compile-fail/nolink-with-link-args.rs @@ -9,7 +9,7 @@ // except according to those terms. // error-pattern:aFdEfSeVEE -// compile-flags: -Z linker-flavor=ld +// compile-flags: -C linker-flavor=ld /* We're testing that link_args are indeed passed when nolink is specified. So we try to compile with junk link_args and make sure they are visible in diff --git a/src/test/compile-fail/proc-macro/auxiliary/derive-clona.rs b/src/test/compile-fail/proc-macro/auxiliary/derive-clona.rs deleted file mode 100644 index 719fbdb15ef..00000000000 --- a/src/test/compile-fail/proc-macro/auxiliary/derive-clona.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_derive(Clona)] -pub fn derive_clonea(input: TokenStream) -> TokenStream { - "".parse().unwrap() -} diff --git a/src/test/compile-fail/proc-macro/auxiliary/derive-foo.rs b/src/test/compile-fail/proc-macro/auxiliary/derive-foo.rs deleted file mode 100644 index 64dcf72ba20..00000000000 --- a/src/test/compile-fail/proc-macro/auxiliary/derive-foo.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_derive(FooWithLongName)] -pub fn derive_foo(input: TokenStream) -> TokenStream { - "".parse().unwrap() -} diff --git a/src/test/debuginfo/function-call.rs b/src/test/debuginfo/function-call.rs new file mode 100644 index 00000000000..266e536e8f2 --- /dev/null +++ b/src/test/debuginfo/function-call.rs @@ -0,0 +1,52 @@ +// 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. + +// This test does not passed with gdb < 8.0. See #53497. +// min-gdb-version 8.0 + +// compile-flags:-g + +// === GDB TESTS =================================================================================== + +// gdb-command:run + +// gdb-command:print fun(45, true) +// gdb-check:$1 = true +// gdb-command:print fun(444, false) +// gdb-check:$2 = false + +// gdb-command:print r.get_x() +// gdb-check:$3 = 4 + +#![allow(dead_code, unused_variables)] + +struct RegularStruct { + x: i32 +} + +impl RegularStruct { + fn get_x(&self) -> i32 { + self.x + } +} + +fn main() { + let _ = fun(4, true); + let r = RegularStruct{x: 4}; + let _ = r.get_x(); + + zzz(); // #break +} + +fn fun(x: isize, y: bool) -> bool { + y +} + +fn zzz() { () } diff --git a/src/test/debuginfo/nil-enum.rs b/src/test/debuginfo/nil-enum.rs deleted file mode 100644 index ab42b2eff99..00000000000 --- a/src/test/debuginfo/nil-enum.rs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2013-2014 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. - -// NOTE Instantiating an empty enum is UB. This test may break in the future. - -// LLDB can't handle zero-sized values -// ignore-lldb - - -// Require LLVM with DW_TAG_variant_part and a gdb that can read it. -// gdb 8.2.0 crashes on this test case, see -// https://sourceware.org/bugzilla/show_bug.cgi?id=23626 -// This will be fixed in the next release, which will be >= 8.2.1. -// min-system-llvm-version: 7.0 -// min-gdb-version: 8.2.1 - -// compile-flags:-g -// gdb-command:run - -// gdb-command:print first -// gdbr-check:$1 = nil_enum::ANilEnum {} - -// gdb-command:print second -// gdbr-check:$2 = nil_enum::AnotherNilEnum {} - -#![allow(unused_variables)] -#![feature(omit_gdb_pretty_printer_section)] -#![feature(maybe_uninit)] -#![omit_gdb_pretty_printer_section] - -use std::mem::MaybeUninit; - -enum ANilEnum {} -enum AnotherNilEnum {} - -// This test relies on gdbg printing the string "{}" for empty -// structs (which may change some time) -// The error from gdbr is expected since nil enums are not supposed to exist. -fn main() { - unsafe { - let first: ANilEnum = MaybeUninit::uninitialized().into_inner(); - let second: AnotherNilEnum = MaybeUninit::uninitialized().into_inner(); - - zzz(); // #break - } -} - -fn zzz() {()} diff --git a/src/test/debuginfo/pretty-std-collections.rs b/src/test/debuginfo/pretty-std-collections.rs index a51be370aa4..350b30d2cc1 100644 --- a/src/test/debuginfo/pretty-std-collections.rs +++ b/src/test/debuginfo/pretty-std-collections.rs @@ -13,7 +13,11 @@ // ignore-freebsd: gdb package too new // ignore-android: FIXME(#10381) // compile-flags:-g -// min-gdb-version 7.7 + +// The pretty printers being tested here require the patch from +// https://sourceware.org/bugzilla/show_bug.cgi?id=21763 +// min-gdb-version 8.1 + // min-lldb-version: 310 // === GDB TESTS =================================================================================== diff --git a/src/test/debuginfo/type-names.rs b/src/test/debuginfo/type-names.rs index 3ec8b048b12..8b4b10ad23c 100644 --- a/src/test/debuginfo/type-names.rs +++ b/src/test/debuginfo/type-names.rs @@ -280,7 +280,7 @@ extern { } // In many of the cases below, the type that is actually under test is wrapped -// in a tuple, e.g. Box, references, raw pointers, fixed-size vectors, ... +// in a tuple, e.g., Box, references, raw pointers, fixed-size vectors, ... // This is because GDB will not print the type name from DWARF debuginfo for // some kinds of types (pointers, arrays, functions, ...) // Since tuples are structs as far as GDB is concerned, their name will be diff --git a/src/test/incremental/foreign.rs b/src/test/incremental/foreign.rs index dbdebefaf31..648e89be037 100644 --- a/src/test/incremental/foreign.rs +++ b/src/test/incremental/foreign.rs @@ -13,7 +13,7 @@ // revisions: rpass1 -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; diff --git a/src/test/incremental/hashes/panic_exprs.rs b/src/test/incremental/hashes/panic_exprs.rs index ffb66c29219..f2d610c1ade 100644 --- a/src/test/incremental/hashes/panic_exprs.rs +++ b/src/test/incremental/hashes/panic_exprs.rs @@ -9,7 +9,7 @@ // except according to those terms. // This test case tests the incremental compilation hash (ICH) implementation -// for exprs that can panic at runtime (e.g. because of bounds checking). For +// for exprs that can panic at runtime (e.g., because of bounds checking). For // these expressions an error message containing their source location is // generated, so their hash must always depend on their location in the source // code, not just when debuginfo is enabled. diff --git a/src/test/incremental/hashes/struct_defs.rs b/src/test/incremental/hashes/struct_defs.rs index 10b1beb0413..06842e3c6c4 100644 --- a/src/test/incremental/hashes/struct_defs.rs +++ b/src/test/incremental/hashes/struct_defs.rs @@ -340,7 +340,7 @@ struct AddTypeParameterBoundWhereClause( // Empty struct ---------------------------------------------------------------- // Since we cannot change anything in this case, we just make sure that the -// fingerprint is stable (i.e. that there are no random influences like memory +// fingerprint is stable (i.e., that there are no random influences like memory // addresses taken into account by the hashing algorithm). // Note: there is no #[cfg(...)], so this is ALWAYS compiled #[rustc_clean(label="Hir", cfg="cfail2")] diff --git a/src/test/mir-opt/match_test.rs b/src/test/mir-opt/match_test.rs new file mode 100644 index 00000000000..9bfb728e134 --- /dev/null +++ b/src/test/mir-opt/match_test.rs @@ -0,0 +1,85 @@ +// Make sure redundant testing paths in `match` expressions are sorted out. + +#![feature(exclusive_range_pattern)] + +fn main() { + let x = 3; + let b = true; + + // When `(0..=10).contains(x) && !b`, we should jump to the last arm + // without testing two other candidates. + match x { + 0..10 if b => 0, + 10..=20 => 1, + -1 => 2, + _ => 3, + }; +} + +// END RUST SOURCE +// START rustc.main.SimplifyCfg-initial.after.mir +// bb0: { +// ... +// _4 = Le(const 0i32, _1); +// switchInt(move _4) -> [false: bb10, otherwise: bb11]; +// } +// bb1: { +// _3 = const 0i32; +// goto -> bb16; +// } +// bb2: { +// _3 = const 1i32; +// goto -> bb16; +// } +// bb3: { +// _3 = const 2i32; +// goto -> bb16; +// } +// bb4: { +// _3 = const 3i32; +// goto -> bb16; +// } +// bb5: { +// falseEdges -> [real: bb12, imaginary: bb6]; +// } +// bb6: { +// falseEdges -> [real: bb2, imaginary: bb7]; +// } +// bb7: { +// falseEdges -> [real: bb3, imaginary: bb8]; +// } +// bb8: { +// falseEdges -> [real: bb4, imaginary: bb9]; +// } +// bb9: { +// unreachable; +// } +// bb10: { +// _7 = Le(const 10i32, _1); +// switchInt(move _7) -> [false: bb14, otherwise: bb15]; +// } +// bb11: { +// _5 = Lt(_1, const 10i32); +// switchInt(move _5) -> [false: bb10, otherwise: bb5]; +// } +// bb12: { +// StorageLive(_6); +// _6 = _2; +// switchInt(move _6) -> [false: bb13, otherwise: bb1]; +// } +// bb13: { +// falseEdges -> [real: bb8, imaginary: bb6]; +// } +// bb14: { +// switchInt(_1) -> [-1i32: bb7, otherwise: bb8]; +// } +// bb15: { +// _8 = Le(_1, const 20i32); +// switchInt(move _8) -> [false: bb14, otherwise: bb6]; +// } +// bb16: { +// StorageDead(_6); +// ... +// return; +// } +// END rustc.main.SimplifyCfg-initial.after.mir diff --git a/src/test/mir-opt/retag.rs b/src/test/mir-opt/retag.rs index 7da55c0868c..f48862ff933 100644 --- a/src/test/mir-opt/retag.rs +++ b/src/test/mir-opt/retag.rs @@ -87,8 +87,8 @@ fn main() { // ... // _14 = &mut (*_10); // Retag(_14); -// EscapeToRaw(move _14); // _13 = move _14 as *mut i32 (Misc); +// Retag([raw] _13); // ... // _17 = move _18(move _19) -> bb2; // } diff --git a/src/test/mir-opt/simplify_cfg.rs b/src/test/mir-opt/simplify_cfg.rs new file mode 100644 index 00000000000..ef843f71581 --- /dev/null +++ b/src/test/mir-opt/simplify_cfg.rs @@ -0,0 +1,54 @@ +// Test that the goto chain starting from bb0 is collapsed. + +fn main() { + loop { + if bar() { + break; + } + } +} + +#[inline(never)] +fn bar() -> bool { + true +} + +// END RUST SOURCE +// START rustc.main.SimplifyCfg-initial.before.mir +// bb0: { +// goto -> bb1; +// } +// bb1: { +// falseUnwind -> [real: bb3, cleanup: bb4]; +// } +// ... +// bb11: { +// ... +// goto -> bb1; +// } +// END rustc.main.SimplifyCfg-initial.before.mir +// START rustc.main.SimplifyCfg-initial.after.mir +// bb0: { +// falseUnwind -> [real: bb1, cleanup: bb2]; +// } +// ... +// bb5: { +// ... +// goto -> bb0; +// } +// END rustc.main.SimplifyCfg-initial.after.mir +// START rustc.main.SimplifyCfg-early-opt.before.mir +// bb0: { +// goto -> bb1; +// } +// bb1: { +// StorageLive(_2); +// _2 = const bar() -> bb3; +// } +// END rustc.main.SimplifyCfg-early-opt.before.mir +// START rustc.main.SimplifyCfg-early-opt.after.mir +// bb0: { +// StorageLive(_2); +// _2 = const bar() -> bb1; +// } +// END rustc.main.SimplifyCfg-early-opt.after.mir diff --git a/src/test/mir-opt/uninhabited-enum.rs b/src/test/mir-opt/uninhabited-enum.rs new file mode 100644 index 00000000000..904a9c43c1b --- /dev/null +++ b/src/test/mir-opt/uninhabited-enum.rs @@ -0,0 +1,37 @@ +#![feature(never_type)] + +pub enum Void {} + +#[no_mangle] +pub fn process_never(input: *const !) { + let _input = unsafe { &*input }; +} + +#[no_mangle] +pub fn process_void(input: *const Void) { + let _input = unsafe { &*input }; + // In the future, this should end with `unreachable`, but we currently only do + // unreachability analysis for `!`. +} + +fn main() {} + +// END RUST SOURCE +// +// START rustc.process_never.SimplifyLocals.after.mir +// bb0: { +// StorageLive(_2); +// _2 = &(*_1); +// StorageDead(_2); +// unreachable; +// } +// END rustc.process_never.SimplifyLocals.after.mir +// +// START rustc.process_void.SimplifyLocals.after.mir +// bb0: { +// StorageLive(_2); +// _2 = &(*_1); +// StorageDead(_2); +// return; +// } +// END rustc.process_void.SimplifyLocals.after.mir diff --git a/src/test/pretty/block-disambig.rs b/src/test/pretty/block-disambig.rs index c645a66b70e..aed34bf3585 100644 --- a/src/test/pretty/block-disambig.rs +++ b/src/test/pretty/block-disambig.rs @@ -11,7 +11,7 @@ // compile-flags: --crate-type=lib // A bunch of tests for syntactic forms involving blocks that were -// previously ambiguous (e.g. 'if true { } *val;' gets parsed as a +// previously ambiguous (e.g., 'if true { } *val;' gets parsed as a // binop) diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp index 5f42b86c82a..3b01ab3a47b 100644 --- a/src/test/pretty/issue-4264.pp +++ b/src/test/pretty/issue-4264.pp @@ -39,8 +39,8 @@ pub fn bar() ({ - ((::fmt::format as - for<'r> fn(std::fmt::Arguments<'r>) -> std::string::String {std::fmt::format})(((<::fmt::Arguments>::new_v1 + (($crate::fmt::format as + for<'r> fn(std::fmt::Arguments<'r>) -> std::string::String {std::fmt::format})(((<$crate::fmt::Arguments>::new_v1 as fn(&[&str], &[std::fmt::ArgumentV1<'_>]) -> std::fmt::Arguments<'_> {std::fmt::Arguments<'_>::new_v1})((&([("test" as diff --git a/src/test/run-make-fulldeps/atomic-lock-free/Makefile b/src/test/run-make-fulldeps/atomic-lock-free/Makefile index a7df821f92d..9e8b4fabf17 100644 --- a/src/test/run-make-fulldeps/atomic-lock-free/Makefile +++ b/src/test/run-make-fulldeps/atomic-lock-free/Makefile @@ -18,6 +18,8 @@ ifeq ($(filter arm,$(LLVM_COMPONENTS)),arm) nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add $(RUSTC) --target=armv7-unknown-linux-gnueabihf atomic_lock_free.rs nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add + $(RUSTC) --target=thumbv7neon-unknown-linux-gnueabihf atomic_lock_free.rs + nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add endif ifeq ($(filter aarch64,$(LLVM_COMPONENTS)),aarch64) $(RUSTC) --target=aarch64-unknown-linux-gnu atomic_lock_free.rs diff --git a/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/checkrust.rs b/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/checkrust.rs index 90ad6011526..0254c7cf403 100644 --- a/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/checkrust.rs +++ b/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/checkrust.rs @@ -10,7 +10,7 @@ #![crate_type = "staticlib"] #![feature(c_variadic)] -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; diff --git a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs index 87d2026fe2d..3d3cb2c473b 100644 --- a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs +++ b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs @@ -78,5 +78,5 @@ impl CodegenBackend for TheBackend { /// This is the entrypoint for a hot plugged rustc_codegen_llvm #[no_mangle] pub fn __rustc_codegen_backend() -> Box { - Box::new(TheBackend(MetadataOnlyCodegenBackend::new())) + Box::new(TheBackend(MetadataOnlyCodegenBackend::boxed())) } diff --git a/src/test/run-make-fulldeps/issue-19371/foo.rs b/src/test/run-make-fulldeps/issue-19371/foo.rs index 4dfecb33c14..c342e1c4835 100644 --- a/src/test/run-make-fulldeps/issue-19371/foo.rs +++ b/src/test/run-make-fulldeps/issue-19371/foo.rs @@ -72,7 +72,8 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) { driver::spawn_thread_pool(opts, |opts| { let (sess, cstore, codegen_backend) = basic_sess(opts); let control = CompileController::basic(); - let input = Input::Str { name: FileName::Anon, input: code }; + let name = FileName::anon_source_code(&code); + let input = Input::Str { name, input: code }; let _ = compile_input( codegen_backend, &sess, diff --git a/src/test/run-make-fulldeps/issue-25581/test.rs b/src/test/run-make-fulldeps/issue-25581/test.rs index 6717d16cb7c..b084092d727 100644 --- a/src/test/run-make-fulldeps/issue-25581/test.rs +++ b/src/test/run-make-fulldeps/issue-25581/test.rs @@ -8,14 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(libc)] - -extern crate libc; - #[link(name = "test", kind = "static")] extern { - fn slice_len(s: &[u8]) -> libc::size_t; - fn slice_elem(s: &[u8], idx: libc::size_t) -> u8; + fn slice_len(s: &[u8]) -> usize; + fn slice_elem(s: &[u8], idx: usize) -> u8; } fn main() { diff --git a/src/test/run-make-fulldeps/issue-26006/in/time/lib.rs b/src/test/run-make-fulldeps/issue-26006/in/time/lib.rs index b1d07d57337..1427250b9f0 100644 --- a/src/test/run-make-fulldeps/issue-26006/in/time/lib.rs +++ b/src/test/run-make-fulldeps/issue-26006/in/time/lib.rs @@ -7,7 +7,7 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; fn main(){} diff --git a/src/test/run-make-fulldeps/libs-search-path/Makefile b/src/test/run-make-fulldeps/libs-search-path/Makefile new file mode 100644 index 00000000000..db0a069c3f5 --- /dev/null +++ b/src/test/run-make-fulldeps/libs-search-path/Makefile @@ -0,0 +1,16 @@ +-include ../tools.mk + +ifeq ($(if $(IS_WINDOWS),$(IS_MSVC),no),) + +all: empty.rs + cp -r $(shell cygpath -u $(shell $(RUSTC) --print sysroot)) $(TMPDIR)/sysroot + $(RUSTC) --target $(TARGET) --sysroot $(TMPDIR)/sysroot -L$(TMPDIR)/obj -Z print-link-args empty.rs | $(CGREP) 'lib\\crt2.o' + mkdir -p $(TMPDIR)/obj + mv $(TMPDIR)/sysroot/lib/rustlib/$(TARGET)/lib/crt2.o $(TMPDIR)/obj/crt2.o + $(RUSTC) --target $(TARGET) --sysroot $(TMPDIR)/sysroot -L$(TMPDIR)/obj -Z print-link-args empty.rs | $(CGREP) 'obj\\crt2.o' + +else + +all: + +endif diff --git a/src/test/ui/feature-gates/feature-gate-underscore-imports.rs b/src/test/run-make-fulldeps/libs-search-path/empty.rs similarity index 76% rename from src/test/ui/feature-gates/feature-gate-underscore-imports.rs rename to src/test/run-make-fulldeps/libs-search-path/empty.rs index ceb8afe124a..3f07b46791d 100644 --- a/src/test/ui/feature-gates/feature-gate-underscore-imports.rs +++ b/src/test/run-make-fulldeps/libs-search-path/empty.rs @@ -8,7 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern crate std as _; //~ ERROR renaming extern crates with `_` is unstable -use std::vec as _; //~ ERROR renaming imports with `_` is unstable - fn main() {} diff --git a/src/test/run-make-fulldeps/libtest-json/output.json b/src/test/run-make-fulldeps/libtest-json/output.json index d8169ece89b..2b831ea2bdc 100644 --- a/src/test/run-make-fulldeps/libtest-json/output.json +++ b/src/test/run-make-fulldeps/libtest-json/output.json @@ -2,7 +2,7 @@ { "type": "test", "event": "started", "name": "a" } { "type": "test", "name": "a", "event": "ok" } { "type": "test", "event": "started", "name": "b" } -{ "type": "test", "name": "b", "event": "failed", "stdout": "thread 'b' panicked at 'assertion failed: false', f.rs:18:5\nnote: Run with `RUST_BACKTRACE=1` for a backtrace.\n" } +{ "type": "test", "name": "b", "event": "failed", "stdout": "thread 'main' panicked at 'assertion failed: false', f.rs:18:5\nnote: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.\n" } { "type": "test", "event": "started", "name": "c" } { "type": "test", "name": "c", "event": "ok" } { "type": "test", "event": "started", "name": "d" } diff --git a/src/test/run-make-fulldeps/link-path-order/main.rs b/src/test/run-make-fulldeps/link-path-order/main.rs index f3502e8bcd4..4d38dc8fa0f 100644 --- a/src/test/run-make-fulldeps/link-path-order/main.rs +++ b/src/test/run-make-fulldeps/link-path-order/main.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; diff --git a/src/test/run-make-fulldeps/reproducible-build/reproducible-build.rs b/src/test/run-make-fulldeps/reproducible-build/reproducible-build.rs index a040c0f858d..c8c8bb1c850 100644 --- a/src/test/run-make-fulldeps/reproducible-build/reproducible-build.rs +++ b/src/test/run-make-fulldeps/reproducible-build/reproducible-build.rs @@ -9,7 +9,7 @@ // except according to those terms. // This test case makes sure that two identical invocations of the compiler -// (i.e. same code base, same compile-flags, same compiler-versions, etc.) +// (i.e., same code base, same compile-flags, same compiler-versions, etc.) // produce the same output. In the past, symbol names of monomorphized functions // were not deterministic (which we want to avoid). // diff --git a/src/test/run-make-fulldeps/rustdoc-io-error/Makefile b/src/test/run-make-fulldeps/rustdoc-io-error/Makefile new file mode 100644 index 00000000000..2055c9cbf2d --- /dev/null +++ b/src/test/run-make-fulldeps/rustdoc-io-error/Makefile @@ -0,0 +1,25 @@ +-include ../tools.mk + +# This test verifies that rustdoc doesn't ICE when it encounters an IO error +# while generating files. Ideally this would be a rustdoc-ui test, so we could +# verify the error message as well. + +OUTPUT_DIR := "$(TMPDIR)/rustdoc-io-error" + +# Ignore Windows: the test uses `chmod`. +ifndef IS_WINDOWS + +# This test operates by creating a temporary directory and modifying its +# permissions so that it is not writable. We have to take special care to set +# the permissions back to normal so that it's able to be deleted later. +all: + mkdir -p $(OUTPUT_DIR) + chmod u-w $(OUTPUT_DIR) + -$(shell $(RUSTDOC) -o $(OUTPUT_DIR) foo.rs) + chmod u+w $(OUTPUT_DIR) + exit $($(.SHELLSTATUS) -eq 1) + +else +all: + +endif diff --git a/src/test/run-make-fulldeps/rustdoc-io-error/foo.rs b/src/test/run-make-fulldeps/rustdoc-io-error/foo.rs new file mode 100644 index 00000000000..4a835673a59 --- /dev/null +++ b/src/test/run-make-fulldeps/rustdoc-io-error/foo.rs @@ -0,0 +1 @@ +pub struct Foo; diff --git a/src/test/run-make-fulldeps/tools.mk b/src/test/run-make-fulldeps/tools.mk index 3de358fa500..79399281804 100644 --- a/src/test/run-make-fulldeps/tools.mk +++ b/src/test/run-make-fulldeps/tools.mk @@ -76,7 +76,7 @@ endif # Extra flags needed to compile a working executable with the standard library ifdef IS_WINDOWS ifdef IS_MSVC - EXTRACFLAGS := ws2_32.lib userenv.lib shell32.lib advapi32.lib + EXTRACFLAGS := ws2_32.lib userenv.lib advapi32.lib else EXTRACFLAGS := -lws2_32 -luserenv endif 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 8f54f2e2dc3..c9d03294843 100644 --- a/src/test/run-pass-fulldeps/ast_stmt_expr_attr.rs +++ b/src/test/run-pass-fulldeps/ast_stmt_expr_attr.rs @@ -25,7 +25,6 @@ use syntax::parse::new_parser_from_source_str; use syntax::parse::parser::Parser; use syntax::parse::token; use syntax::ptr::P; -use syntax::str::char_at; use syntax::parse::attr::*; use syntax::print::pprust; use std::fmt; @@ -33,7 +32,7 @@ use std::fmt; // Copied out of syntax::util::parser_testing pub fn string_to_parser<'a>(ps: &'a ParseSess, source_str: String) -> Parser<'a> { - new_parser_from_source_str(ps, FileName::Custom("bogofile".to_owned()), source_str) + new_parser_from_source_str(ps, FileName::Custom(source_str.clone()), source_str) } fn with_error_checking_parse<'a, T, F>(s: String, ps: &'a ParseSess, f: F) -> PResult<'a, T> where diff --git a/src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin.rs b/src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin.rs index 449cd29ada3..b8f91386f08 100644 --- a/src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin.rs +++ b/src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin.rs @@ -31,11 +31,11 @@ use rustc_plugin::Registry; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { - reg.register_custom_derive( + reg.register_syntax_extension( Symbol::intern("derive_TotalSum"), MultiDecorator(box expand)); - reg.register_custom_derive( + reg.register_syntax_extension( Symbol::intern("derive_Nothing"), MultiDecorator(box noop)); } diff --git a/src/test/run-pass-fulldeps/auxiliary/issue-40001-plugin.rs b/src/test/run-pass-fulldeps/auxiliary/issue-40001-plugin.rs index f4d3f2c94ca..7a7dd963e0d 100644 --- a/src/test/run-pass-fulldeps/auxiliary/issue-40001-plugin.rs +++ b/src/test/run-pass-fulldeps/auxiliary/issue-40001-plugin.rs @@ -56,9 +56,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingWhitelistedAttrPass { span: source_map::Span, id: ast::NodeId) { - let item = match cx.tcx.hir.get(id) { + let item = match cx.tcx.hir().get(id) { Node::Item(item) => item, - _ => cx.tcx.hir.expect_item(cx.tcx.hir.get_parent(id)), + _ => cx.tcx.hir().expect_item(cx.tcx.hir().get_parent(id)), }; if !attr::contains_name(&item.attrs, "whitelisted_attr") { diff --git a/src/test/run-pass-fulldeps/custom-derive-partial-eq.rs b/src/test/run-pass-fulldeps/custom-derive-partial-eq.rs index 47f5f8397d1..f986efb913c 100644 --- a/src/test/run-pass-fulldeps/custom-derive-partial-eq.rs +++ b/src/test/run-pass-fulldeps/custom-derive-partial-eq.rs @@ -10,11 +10,11 @@ // aux-build:custom_derive_partial_eq.rs // ignore-stage1 -#![feature(plugin, custom_derive)] +#![feature(plugin)] #![plugin(custom_derive_partial_eq)] #![allow(unused)] -#[derive(CustomPartialEq)] // Check that this is not a stability error. +#[derive_CustomPartialEq] // Check that this is not a stability error. enum E { V1, V2 } fn main() {} diff --git a/src/test/run-pass-fulldeps/custom-derive-partial-eq.stderr b/src/test/run-pass-fulldeps/custom-derive-partial-eq.stderr deleted file mode 100644 index ba956e4c132..00000000000 --- a/src/test/run-pass-fulldeps/custom-derive-partial-eq.stderr +++ /dev/null @@ -1,6 +0,0 @@ -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-totalsum-attr.rs b/src/test/run-pass-fulldeps/derive-totalsum-attr.rs index e088f5e4262..374e15d22a1 100644 --- a/src/test/run-pass-fulldeps/derive-totalsum-attr.rs +++ b/src/test/run-pass-fulldeps/derive-totalsum-attr.rs @@ -11,7 +11,7 @@ // aux-build:custom_derive_plugin_attr.rs // ignore-stage1 -#![feature(plugin, custom_derive, rustc_attrs)] +#![feature(plugin, rustc_attrs)] #![plugin(custom_derive_plugin_attr)] trait TotalSum { diff --git a/src/test/run-pass-fulldeps/derive-totalsum.rs b/src/test/run-pass-fulldeps/derive-totalsum.rs index 848b2425e44..86f14ca4463 100644 --- a/src/test/run-pass-fulldeps/derive-totalsum.rs +++ b/src/test/run-pass-fulldeps/derive-totalsum.rs @@ -11,7 +11,7 @@ // aux-build:custom_derive_plugin.rs // ignore-stage1 -#![feature(plugin, custom_derive)] +#![feature(plugin)] #![plugin(custom_derive_plugin)] trait TotalSum { @@ -32,14 +32,14 @@ impl TotalSum for Seven { } } -#[derive(TotalSum)] +#[derive_TotalSum] struct Foo { seven: Seven, bar: Bar, baz: isize, } -#[derive(TotalSum)] +#[derive_TotalSum] struct Bar { quux: isize, bleh: isize, diff --git a/src/test/run-pass-fulldeps/issue-40663.rs b/src/test/run-pass-fulldeps/issue-40663.rs index 8633e906082..a33e9cc0543 100644 --- a/src/test/run-pass-fulldeps/issue-40663.rs +++ b/src/test/run-pass-fulldeps/issue-40663.rs @@ -12,10 +12,12 @@ // aux-build:custom_derive_plugin.rs // ignore-stage1 -#![feature(plugin, custom_derive)] +#![feature(plugin)] #![plugin(custom_derive_plugin)] -#[derive(Nothing, Nothing, Nothing)] +#[derive_Nothing] +#[derive_Nothing] +#[derive_Nothing] struct S; fn main() {} diff --git a/src/test/run-pass-fulldeps/newtype_index.rs b/src/test/run-pass-fulldeps/newtype_index.rs index 3cd622a33b1..0fd7ccd55fb 100644 --- a/src/test/run-pass-fulldeps/newtype_index.rs +++ b/src/test/run-pass-fulldeps/newtype_index.rs @@ -1,4 +1,4 @@ -#![feature(rustc_attrs, rustc_private, step_trait)] +#![feature(rustc_attrs, rustc_private, step_trait, min_const_unsafe_fn)] #[macro_use] extern crate rustc_data_structures; extern crate rustc_serialize; diff --git a/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs b/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs index e944ef2b620..854063a2984 100644 --- a/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs +++ b/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs @@ -44,9 +44,11 @@ use syntax::ptr::P; fn parse_expr(ps: &ParseSess, src: &str) -> P { + let src_as_string = src.to_string(); + let mut p = parse::new_parser_from_source_str(ps, - FileName::Custom("expr".to_owned()), - src.to_owned()); + FileName::Custom(src_as_string.clone()), + src_as_string); p.parse_expr().unwrap() } diff --git a/src/test/run-pass-valgrind/osx-frameworks.rs b/src/test/run-pass-valgrind/osx-frameworks.rs index 468a20db6f7..afa9374ff67 100644 --- a/src/test/run-pass-valgrind/osx-frameworks.rs +++ b/src/test/run-pass-valgrind/osx-frameworks.rs @@ -11,7 +11,7 @@ // no-prefer-dynamic // pretty-expanded FIXME #23616 -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; diff --git a/src/test/run-pass/abort-on-c-abi.rs b/src/test/run-pass/abort-on-c-abi.rs index 17b2ee39c88..12b5b786766 100644 --- a/src/test/run-pass/abort-on-c-abi.rs +++ b/src/test/run-pass/abort-on-c-abi.rs @@ -15,14 +15,11 @@ // ignore-cloudabi no env and process // ignore-emscripten no processes -#![feature(unwind_attributes)] - use std::{env, panic}; use std::io::prelude::*; use std::io; use std::process::{Command, Stdio}; -#[unwind(aborts)] extern "C" fn panic_in_ffi() { panic!("Test"); } diff --git a/src/test/run-pass/anon-extern-mod.rs b/src/test/run-pass/anon-extern-mod.rs index 16ca7bce95b..daa2bd62882 100644 --- a/src/test/run-pass/anon-extern-mod.rs +++ b/src/test/run-pass/anon-extern-mod.rs @@ -11,7 +11,7 @@ // pretty-expanded FIXME #23616 // ignore-wasm32-bare no libc to test ffi with -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; diff --git a/src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs b/src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs index 80a7ce96911..6ec70bb8c09 100644 --- a/src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs +++ b/src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(arbitrary_self_types)] #![feature(pin)] #![feature(rustc_attrs)] @@ -23,6 +22,7 @@ trait Trait { fn by_arc(self: Arc) -> i64; fn by_pin_mut(self: Pin<&mut Self>) -> i64; fn by_pin_box(self: Pin>) -> i64; + fn by_pin_pin_pin_ref(self: Pin>>) -> i64; } impl Trait for i64 { @@ -38,6 +38,9 @@ impl Trait for i64 { fn by_pin_box(self: Pin>) -> i64 { *self } + fn by_pin_pin_pin_ref(self: Pin>>) -> i64 { + *self + } } fn main() { @@ -53,4 +56,8 @@ fn main() { let pin_box = Into::>>::into(Box::new(4i64)) as Pin>; assert_eq!(4, pin_box.by_pin_box()); + + let value = 5i64; + let pin_pin_pin_ref = Pin::new(Pin::new(Pin::new(&value))) as Pin>>; + assert_eq!(5, pin_pin_pin_ref.by_pin_pin_pin_ref()); } diff --git a/src/test/run-pass/array-slice-vec/vec-macro-no-std.rs b/src/test/run-pass/array-slice-vec/vec-macro-no-std.rs index 509167413b6..7a90a022e0a 100644 --- a/src/test/run-pass/array-slice-vec/vec-macro-no-std.rs +++ b/src/test/run-pass/array-slice-vec/vec-macro-no-std.rs @@ -12,7 +12,7 @@ // ignore-emscripten no no_std executables -#![feature(lang_items, start, libc, alloc)] +#![feature(lang_items, start, rustc_private, alloc)] #![no_std] extern crate std as other; diff --git a/src/test/run-pass/auxiliary/anon-extern-mod-cross-crate-1.rs b/src/test/run-pass/auxiliary/anon-extern-mod-cross-crate-1.rs index 741ce351da3..6b464c59f2a 100644 --- a/src/test/run-pass/auxiliary/anon-extern-mod-cross-crate-1.rs +++ b/src/test/run-pass/auxiliary/anon-extern-mod-cross-crate-1.rs @@ -9,7 +9,7 @@ // except according to those terms. #![crate_name="anonexternmod"] -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; diff --git a/src/test/run-pass/auxiliary/check_static_recursion_foreign_helper.rs b/src/test/run-pass/auxiliary/check_static_recursion_foreign_helper.rs index cd36a8eedb4..4d1acf31be3 100644 --- a/src/test/run-pass/auxiliary/check_static_recursion_foreign_helper.rs +++ b/src/test/run-pass/auxiliary/check_static_recursion_foreign_helper.rs @@ -10,7 +10,7 @@ // Helper definition for test/run-pass/check-static-recursion-foreign.rs. -#![feature(libc)] +#![feature(rustc_private)] #![crate_name = "check_static_recursion_foreign_helper"] #![crate_type = "lib"] diff --git a/src/test/run-pass/auxiliary/foreign_lib.rs b/src/test/run-pass/auxiliary/foreign_lib.rs index cef36274c62..465feb8eaf7 100644 --- a/src/test/run-pass/auxiliary/foreign_lib.rs +++ b/src/test/run-pass/auxiliary/foreign_lib.rs @@ -10,7 +10,7 @@ #![crate_name="foreign_lib"] -#![feature(libc)] +#![feature(rustc_private)] pub mod rustrt { extern crate libc; diff --git a/src/test/run-pass/binding/empty-types-in-patterns.rs b/src/test/run-pass/binding/empty-types-in-patterns.rs index 7fb7eec1256..f595bb0da9a 100644 --- a/src/test/run-pass/binding/empty-types-in-patterns.rs +++ b/src/test/run-pass/binding/empty-types-in-patterns.rs @@ -14,6 +14,7 @@ #![feature(slice_patterns)] #![allow(unreachable_patterns)] #![allow(unreachable_code)] +#![allow(unused_variables)] #[allow(dead_code)] fn foo(z: !) { diff --git a/src/test/run-pass/c-stack-as-value.rs b/src/test/run-pass/c-stack-as-value.rs index df4989d89ab..1f29a5201bd 100644 --- a/src/test/run-pass/c-stack-as-value.rs +++ b/src/test/run-pass/c-stack-as-value.rs @@ -11,7 +11,7 @@ // pretty-expanded FIXME #23616 // ignore-wasm32-bare no libc to test ffi with -#![feature(libc)] +#![feature(rustc_private)] mod rustrt { extern crate libc; diff --git a/src/test/run-pass/c-stack-returning-int64.rs b/src/test/run-pass/c-stack-returning-int64.rs index 56a0437146b..7dd3b9a7a5b 100644 --- a/src/test/run-pass/c-stack-returning-int64.rs +++ b/src/test/run-pass/c-stack-returning-int64.rs @@ -10,7 +10,7 @@ // ignore-wasm32-bare no libc to test with -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; diff --git a/src/test/run-pass/check-static-recursion-foreign.rs b/src/test/run-pass/check-static-recursion-foreign.rs index a95870c2b27..15f509a1753 100644 --- a/src/test/run-pass/check-static-recursion-foreign.rs +++ b/src/test/run-pass/check-static-recursion-foreign.rs @@ -16,7 +16,7 @@ // pretty-expanded FIXME #23616 -#![feature(custom_attribute, libc)] +#![feature(custom_attribute, rustc_private)] extern crate check_static_recursion_foreign_helper; extern crate libc; diff --git a/src/test/run-pass/coerce/coerce-unify.rs b/src/test/run-pass/coerce/coerce-unify.rs index 575d672e092..bfcdf5b143f 100644 --- a/src/test/run-pass/coerce/coerce-unify.rs +++ b/src/test/run-pass/coerce/coerce-unify.rs @@ -47,7 +47,7 @@ macro_rules! check3 { check2!($b, $c); check2!($a, $c); - // Check the remaining cases, i.e. permutations of ($a, $b, $c). + // Check the remaining cases, i.e., permutations of ($a, $b, $c). check!($a, $b, $c); check!($a, $c, $b); check!($b, $a, $c); diff --git a/src/test/run-pass/coerce/coerce-unsize-subtype.rs b/src/test/run-pass/coerce/coerce-unsize-subtype.rs index 068b010da1e..088d10f8d63 100644 --- a/src/test/run-pass/coerce/coerce-unsize-subtype.rs +++ b/src/test/run-pass/coerce/coerce-unsize-subtype.rs @@ -32,7 +32,7 @@ fn long_to_short_rc<'a, T>(xs: Rc<[&'static T; 1]>) -> Rc<[&'a T]> { } // LUB-coercion (if-else/match/array) coerces `xs: &'b [&'static T: N]` -// to a subtype of the LUB of `xs` and `ys` (i.e. `&'b [&'a T]`), +// to a subtype of the LUB of `xs` and `ys` (i.e., `&'b [&'a T]`), // regardless of the order they appear (in if-else/match/array). fn long_and_short_lub1<'a, 'b, T>(xs: &'b [&'static T; 1], ys: &'b [&'a T]) { let _order1 = [xs, ys]; @@ -40,7 +40,7 @@ fn long_and_short_lub1<'a, 'b, T>(xs: &'b [&'static T; 1], ys: &'b [&'a T]) { } // LUB-coercion should also have the exact same effect when `&'b [&'a T; N]` -// needs to be coerced, i.e. the resulting type is not &'b [&'static T], but +// needs to be coerced, i.e., the resulting type is not &'b [&'static T], but // rather the `&'b [&'a T]` LUB. fn long_and_short_lub2<'a, 'b, T>(xs: &'b [&'static T], ys: &'b [&'a T; 1]) { let _order1 = [xs, ys]; diff --git a/src/test/run-pass/command-before-exec.rs b/src/test/run-pass/command-before-exec.rs index 5d8bc31c2a3..b78fa849d0d 100644 --- a/src/test/run-pass/command-before-exec.rs +++ b/src/test/run-pass/command-before-exec.rs @@ -13,7 +13,7 @@ // ignore-cloudabi no processes // ignore-emscripten no processes -#![feature(process_exec, libc)] +#![feature(process_exec, rustc_private)] extern crate libc; diff --git a/src/test/run-pass/consts/auxiliary/anon-extern-mod-cross-crate-1.rs b/src/test/run-pass/consts/auxiliary/anon-extern-mod-cross-crate-1.rs index 741ce351da3..6b464c59f2a 100644 --- a/src/test/run-pass/consts/auxiliary/anon-extern-mod-cross-crate-1.rs +++ b/src/test/run-pass/consts/auxiliary/anon-extern-mod-cross-crate-1.rs @@ -9,7 +9,7 @@ // except according to those terms. #![crate_name="anonexternmod"] -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; diff --git a/src/test/run-pass/core-run-destroy.rs b/src/test/run-pass/core-run-destroy.rs index aaf017c0ad3..902332656a8 100644 --- a/src/test/run-pass/core-run-destroy.rs +++ b/src/test/run-pass/core-run-destroy.rs @@ -16,11 +16,11 @@ // ignore-cloudabi no processes // ignore-emscripten no processes -// NB: These tests kill child processes. Valgrind sees these children as leaking +// N.B., these tests kill child processes. Valgrind sees these children as leaking // memory, which makes for some *confusing* logs. That's why these are here // instead of in std. -#![feature(libc, duration)] +#![feature(rustc_private, duration)] extern crate libc; diff --git a/src/test/run-pass/cross-crate/auxiliary/anon-extern-mod-cross-crate-1.rs b/src/test/run-pass/cross-crate/auxiliary/anon-extern-mod-cross-crate-1.rs index 741ce351da3..6b464c59f2a 100644 --- a/src/test/run-pass/cross-crate/auxiliary/anon-extern-mod-cross-crate-1.rs +++ b/src/test/run-pass/cross-crate/auxiliary/anon-extern-mod-cross-crate-1.rs @@ -9,7 +9,7 @@ // except according to those terms. #![crate_name="anonexternmod"] -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; diff --git a/src/test/run-pass/ctfe/references.rs b/src/test/run-pass/ctfe/references.rs index 946ed246bb0..421f3543830 100644 --- a/src/test/run-pass/ctfe/references.rs +++ b/src/test/run-pass/ctfe/references.rs @@ -28,6 +28,7 @@ fn main() { _ => panic!("c"), } + #[allow(unreachable_patterns)] match &43 { &42 => panic!(), BOO => panic!(), diff --git a/src/test/run-pass/drop/dropck-eyepatch.rs b/src/test/run-pass/drop/dropck-eyepatch.rs index fb9af09a7ce..97820ac7ea8 100644 --- a/src/test/run-pass/drop/dropck-eyepatch.rs +++ b/src/test/run-pass/drop/dropck-eyepatch.rs @@ -32,7 +32,7 @@ // - D means "I implement Drop" // // - P means "I implement Drop but guarantee my (first) parameter is -// pure, i.e. not accessed from the destructor"; no other parameters +// pure, i.e., not accessed from the destructor"; no other parameters // are pure. // // - S means "I do not implement Drop" diff --git a/src/test/run-pass/drop/dropck_legal_cycles.rs b/src/test/run-pass/drop/dropck_legal_cycles.rs index 2c88cfd5c8f..89d70da32cf 100644 --- a/src/test/run-pass/drop/dropck_legal_cycles.rs +++ b/src/test/run-pass/drop/dropck_legal_cycles.rs @@ -108,7 +108,7 @@ // of all-zeroes. // // 6. assert that the context confirms that it actually saw a cycle (since a traversal -// might have terminated, e.g. on a tree structure that contained no cycles). +// might have terminated, e.g., on a tree structure that contained no cycles). use std::cell::{Cell, RefCell}; use std::cmp::Ordering; diff --git a/src/test/run-pass/env-funky-keys.rs b/src/test/run-pass/env-funky-keys.rs index 12e1cbe97d8..7e7899cf151 100644 --- a/src/test/run-pass/env-funky-keys.rs +++ b/src/test/run-pass/env-funky-keys.rs @@ -16,7 +16,7 @@ // ignore-emscripten no execve // no-prefer-dynamic -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; diff --git a/src/test/run-pass/env-null-vars.rs b/src/test/run-pass/env-null-vars.rs index 9a461991c1e..cdbecf120c3 100644 --- a/src/test/run-pass/env-null-vars.rs +++ b/src/test/run-pass/env-null-vars.rs @@ -15,7 +15,7 @@ // issue-53200 -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; use std::env; diff --git a/src/test/run-pass/extern/auxiliary/extern-crosscrate-source.rs b/src/test/run-pass/extern/auxiliary/extern-crosscrate-source.rs index 150dffeea88..d20d9dbac3d 100644 --- a/src/test/run-pass/extern/auxiliary/extern-crosscrate-source.rs +++ b/src/test/run-pass/extern/auxiliary/extern-crosscrate-source.rs @@ -10,7 +10,7 @@ #![crate_name="externcallback"] #![crate_type = "lib"] -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; diff --git a/src/test/run-pass/extern/extern-call-deep.rs b/src/test/run-pass/extern/extern-call-deep.rs index 6e8d94becbd..12df0f32134 100644 --- a/src/test/run-pass/extern/extern-call-deep.rs +++ b/src/test/run-pass/extern/extern-call-deep.rs @@ -10,8 +10,9 @@ // run-pass // ignore-wasm32-bare no libc to test ffi with +// ignore-emscripten blows the JS stack -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; diff --git a/src/test/run-pass/extern/extern-call-deep2.rs b/src/test/run-pass/extern/extern-call-deep2.rs index 28157c5a8d5..8cb04771cb9 100644 --- a/src/test/run-pass/extern/extern-call-deep2.rs +++ b/src/test/run-pass/extern/extern-call-deep2.rs @@ -12,7 +12,7 @@ #![allow(unused_must_use)] // ignore-emscripten no threads support -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; use std::thread; diff --git a/src/test/run-pass/extern/extern-call-indirect.rs b/src/test/run-pass/extern/extern-call-indirect.rs index 1badb10364e..d20721f2c91 100644 --- a/src/test/run-pass/extern/extern-call-indirect.rs +++ b/src/test/run-pass/extern/extern-call-indirect.rs @@ -11,7 +11,7 @@ // run-pass // ignore-wasm32-bare no libc to test ffi with -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; diff --git a/src/test/run-pass/extern/extern-call-scrub.rs b/src/test/run-pass/extern/extern-call-scrub.rs index ea18069fa32..5e158c2dfc9 100644 --- a/src/test/run-pass/extern/extern-call-scrub.rs +++ b/src/test/run-pass/extern/extern-call-scrub.rs @@ -16,7 +16,7 @@ // ignore-emscripten no threads support -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; use std::thread; diff --git a/src/test/run-pass/extern/extern-crosscrate.rs b/src/test/run-pass/extern/extern-crosscrate.rs index c6fccbe003c..b99e27af920 100644 --- a/src/test/run-pass/extern/extern-crosscrate.rs +++ b/src/test/run-pass/extern/extern-crosscrate.rs @@ -12,7 +12,7 @@ // aux-build:extern-crosscrate-source.rs // ignore-wasm32-bare no libc to test ffi with -#![feature(libc)] +#![feature(rustc_private)] extern crate externcallback; extern crate libc; diff --git a/src/test/run-pass/fds-are-cloexec.rs b/src/test/run-pass/fds-are-cloexec.rs index a5ae0ae9f31..33e64d832fc 100644 --- a/src/test/run-pass/fds-are-cloexec.rs +++ b/src/test/run-pass/fds-are-cloexec.rs @@ -14,7 +14,7 @@ // ignore-emscripten no processes // ignore-haiku -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; diff --git a/src/test/run-pass/for-loop-while/loop-no-reinit-needed-post-bot.rs b/src/test/run-pass/for-loop-while/loop-no-reinit-needed-post-bot.rs index 95bb8e8aa64..7bc4dccdcce 100644 --- a/src/test/run-pass/for-loop-while/loop-no-reinit-needed-post-bot.rs +++ b/src/test/run-pass/for-loop-while/loop-no-reinit-needed-post-bot.rs @@ -15,7 +15,7 @@ struct S; // Ensure S is moved, not copied, on assignment. impl Drop for S { fn drop(&mut self) { } } -// user-defined function "returning" bottom (i.e. no return at all). +// user-defined function "returning" bottom (i.e., no return at all). fn my_panic() -> ! { loop {} } pub fn step(f: bool) { diff --git a/src/test/run-pass/foreign/auxiliary/foreign_lib.rs b/src/test/run-pass/foreign/auxiliary/foreign_lib.rs index cef36274c62..465feb8eaf7 100644 --- a/src/test/run-pass/foreign/auxiliary/foreign_lib.rs +++ b/src/test/run-pass/foreign/auxiliary/foreign_lib.rs @@ -10,7 +10,7 @@ #![crate_name="foreign_lib"] -#![feature(libc)] +#![feature(rustc_private)] pub mod rustrt { extern crate libc; diff --git a/src/test/run-pass/foreign/foreign-call-no-runtime.rs b/src/test/run-pass/foreign/foreign-call-no-runtime.rs index 4837f78ce3b..e35ec882132 100644 --- a/src/test/run-pass/foreign/foreign-call-no-runtime.rs +++ b/src/test/run-pass/foreign/foreign-call-no-runtime.rs @@ -11,7 +11,7 @@ // run-pass // ignore-emscripten no threads support -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; diff --git a/src/test/run-pass/foreign/foreign-fn-linkname.rs b/src/test/run-pass/foreign/foreign-fn-linkname.rs index 75876607603..8fe90b7d498 100644 --- a/src/test/run-pass/foreign/foreign-fn-linkname.rs +++ b/src/test/run-pass/foreign/foreign-fn-linkname.rs @@ -11,7 +11,7 @@ // run-pass // ignore-wasm32-bare no libc to test ffi with -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; use std::ffi::CString; diff --git a/src/test/run-pass/foreign/foreign-no-abi.rs b/src/test/run-pass/foreign/foreign-no-abi.rs index 1d35f08a11f..49ddd09beee 100644 --- a/src/test/run-pass/foreign/foreign-no-abi.rs +++ b/src/test/run-pass/foreign/foreign-no-abi.rs @@ -14,7 +14,7 @@ // ignore-wasm32-bare no libc to test ffi with // pretty-expanded FIXME #23616 -#![feature(libc)] +#![feature(rustc_private)] mod rustrt { extern crate libc; diff --git a/src/test/run-pass/foreign/foreign2.rs b/src/test/run-pass/foreign/foreign2.rs index bd6c8e6b53d..f8942bc1712 100644 --- a/src/test/run-pass/foreign/foreign2.rs +++ b/src/test/run-pass/foreign/foreign2.rs @@ -13,7 +13,7 @@ // ignore-wasm32-bare no libc to test ffi with // pretty-expanded FIXME #23616 -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; diff --git a/src/test/run-pass/impl-trait/example-calendar.rs b/src/test/run-pass/impl-trait/example-calendar.rs index e6dd421f48f..d622fd6171a 100644 --- a/src/test/run-pass/impl-trait/example-calendar.rs +++ b/src/test/run-pass/impl-trait/example-calendar.rs @@ -86,7 +86,7 @@ impl NaiveDate { let weeks_in_year = self.last_week_number(); // Work out the final result. - // If the week is -1 or >= weeks_in_year, we will need to adjust the year. + // If the week is `-1` or `>= weeks_in_year`, we will need to adjust the year. let year = self.year(); let wd = self.weekday(); @@ -234,7 +234,7 @@ impl Weekday { } } -/// GroupBy implementation. +/// `GroupBy` implementation. struct GroupBy { it: std::iter::Peekable, f: F, @@ -319,7 +319,7 @@ trait IteratorExt: Iterator + Sized { s } - // HACK(eddyb) Only needed because `impl Trait` can't be + // HACK(eddyb): only needed because `impl Trait` can't be // used with trait methods: `.foo()` becomes `.__(foo)`. fn __(self, f: F) -> R where F: FnOnce(Self) -> R { @@ -329,9 +329,7 @@ trait IteratorExt: Iterator + Sized { impl IteratorExt for It where It: Iterator {} -/// -/// Generates an iterator that yields exactly n spaces. -/// +/// Generates an iterator that yields exactly `n` spaces. fn spaces(n: usize) -> std::iter::Take> { std::iter::repeat(' ').take(n) } @@ -341,9 +339,7 @@ fn test_spaces() { assert_eq!(spaces(10).collect::(), " ") } -/// /// Returns an iterator of dates in a given year. -/// fn dates_in_year(year: i32) -> impl Iterator+Clone { InGroup { it: NaiveDate::from_ymd(year, 1, 1).., @@ -357,10 +353,10 @@ fn test_dates_in_year() { let mut dates = dates_in_year(2013); assert_eq!(dates.next(), Some(NaiveDate::from_ymd(2013, 1, 1))); - // Check increment + // Check increment. assert_eq!(dates.next(), Some(NaiveDate::from_ymd(2013, 1, 2))); - // Check monthly rollover + // Check monthly roll-over. for _ in 3..31 { assert!(dates.next() != None); } @@ -370,7 +366,7 @@ fn test_dates_in_year() { } { - // Check length of year + // Check length of year. let mut dates = dates_in_year(2013); for _ in 0..365 { assert!(dates.next() != None); @@ -379,7 +375,7 @@ fn test_dates_in_year() { } { - // Check length of leap year + // Check length of leap year. let mut dates = dates_in_year(1984); for _ in 0..366 { assert!(dates.next() != None); @@ -388,10 +384,8 @@ fn test_dates_in_year() { } } -/// /// Convenience trait for verifying that a given type iterates over /// `NaiveDate`s. -/// trait DateIterator: Iterator + Clone {} impl DateIterator for It where It: Iterator + Clone {} @@ -427,11 +421,9 @@ fn test_group_by() { } } -/// /// Groups an iterator of dates by month. -/// fn by_month(it: impl Iterator + Clone) - -> impl Iterator + Clone)> + Clone + -> impl Iterator + Clone)> + Clone { it.group_by(|d| d.month()) } @@ -444,9 +436,7 @@ fn test_by_month() { assert!(months.next().is_none()); } -/// /// Groups an iterator of dates by week. -/// fn by_week(it: impl DateIterator) -> impl Iterator + Clone { @@ -518,9 +508,7 @@ const COLS_PER_DAY: u32 = 3; /// The number of columns per week in the formatted output. const COLS_PER_WEEK: u32 = 7 * COLS_PER_DAY; -/// /// Formats an iterator of weeks into an iterator of strings. -/// fn format_weeks(it: impl Iterator) -> impl Iterator { it.map(|week| { let mut buf = String::with_capacity((COLS_PER_DAY * COLS_PER_WEEK + 2) as usize); @@ -541,7 +529,7 @@ fn format_weeks(it: impl Iterator) -> impl Iterator String { const MONTH_NAMES: &'static [&'static str] = &[ "January", "February", "March", "April", "May", "June", @@ -584,7 +570,7 @@ fn month_title(month: u32) -> String { let before = (COLS_PER_WEEK as usize - name.len()) / 2; let after = COLS_PER_WEEK as usize - name.len() - before; - // NOTE: Being slightly more verbose to avoid extra allocations. + // Note: being slightly more verbose to avoid extra allocations. let mut result = String::with_capacity(COLS_PER_WEEK as usize); result.extend(spaces(before)); result.push_str(name); @@ -596,9 +582,7 @@ fn test_month_title() { assert_eq!(month_title(1).len(), COLS_PER_WEEK as usize); } -/// /// Formats a month. -/// fn format_month(it: impl DateIterator) -> impl Iterator { let mut month_days = it.peekable(); let title = month_title(month_days.peek().unwrap().month()); @@ -627,22 +611,17 @@ fn test_format_month() { ); } - -/// /// Formats an iterator of months. -/// fn format_months(it: impl Iterator) -> impl Iterator> { it.map(format_month) } -/// /// Takes an iterator of iterators of strings; the sub-iterators are consumed /// in lock-step, with their elements joined together. -/// trait PasteBlocks: Iterator + Sized -where Self::Item: Iterator { +where Self::Item: Iterator { fn paste_blocks(self, sep_width: usize) -> PasteBlocksIter { PasteBlocksIter { iters: self.collect(), @@ -721,9 +700,7 @@ fn test_paste_blocks() { ); } -/// /// Produces an iterator that yields `n` elements at a time. -/// trait Chunks: Iterator + Sized { fn chunks(self, n: usize) -> ChunksIter { assert!(n > 0); @@ -742,7 +719,7 @@ where It: Iterator { n: usize, } -// NOTE: `chunks` in Rust is more-or-less impossible without overhead of some kind. +// Note: `chunks` in Rust is more-or-less impossible without overhead of some kind. // Aliasing rules mean you need to add dynamic borrow checking, and the design of // `Iterator` means that you need to have the iterator's state kept in an allocation // that is jointly owned by the iterator itself and the sub-iterator. @@ -753,10 +730,7 @@ where It: Iterator { type Item = Vec; fn next(&mut self) -> Option> { - let first = match self.it.next() { - Some(e) => e, - None => return None - }; + let first = self.it.next()?; let mut result = Vec::with_capacity(self.n); result.push(first); @@ -772,9 +746,7 @@ fn test_chunks() { assert_eq!(&*c, &[vec![1, 2, 3], vec![4, 5, 6], vec![7]]); } -/// /// Formats a year. -/// fn format_year(year: i32, months_per_row: usize) -> String { const COL_SPACING: usize = 1; @@ -787,17 +759,17 @@ fn format_year(year: i32, months_per_row: usize) -> String { // Group the months into horizontal rows. .chunks(months_per_row) - // Format each row + // Format each row... .map(|r| r.into_iter() - // By formatting each month + // ... by formatting each month ... .__(format_months) - // Horizontally pasting each respective month's lines together. + // ... and horizontally pasting each respective month's lines together. .paste_blocks(COL_SPACING) .join("\n") ) - // Insert a blank line between each row + // Insert a blank line between each row. .join("\n\n") } diff --git a/src/test/run-pass/invalid_const_promotion.rs b/src/test/run-pass/invalid_const_promotion.rs index 0f354e1aad6..3b8a265dd70 100644 --- a/src/test/run-pass/invalid_const_promotion.rs +++ b/src/test/run-pass/invalid_const_promotion.rs @@ -15,7 +15,7 @@ // compile-flags: -C debug_assertions=yes #![stable(feature = "rustc", since = "1.0.0")] -#![feature(const_fn, libc, staged_api, rustc_attrs)] +#![feature(const_fn, rustc_private, staged_api, rustc_attrs)] #![allow(const_err)] extern crate libc; diff --git a/src/test/run-pass/issue-53843.rs b/src/test/run-pass/issue-53843.rs new file mode 100644 index 00000000000..4b15ecb3e54 --- /dev/null +++ b/src/test/run-pass/issue-53843.rs @@ -0,0 +1,34 @@ +// 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 std::ops::Deref; + +pub struct Pin

(P); + +impl Deref for Pin

+where + P: Deref, +{ + type Target = T; + + fn deref(&self) -> &T { + &*self.0 + } +} + +impl

Pin

{ + fn poll(self) {} +} + +fn main() { + let mut unit = (); + let pin = Pin(&mut unit); + pin.poll(); +} diff --git a/src/test/run-pass/issue-55380.rs b/src/test/run-pass/issue-55380.rs new file mode 100644 index 00000000000..29392fba8b4 --- /dev/null +++ b/src/test/run-pass/issue-55380.rs @@ -0,0 +1,38 @@ +// 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 + +#![feature(specialization)] + +pub trait Foo { + fn abc() -> u32; + fn def() -> u32; +} + +pub trait Marker {} + +impl Marker for () {} + +impl Foo for T { + default fn abc() -> u32 { 16 } + default fn def() -> u32 { 42 } +} + +impl Foo for T { + fn def() -> u32 { + Self::abc() + } +} + +fn main() { + assert_eq!(<()>::def(), 16); + assert_eq!(::def(), 42); +} diff --git a/src/test/run-pass/issue-56237.rs b/src/test/run-pass/issue-56237.rs new file mode 100644 index 00000000000..87e10e83612 --- /dev/null +++ b/src/test/run-pass/issue-56237.rs @@ -0,0 +1,11 @@ +use std::ops::Deref; + +fn foo

(_value:

::Target) +where + P: Deref, +

::Target: Sized, +{} + +fn main() { + foo::>(2); +} diff --git a/src/test/run-pass/issues/issue-13259-windows-tcb-trash.rs b/src/test/run-pass/issues/issue-13259-windows-tcb-trash.rs index de18e09532b..9c983eab7d8 100644 --- a/src/test/run-pass/issues/issue-13259-windows-tcb-trash.rs +++ b/src/test/run-pass/issues/issue-13259-windows-tcb-trash.rs @@ -9,7 +9,7 @@ // except according to those terms. // run-pass -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; diff --git a/src/test/run-pass/issues/issue-18804/main.rs b/src/test/run-pass/issues/issue-18804/main.rs index 2abcd4b7ba9..4b32cc12dfd 100644 --- a/src/test/run-pass/issues/issue-18804/main.rs +++ b/src/test/run-pass/issues/issue-18804/main.rs @@ -14,9 +14,14 @@ // ignore-asmjs no weak symbol support // ignore-emscripten no weak symbol support +// ignore-windows no extern_weak linkage +// ignore-macos no extern_weak linkage // aux-build:lib.rs +// rust-lang/rust#56772: nikic says we need this to be proper test. +// compile-flags: -C no-prepopulate-passes -C passes=name-anon-globals + extern crate lib; fn main() { diff --git a/src/test/run-pass/issues/issue-2214.rs b/src/test/run-pass/issues/issue-2214.rs index 8329847d3c5..f3795c216c8 100644 --- a/src/test/run-pass/issues/issue-2214.rs +++ b/src/test/run-pass/issues/issue-2214.rs @@ -11,7 +11,7 @@ // run-pass // ignore-wasm32-bare no libc to test ffi with -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; diff --git a/src/test/run-pass/issues/issue-23808.rs b/src/test/run-pass/issues/issue-23808.rs index 133da00ffaa..59c3e395cf9 100644 --- a/src/test/run-pass/issues/issue-23808.rs +++ b/src/test/run-pass/issues/issue-23808.rs @@ -9,6 +9,7 @@ // except according to those terms. // run-pass + #![deny(dead_code)] // use different types / traits to test all combinations diff --git a/src/test/run-pass/issues/issue-24805-dropck-itemless.rs b/src/test/run-pass/issues/issue-24805-dropck-itemless.rs index 1d1bd21075b..b9d2523cd79 100644 --- a/src/test/run-pass/issues/issue-24805-dropck-itemless.rs +++ b/src/test/run-pass/issues/issue-24805-dropck-itemless.rs @@ -23,7 +23,7 @@ trait UserDefined { } impl UserDefined for i32 { } impl<'a, T> UserDefined for &'a T { } -// e.g. `impl_drop!(Send, D_Send)` expands to: +// e.g., `impl_drop!(Send, D_Send)` expands to: // ```rust // struct D_Send(T); // impl Drop for D_Send { fn drop(&mut self) { } } diff --git a/src/test/run-pass/issues/issue-26996.rs b/src/test/run-pass/issues/issue-26996.rs index 83445c6657e..61ac665caf6 100644 --- a/src/test/run-pass/issues/issue-26996.rs +++ b/src/test/run-pass/issues/issue-26996.rs @@ -10,7 +10,7 @@ // run-pass -// This test is bogus (i.e. should be compile-fail) during the period +// This test is bogus (i.e., should be compile-fail) during the period // where #54986 is implemented and #54987 is *not* implemented. For // now: just ignore it under nll // diff --git a/src/test/run-pass/issues/issue-27021.rs b/src/test/run-pass/issues/issue-27021.rs index dbad8556aeb..21e4568a520 100644 --- a/src/test/run-pass/issues/issue-27021.rs +++ b/src/test/run-pass/issues/issue-27021.rs @@ -10,7 +10,7 @@ // run-pass -// This test is bogus (i.e. should be compile-fail) during the period +// This test is bogus (i.e., should be compile-fail) during the period // where #54986 is implemented and #54987 is *not* implemented. For // now: just ignore it under nll // diff --git a/src/test/run-pass/issues/issue-30490.rs b/src/test/run-pass/issues/issue-30490.rs index 500999cc1cf..47f60fb93d7 100644 --- a/src/test/run-pass/issues/issue-30490.rs +++ b/src/test/run-pass/issues/issue-30490.rs @@ -18,7 +18,7 @@ // where the descriptors to inherit were already stdio descriptors. // This test checks to avoid that regression. -#![cfg_attr(unix, feature(libc))] +#![cfg_attr(unix, feature(rustc_private))] #![cfg_attr(windows, allow(unused_imports))] #[cfg(unix)] diff --git a/src/test/run-pass/issues/issue-33140.rs b/src/test/run-pass/issues/issue-33140.rs new file mode 100644 index 00000000000..08c69452f69 --- /dev/null +++ b/src/test/run-pass/issues/issue-33140.rs @@ -0,0 +1,57 @@ +// 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. + +#![allow(order_dependent_trait_objects)] + +trait Trait { + fn xyz() -> bool; +} + +impl Trait for dyn Send + Sync { + fn xyz() -> bool { false } +} + +impl Trait for dyn Sync + Send { + fn xyz() -> bool { true } +} + +trait Trait2 { + fn uvw() -> bool; +} + +impl Trait2 for dyn Send + Sync { + fn uvw() -> bool { false } +} + +impl Trait2 for dyn Sync + Send + Sync { + fn uvw() -> bool { true } +} + +struct Foo(T); +impl Foo { + fn abc() -> bool { + false + } +} + +impl Foo { + fn abc() -> bool { + true + } +} + +fn main() { + assert_eq!(::xyz(), false); + assert_eq!(::xyz(), true); + assert_eq!(::uvw(), false); + assert_eq!(::uvw(), true); + assert_eq!(>::abc(), false); + assert_eq!(>::abc(), true); +} diff --git a/src/test/run-pass/issues/issue-3563-3.rs b/src/test/run-pass/issues/issue-3563-3.rs index 13d74be89d8..6ba1a7b8dfa 100644 --- a/src/test/run-pass/issues/issue-3563-3.rs +++ b/src/test/run-pass/issues/issue-3563-3.rs @@ -128,7 +128,7 @@ trait Canvas { } // Here we provide an implementation of the Canvas methods for AsciiArt. -// Other implementations could also be provided (e.g. for PDF or Apple's Quartz) +// Other implementations could also be provided (e.g., for PDF or Apple's Quartz) // and code can use them polymorphically via the Canvas trait. impl Canvas for AsciiArt { fn add_point(&mut self, shape: Point) { diff --git a/src/test/run-pass/issues/issue-3656.rs b/src/test/run-pass/issues/issue-3656.rs index 63b27406198..99a72444d73 100644 --- a/src/test/run-pass/issues/issue-3656.rs +++ b/src/test/run-pass/issues/issue-3656.rs @@ -19,7 +19,7 @@ // pretty-expanded FIXME #23616 // ignore-wasm32-bare no libc to test with -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; use libc::{c_uint, uint32_t, c_void}; diff --git a/src/test/run-pass/issues/issue-41696.rs b/src/test/run-pass/issues/issue-41696.rs index 3937f9c1930..5a5a2adc124 100644 --- a/src/test/run-pass/issues/issue-41696.rs +++ b/src/test/run-pass/issues/issue-41696.rs @@ -11,6 +11,7 @@ // run-pass #![allow(dead_code)] #![allow(unused_variables)] +#![recursion_limit = "128"] // this used to cause exponential code-size blowup during LLVM passes. #![feature(test)] diff --git a/src/test/run-pass/issues/issue-48159.rs b/src/test/run-pass/issues/issue-48159.rs index 2f625747b25..0d5b211bca9 100644 --- a/src/test/run-pass/issues/issue-48159.rs +++ b/src/test/run-pass/issues/issue-48159.rs @@ -9,7 +9,6 @@ // except according to those terms. // run-pass -#![feature(repr_packed)] #![allow(non_camel_case_types)] use std::mem; diff --git a/src/test/run-pass/issues/issue-49298.rs b/src/test/run-pass/issues/issue-49298.rs index db3c9792f35..42cfb6f6176 100644 --- a/src/test/run-pass/issues/issue-49298.rs +++ b/src/test/run-pass/issues/issue-49298.rs @@ -12,7 +12,7 @@ #![feature(test)] #![allow(unused_mut)] // under NLL we get warning about `x` below: rust-lang/rust#54499 -// This test is bogus (i.e. should be compile-fail) during the period +// This test is bogus (i.e., should be compile-fail) during the period // where #54986 is implemented and #54987 is *not* implemented. For // now: just ignore it under nll // diff --git a/src/test/run-pass/issues/issue-49955-2.rs b/src/test/run-pass/issues/issue-49955-2.rs index 88883821073..94aaa631bc1 100644 --- a/src/test/run-pass/issues/issue-49955-2.rs +++ b/src/test/run-pass/issues/issue-49955-2.rs @@ -18,7 +18,7 @@ const FIVE: Cell = Cell::new(5); #[inline(never)] fn tuple_field() -> &'static u32 { // This test is MIR-borrowck-only because the old borrowck - // doesn't agree that borrows of "frozen" (i.e. without any + // doesn't agree that borrows of "frozen" (i.e., without any // interior mutability) fields of non-frozen temporaries, // should be promoted, while MIR promotion does promote them. &(FIVE, 42).1 diff --git a/src/test/run-pass/lexer-crlf-line-endings-string-literal-doc-comment.rs b/src/test/run-pass/lexer-crlf-line-endings-string-literal-doc-comment.rs index 05f1f1bfea0..77b6ba1e4f8 100644 --- a/src/test/run-pass/lexer-crlf-line-endings-string-literal-doc-comment.rs +++ b/src/test/run-pass/lexer-crlf-line-endings-string-literal-doc-comment.rs @@ -12,7 +12,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// NB: this file needs CRLF line endings. The .gitattributes file in +// N.B., this file needs CRLF line endings. The .gitattributes file in // this directory should enforce it. // ignore-pretty issue #37195 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 14ef8c1f51f..71f39c12957 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 @@ -15,7 +15,7 @@ #![forbid(non_upper_case_globals)] #![feature(non_ascii_idents)] -// Some scripts (e.g. hiragana) don't have a concept of +// Some scripts (e.g., hiragana) don't have a concept of // upper/lowercase struct ヒ; diff --git a/src/test/run-pass/macros/macro-comma-behavior.rs b/src/test/run-pass/macros/macro-comma-behavior.rs index 95774cad229..b245fe1107b 100644 --- a/src/test/run-pass/macros/macro-comma-behavior.rs +++ b/src/test/run-pass/macros/macro-comma-behavior.rs @@ -15,7 +15,7 @@ // // This checks the behavior of macros with trailing commas in key // places where regressions in behavior seem highly possible (due -// to it being e.g. a place where the addition of an argument +// to it being e.g., a place where the addition of an argument // causes it to go down a code path with subtly different behavior). // // There is a companion test in compile-fail. diff --git a/src/test/run-pass/mir/mir_match_test.rs b/src/test/run-pass/mir/mir_match_test.rs new file mode 100644 index 00000000000..1f96d6737e0 --- /dev/null +++ b/src/test/run-pass/mir/mir_match_test.rs @@ -0,0 +1,83 @@ +#![feature(exclusive_range_pattern)] + +// run-pass + +fn main() { + let incl_range = |x, b| { + match x { + 0..=5 if b => 0, + 5..=10 if b => 1, + 1..=4 if !b => 2, + _ => 3, + } + }; + assert_eq!(incl_range(3, false), 2); + assert_eq!(incl_range(3, true), 0); + assert_eq!(incl_range(5, false), 3); + assert_eq!(incl_range(5, true), 0); + + let excl_range = |x, b| { + match x { + 0..5 if b => 0, + 5..10 if b => 1, + 1..4 if !b => 2, + _ => 3, + } + }; + assert_eq!(excl_range(3, false), 2); + assert_eq!(excl_range(3, true), 0); + assert_eq!(excl_range(5, false), 3); + assert_eq!(excl_range(5, true), 1); + + let incl_range_vs_const = |x, b| { + match x { + 0..=5 if b => 0, + 7 => 1, + 3 => 2, + _ => 3, + } + }; + assert_eq!(incl_range_vs_const(5, false), 3); + assert_eq!(incl_range_vs_const(5, true), 0); + assert_eq!(incl_range_vs_const(3, false), 2); + assert_eq!(incl_range_vs_const(3, true), 0); + assert_eq!(incl_range_vs_const(7, false), 1); + assert_eq!(incl_range_vs_const(7, true), 1); + + let excl_range_vs_const = |x, b| { + match x { + 0..5 if b => 0, + 7 => 1, + 3 => 2, + _ => 3, + } + }; + assert_eq!(excl_range_vs_const(5, false), 3); + assert_eq!(excl_range_vs_const(5, true), 3); + assert_eq!(excl_range_vs_const(3, false), 2); + assert_eq!(excl_range_vs_const(3, true), 0); + assert_eq!(excl_range_vs_const(7, false), 1); + assert_eq!(excl_range_vs_const(7, true), 1); + + let const_vs_incl_range = |x, b| { + match x { + 3 if b => 0, + 5..=7 => 2, + 1..=4 => 1, + _ => 3, + } + }; + assert_eq!(const_vs_incl_range(3, false), 1); + assert_eq!(const_vs_incl_range(3, true), 0); + + let const_vs_excl_range = |x, b| { + match x { + 3 if b => 0, + 5..7 => 2, + 1..4 => 1, + _ => 3, + } + }; + assert_eq!(const_vs_excl_range(3, false), 1); + assert_eq!(const_vs_excl_range(3, true), 0); +} diff --git a/src/test/run-pass/multi-panic.rs b/src/test/run-pass/multi-panic.rs index 2e6e10935fa..03e58fc2387 100644 --- a/src/test/run-pass/multi-panic.rs +++ b/src/test/run-pass/multi-panic.rs @@ -17,7 +17,8 @@ fn check_for_no_backtrace(test: std::process::Output) { let mut it = err.lines(); assert_eq!(it.next().map(|l| l.starts_with("thread '' panicked at")), Some(true)); - assert_eq!(it.next(), Some("note: Run with `RUST_BACKTRACE=1` for a backtrace.")); + assert_eq!(it.next(), Some("note: Run with `RUST_BACKTRACE=1` \ + environment variable to display a backtrace.")); assert_eq!(it.next().map(|l| l.starts_with("thread 'main' panicked at")), Some(true)); assert_eq!(it.next(), None); } diff --git a/src/test/run-pass/no-stdio.rs b/src/test/run-pass/no-stdio.rs index d3424176960..2f5bfbb501f 100644 --- a/src/test/run-pass/no-stdio.rs +++ b/src/test/run-pass/no-stdio.rs @@ -12,7 +12,7 @@ // ignore-cloudabi no processes // ignore-emscripten no processes -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; diff --git a/src/test/run-pass/out-of-stack.rs b/src/test/run-pass/out-of-stack.rs index cd0f7cdbf6d..1c714e7f7fa 100644 --- a/src/test/run-pass/out-of-stack.rs +++ b/src/test/run-pass/out-of-stack.rs @@ -16,7 +16,7 @@ // ignore-emscripten no processes #![feature(asm)] -#![feature(libc)] +#![feature(rustc_private)] #[cfg(unix)] extern crate libc; diff --git a/src/test/run-pass/packed/auxiliary/packed.rs b/src/test/run-pass/packed/auxiliary/packed.rs index 828be41cd41..6884c360e4a 100644 --- a/src/test/run-pass/packed/auxiliary/packed.rs +++ b/src/test/run-pass/packed/auxiliary/packed.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(repr_packed)] - #[repr(packed)] pub struct P1S5 { a: u8, diff --git a/src/test/run-pass/packed/packed-struct-borrow-element.rs b/src/test/run-pass/packed/packed-struct-borrow-element.rs index 69969ba640f..87c26c597f5 100644 --- a/src/test/run-pass/packed/packed-struct-borrow-element.rs +++ b/src/test/run-pass/packed/packed-struct-borrow-element.rs @@ -12,8 +12,6 @@ #![allow(dead_code)] // ignore-emscripten weird assertion? -#![feature(repr_packed)] - #[repr(packed)] struct Foo1 { bar: u8, diff --git a/src/test/run-pass/packed/packed-struct-generic-size.rs b/src/test/run-pass/packed/packed-struct-generic-size.rs index 58cd5505ffc..9608ff4ec0e 100644 --- a/src/test/run-pass/packed/packed-struct-generic-size.rs +++ b/src/test/run-pass/packed/packed-struct-generic-size.rs @@ -10,11 +10,8 @@ // run-pass #![allow(dead_code)] -#![allow(stable_features)] #![allow(unused_comparisons)] -#![feature(repr_packed)] - use std::mem; #[repr(packed)] diff --git a/src/test/run-pass/packed/packed-struct-generic-size.stderr b/src/test/run-pass/packed/packed-struct-generic-size.stderr index 994ea7c44fb..672952f6e9f 100644 --- a/src/test/run-pass/packed/packed-struct-generic-size.stderr +++ b/src/test/run-pass/packed/packed-struct-generic-size.stderr @@ -1,35 +1,35 @@ warning: unnecessary path disambiguator - --> $DIR/packed-struct-generic-size.rs:49:14 + --> $DIR/packed-struct-generic-size.rs:46:14 | LL | check!(P1::, 1, 3); | ^^ try removing `::` warning: unnecessary path disambiguator - --> $DIR/packed-struct-generic-size.rs:50:14 + --> $DIR/packed-struct-generic-size.rs:47:14 | LL | check!(P1::, 1, 11); | ^^ try removing `::` warning: unnecessary path disambiguator - --> $DIR/packed-struct-generic-size.rs:52:14 + --> $DIR/packed-struct-generic-size.rs:49:14 | LL | check!(P2::, 1, 3); | ^^ try removing `::` warning: unnecessary path disambiguator - --> $DIR/packed-struct-generic-size.rs:53:14 + --> $DIR/packed-struct-generic-size.rs:50:14 | LL | check!(P2::, 2, 12); | ^^ try removing `::` warning: unnecessary path disambiguator - --> $DIR/packed-struct-generic-size.rs:55:15 + --> $DIR/packed-struct-generic-size.rs:52:15 | LL | check!(P4C::, 1, 3); | ^^ try removing `::` warning: unnecessary path disambiguator - --> $DIR/packed-struct-generic-size.rs:56:15 + --> $DIR/packed-struct-generic-size.rs:53:15 | LL | check!(P4C::, 4, 12); | ^^ try removing `::` diff --git a/src/test/run-pass/packed/packed-struct-match.rs b/src/test/run-pass/packed/packed-struct-match.rs index e349a4e7f54..21ef55e5a42 100644 --- a/src/test/run-pass/packed/packed-struct-match.rs +++ b/src/test/run-pass/packed/packed-struct-match.rs @@ -9,7 +9,6 @@ // except according to those terms. // run-pass -#![feature(repr_packed)] #[repr(packed)] struct Foo1 { diff --git a/src/test/run-pass/packed/packed-struct-optimized-enum.rs b/src/test/run-pass/packed/packed-struct-optimized-enum.rs index e22e8c26fe5..98772778010 100644 --- a/src/test/run-pass/packed/packed-struct-optimized-enum.rs +++ b/src/test/run-pass/packed/packed-struct-optimized-enum.rs @@ -34,12 +34,12 @@ fn main() { // In #46769, `Option<(Packed<&()>, bool)>` was found to have // pointer alignment, without actually being aligned in size. - // E.g. on 64-bit platforms, it had alignment `8` but size `9`. + // e.g., on 64-bit platforms, it had alignment `8` but size `9`. type PackedRefAndBool<'a> = (Packed<&'a ()>, bool); sanity_check_size::>(Some((Packed(&()), true))); // Make sure we don't pay for the enum optimization in size, - // e.g. we shouldn't need extra padding after the packed data. + // e.g., we shouldn't need extra padding after the packed data. assert_eq!(std::mem::align_of::>(), 1); assert_eq!(std::mem::size_of::>(), std::mem::size_of::()); diff --git a/src/test/run-pass/packed/packed-struct-size.rs b/src/test/run-pass/packed/packed-struct-size.rs index 27e07b87ff4..d6a236ffc6d 100644 --- a/src/test/run-pass/packed/packed-struct-size.rs +++ b/src/test/run-pass/packed/packed-struct-size.rs @@ -13,9 +13,6 @@ #![allow(non_camel_case_types)] #![allow(non_upper_case_globals)] -#![feature(repr_packed)] - - use std::mem; #[repr(packed)] diff --git a/src/test/run-pass/packed/packed-struct-vec.rs b/src/test/run-pass/packed/packed-struct-vec.rs index d64bfe0033b..6fd24479c19 100644 --- a/src/test/run-pass/packed/packed-struct-vec.rs +++ b/src/test/run-pass/packed/packed-struct-vec.rs @@ -9,7 +9,6 @@ // except according to those terms. // run-pass -#![feature(repr_packed)] use std::fmt; use std::mem; diff --git a/src/test/run-pass/packed/packed-tuple-struct-size.rs b/src/test/run-pass/packed/packed-tuple-struct-size.rs index 011ff4c20f4..8b18bd33c74 100644 --- a/src/test/run-pass/packed/packed-tuple-struct-size.rs +++ b/src/test/run-pass/packed/packed-tuple-struct-size.rs @@ -12,8 +12,6 @@ #![allow(dead_code)] #![allow(non_camel_case_types)] -#![feature(repr_packed)] - use std::mem; #[repr(packed)] diff --git a/src/test/run-pass/regions/regions-early-bound-trait-param.rs b/src/test/run-pass/regions/regions-early-bound-trait-param.rs index 220614c9203..70cb4bcbd6f 100644 --- a/src/test/run-pass/regions/regions-early-bound-trait-param.rs +++ b/src/test/run-pass/regions/regions-early-bound-trait-param.rs @@ -131,7 +131,7 @@ pub fn main() { // for details. assert_eq!(object_invoke2(&*m), 5); - // The RefMakerTrait above is pretty strange (i.e. it is strange + // The RefMakerTrait above is pretty strange (i.e., it is strange // to consume a value of type T and return a &T). Easiest thing // that came to my mind: consume a cell of a linked list and // return a reference to the list it points to. diff --git a/src/test/run-pass/rfcs/rfc-1014-2.rs b/src/test/run-pass/rfcs/rfc-1014-2.rs index 7fbc0d1db70..257c7f546b1 100644 --- a/src/test/run-pass/rfcs/rfc-1014-2.rs +++ b/src/test/run-pass/rfcs/rfc-1014-2.rs @@ -11,7 +11,7 @@ // run-pass #![allow(dead_code)] -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; diff --git a/src/test/run-pass/rfcs/rfc-1014.rs b/src/test/run-pass/rfcs/rfc-1014.rs index d101c3c9ab1..578a7f4395c 100644 --- a/src/test/run-pass/rfcs/rfc-1014.rs +++ b/src/test/run-pass/rfcs/rfc-1014.rs @@ -13,7 +13,7 @@ // ignore-cloudabi stdout does not map to file descriptor 1 by default // ignore-wasm32-bare no libc -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; 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 a85fe6733dd..961b8020f3d 100644 --- a/src/test/run-pass/segfault-no-out-of-stack.rs +++ b/src/test/run-pass/segfault-no-out-of-stack.rs @@ -12,7 +12,7 @@ // ignore-cloudabi can't run commands // ignore-emscripten can't run commands -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; diff --git a/src/test/run-pass/signal-alternate-stack-cleanup.rs b/src/test/run-pass/signal-alternate-stack-cleanup.rs index ad099f82d13..a79ab20c160 100644 --- a/src/test/run-pass/signal-alternate-stack-cleanup.rs +++ b/src/test/run-pass/signal-alternate-stack-cleanup.rs @@ -16,7 +16,7 @@ // ignore-wasm32-bare no libc // ignore-windows -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; use libc::*; diff --git a/src/test/run-pass/simd/simd-intrinsic-generic-cast.rs b/src/test/run-pass/simd/simd-intrinsic-generic-cast.rs index f0fb24b5832..df5f72e378d 100644 --- a/src/test/run-pass/simd/simd-intrinsic-generic-cast.rs +++ b/src/test/run-pass/simd/simd-intrinsic-generic-cast.rs @@ -94,9 +94,9 @@ fn main() { // there are platform differences for some out of range // casts, so we just normalize such things: it's OK for // "invalid" calculations to result in nonsense answers. - // (E.g. negative float to unsigned integer goes through a + // (e.g., negative float to unsigned integer goes through a // library routine on the default i686 platforms, and the - // implementation of that routine differs on e.g. Linux + // implementation of that routine differs on e.g., Linux // vs. macOS, resulting in different answers.) if $from::is_float() { if !$to::in_range(A) { from.0 = 0 as $to; to.0 = 0 as $to; } diff --git a/src/test/run-pass/simd/simd-intrinsic-generic-gather.rs b/src/test/run-pass/simd/simd-intrinsic-generic-gather.rs index 5f6a72a8e1e..e5ac5775b0c 100644 --- a/src/test/run-pass/simd/simd-intrinsic-generic-gather.rs +++ b/src/test/run-pass/simd/simd-intrinsic-generic-gather.rs @@ -10,7 +10,6 @@ // run-pass // ignore-emscripten -// min-llvm-version 6.0 // Test that the simd_{gather,scatter} intrinsics produce the correct results. diff --git a/src/test/run-pass/simd/simd-intrinsic-generic-select.rs b/src/test/run-pass/simd/simd-intrinsic-generic-select.rs index 590a2990270..74b99ca4950 100644 --- a/src/test/run-pass/simd/simd-intrinsic-generic-select.rs +++ b/src/test/run-pass/simd/simd-intrinsic-generic-select.rs @@ -26,6 +26,10 @@ struct i32x4(pub i32, pub i32, pub i32, pub i32); #[derive(Copy, Clone, PartialEq, Debug)] struct u32x4(pub u32, pub u32, pub u32, pub u32); +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +struct u32x8(u32, u32, u32, u32, u32, u32, u32, u32); + #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] struct f32x4(pub f32, pub f32, pub f32, pub f32); @@ -36,6 +40,7 @@ struct b8x4(pub i8, pub i8, pub i8, pub i8); extern "platform-intrinsic" { fn simd_select(x: T, a: U, b: U) -> U; + fn simd_select_bitmask(x: T, a: U, b: U) -> U; } fn main() { @@ -146,4 +151,29 @@ fn main() { let e = b8x4(t, f, t, t); assert_eq!(r, e); } + + unsafe { + let a = u32x8(0, 1, 2, 3, 4, 5, 6, 7); + let b = u32x8(8, 9, 10, 11, 12, 13, 14, 15); + + let r: u32x8 = simd_select_bitmask(0u8, a, b); + let e = b; + assert_eq!(r, e); + + let r: u32x8 = simd_select_bitmask(0xffu8, a, b); + let e = a; + assert_eq!(r, e); + + let r: u32x8 = simd_select_bitmask(0b01010101u8, a, b); + let e = u32x8(0, 9, 2, 11, 4, 13, 6, 15); + assert_eq!(r, e); + + let r: u32x8 = simd_select_bitmask(0b10101010u8, a, b); + let e = u32x8(8, 1, 10, 3, 12, 5, 14, 7); + assert_eq!(r, e); + + let r: u32x8 = simd_select_bitmask(0b11110000u8, a, b); + let e = u32x8(8, 9, 10, 11, 4, 5, 6, 7); + assert_eq!(r, e); + } } diff --git a/src/test/run-pass/sse2.rs b/src/test/run-pass/sse2.rs index 041286fe656..779c72b8df1 100644 --- a/src/test/run-pass/sse2.rs +++ b/src/test/run-pass/sse2.rs @@ -8,11 +8,9 @@ // 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 +#![allow(stable_features)] #![feature(cfg_target_feature)] use std::env; diff --git a/src/test/run-pass/statics/static-mut-foreign.rs b/src/test/run-pass/statics/static-mut-foreign.rs index d9e43ddea71..460d66a4592 100644 --- a/src/test/run-pass/statics/static-mut-foreign.rs +++ b/src/test/run-pass/statics/static-mut-foreign.rs @@ -15,7 +15,7 @@ // ignore-wasm32-bare no libc to test ffi with -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; diff --git a/src/test/run-pass/structs-enums/align-struct.rs b/src/test/run-pass/structs-enums/align-struct.rs index a0d05a6d0d2..109d5b75590 100644 --- a/src/test/run-pass/structs-enums/align-struct.rs +++ b/src/test/run-pass/structs-enums/align-struct.rs @@ -11,7 +11,6 @@ // run-pass #![allow(dead_code)] #![feature(box_syntax)] -#![feature(repr_packed)] use std::mem; diff --git a/src/test/run-pass/structs-enums/enum-non-c-like-repr-c-and-int.rs b/src/test/run-pass/structs-enums/enum-non-c-like-repr-c-and-int.rs index 14eac687ecf..f59f100653f 100644 --- a/src/test/run-pass/structs-enums/enum-non-c-like-repr-c-and-int.rs +++ b/src/test/run-pass/structs-enums/enum-non-c-like-repr-c-and-int.rs @@ -20,11 +20,12 @@ use std::mem; #[repr(C, u8)] #[derive(Copy, Clone, Eq, PartialEq, Debug)] enum MyEnum { - A(u32), // Single primitive value - B { x: u8, y: i16 }, // Composite, and the offset of `y` depends on tag being internal - C, // Empty - D(Option), // Contains an enum - E(Duration), // Contains a struct + A(u32), // Single primitive value + B { x: u8, y: i16, z: u8 }, // Composite, and the offsets of `y` and `z` + // depend on tag being internal + C, // Empty + D(Option), // Contains an enum + E(Duration), // Contains a struct } #[repr(C)] @@ -44,14 +45,14 @@ union MyEnumPayload { #[repr(u8)] #[derive(Copy, Clone)] enum MyEnumTag { A, B, C, D, E } #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantA(u32); -#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB {x: u8, y: i16 } +#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB {x: u8, y: i16, z: u8 } #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantD(Option); #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantE(Duration); fn main() { let result: Vec> = vec![ Ok(MyEnum::A(17)), - Ok(MyEnum::B { x: 206, y: 1145 }), + Ok(MyEnum::B { x: 206, y: 1145, z: 78 }), Ok(MyEnum::C), Err(()), Ok(MyEnum::D(Some(407))), @@ -63,7 +64,7 @@ fn main() { // Binary serialized version of the above (little-endian) let input: Vec = vec![ 0, 17, 0, 0, 0, - 1, 206, 121, 4, + 1, 206, 121, 4, 78, 2, 8, /* invalid tag value */ 3, 0, 151, 1, 0, 0, @@ -112,6 +113,7 @@ fn parse_my_enum<'a>(dest: &'a mut MyEnum, buf: &mut &[u8]) -> Result<(), ()> { MyEnumTag::B => { dest.payload.B.x = read_u8(buf)?; dest.payload.B.y = read_u16_le(buf)? as i16; + dest.payload.B.z = read_u8(buf)?; } MyEnumTag::C => { /* do nothing */ diff --git a/src/test/run-pass/structs-enums/enum-non-c-like-repr-c.rs b/src/test/run-pass/structs-enums/enum-non-c-like-repr-c.rs index 80c4339af9d..e88b91ab6c3 100644 --- a/src/test/run-pass/structs-enums/enum-non-c-like-repr-c.rs +++ b/src/test/run-pass/structs-enums/enum-non-c-like-repr-c.rs @@ -20,11 +20,12 @@ use std::mem; #[repr(C)] #[derive(Copy, Clone, Eq, PartialEq, Debug)] enum MyEnum { - A(u32), // Single primitive value - B { x: u8, y: i16 }, // Composite, and the offset of `y` depends on tag being internal - C, // Empty - D(Option), // Contains an enum - E(Duration), // Contains a struct + A(u32), // Single primitive value + B { x: u8, y: i16, z: u8 }, // Composite, and the offset of `y` and `z` + // depend on tag being internal + C, // Empty + D(Option), // Contains an enum + E(Duration), // Contains a struct } #[repr(C)] @@ -44,14 +45,14 @@ union MyEnumPayload { #[repr(C)] #[derive(Copy, Clone)] enum MyEnumTag { A, B, C, D, E } #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantA(u32); -#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB {x: u8, y: i16 } +#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB {x: u8, y: i16, z: u8 } #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantD(Option); #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantE(Duration); fn main() { let result: Vec> = vec![ Ok(MyEnum::A(17)), - Ok(MyEnum::B { x: 206, y: 1145 }), + Ok(MyEnum::B { x: 206, y: 1145, z: 78 }), Ok(MyEnum::C), Err(()), Ok(MyEnum::D(Some(407))), @@ -63,7 +64,7 @@ fn main() { // Binary serialized version of the above (little-endian) let input: Vec = vec![ 0, 17, 0, 0, 0, - 1, 206, 121, 4, + 1, 206, 121, 4, 78, 2, 8, /* invalid tag value */ 3, 0, 151, 1, 0, 0, @@ -112,6 +113,7 @@ fn parse_my_enum<'a>(dest: &'a mut MyEnum, buf: &mut &[u8]) -> Result<(), ()> { MyEnumTag::B => { dest.payload.B.x = read_u8(buf)?; dest.payload.B.y = read_u16_le(buf)? as i16; + dest.payload.B.z = read_u8(buf)?; } MyEnumTag::C => { /* do nothing */ diff --git a/src/test/run-pass/structs-enums/enum-non-c-like-repr-int.rs b/src/test/run-pass/structs-enums/enum-non-c-like-repr-int.rs index 4c1fe8db1cd..d862c0c72c2 100644 --- a/src/test/run-pass/structs-enums/enum-non-c-like-repr-int.rs +++ b/src/test/run-pass/structs-enums/enum-non-c-like-repr-int.rs @@ -20,11 +20,12 @@ use std::mem; #[repr(u8)] #[derive(Copy, Clone, Eq, PartialEq, Debug)] enum MyEnum { - A(u32), // Single primitive value - B { x: u8, y: i16 }, // Composite, and the offset of `y` depends on tag being internal - C, // Empty - D(Option), // Contains an enum - E(Duration), // Contains a struct + A(u32), // Single primitive value + B { x: u8, y: i16, z: u8 }, // Composite, and the offset of `y` and `z` + // depend on tag being internal + C, // Empty + D(Option), // Contains an enum + E(Duration), // Contains a struct } #[allow(non_snake_case)] @@ -39,7 +40,7 @@ union MyEnumRepr { #[repr(u8)] #[derive(Copy, Clone)] enum MyEnumTag { A, B, C, D, E } #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantA(MyEnumTag, u32); -#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB { tag: MyEnumTag, x: u8, y: i16 } +#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB { tag: MyEnumTag, x: u8, y: i16, z: u8 } #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantC(MyEnumTag); #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantD(MyEnumTag, Option); #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantE(MyEnumTag, Duration); @@ -47,7 +48,7 @@ union MyEnumRepr { fn main() { let result: Vec> = vec![ Ok(MyEnum::A(17)), - Ok(MyEnum::B { x: 206, y: 1145 }), + Ok(MyEnum::B { x: 206, y: 1145, z: 78 }), Ok(MyEnum::C), Err(()), Ok(MyEnum::D(Some(407))), @@ -59,7 +60,7 @@ fn main() { // Binary serialized version of the above (little-endian) let input: Vec = vec![ 0, 17, 0, 0, 0, - 1, 206, 121, 4, + 1, 206, 121, 4, 78, 2, 8, /* invalid tag value */ 3, 0, 151, 1, 0, 0, @@ -108,6 +109,7 @@ fn parse_my_enum<'a>(dest: &'a mut MyEnum, buf: &mut &[u8]) -> Result<(), ()> { MyEnumTag::B => { dest.B.x = read_u8(buf)?; dest.B.y = read_u16_le(buf)? as i16; + dest.B.z = read_u8(buf)?; } MyEnumTag::C => { /* do nothing */ diff --git a/src/test/run-pass/try-operator-hygiene.rs b/src/test/run-pass/try-operator-hygiene.rs index 045a8a50320..2771ab4233f 100644 --- a/src/test/run-pass/try-operator-hygiene.rs +++ b/src/test/run-pass/try-operator-hygiene.rs @@ -17,7 +17,7 @@ // Err(err) => return Err(From::from(err)), // } // -// This test verifies that the expansion is hygienic, i.e. it's not affected by other `val` and +// This test verifies that the expansion is hygienic, i.e., it's not affected by other `val` and // `err` bindings that may be in scope. use std::num::ParseIntError; diff --git a/src/test/run-pass/uniform-paths/basic-nested.rs b/src/test/run-pass/uniform-paths/basic-nested.rs index a0256187dbb..c6a95ba4089 100644 --- a/src/test/run-pass/uniform-paths/basic-nested.rs +++ b/src/test/run-pass/uniform-paths/basic-nested.rs @@ -41,7 +41,7 @@ use std::io; mod bar { // Also test the unqualified external crate import in a nested module, // to show that the above import doesn't resolve through a local `std` - // item, e.g. the automatically injected `extern crate std;`, which in + // item, e.g., the automatically injected `extern crate std;`, which in // the Rust 2018 should no longer be visible through `crate::std`. pub use std::io; diff --git a/src/test/run-pass/uniform-paths/macros-nested.rs b/src/test/run-pass/uniform-paths/macros-nested.rs index 373734345fc..f22113df80e 100644 --- a/src/test/run-pass/uniform-paths/macros-nested.rs +++ b/src/test/run-pass/uniform-paths/macros-nested.rs @@ -50,7 +50,7 @@ use std::io; mod bar { // Also test the unqualified external crate import in a nested module, // to show that the above import doesn't resolve through a local `std` - // item, e.g. the automatically injected `extern crate std;`, which in + // item, e.g., the automatically injected `extern crate std;`, which in // the Rust 2018 should no longer be visible through `crate::std`. pub use std::io; } diff --git a/src/test/run-pass/union/union-packed.rs b/src/test/run-pass/union/union-packed.rs index a6aef9046ee..4c9e06a395c 100644 --- a/src/test/run-pass/union/union-packed.rs +++ b/src/test/run-pass/union/union-packed.rs @@ -13,7 +13,6 @@ #![allow(non_snake_case)] #![feature(untagged_unions)] -#![feature(repr_packed)] use std::mem::{size_of, size_of_val, align_of, align_of_val}; diff --git a/src/test/run-pass/wait-forked-but-failed-child.rs b/src/test/run-pass/wait-forked-but-failed-child.rs index dc47108e183..d822b67a07c 100644 --- a/src/test/run-pass/wait-forked-but-failed-child.rs +++ b/src/test/run-pass/wait-forked-but-failed-child.rs @@ -11,7 +11,7 @@ // ignore-cloudabi no processes // ignore-emscripten no processes -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; diff --git a/src/test/ui/feature-gates/feature-gate-custom_derive.rs b/src/test/rustdoc-js/filter-crate.js similarity index 69% rename from src/test/ui/feature-gates/feature-gate-custom_derive.rs rename to src/test/rustdoc-js/filter-crate.js index 0b1b3141f5b..97ecc607f47 100644 --- a/src/test/ui/feature-gates/feature-gate-custom_derive.rs +++ b/src/test/rustdoc-js/filter-crate.js @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,8 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[derive_Clone] -//~^ ERROR attributes of the form `#[derive_*]` are reserved -struct Test; +// exact-check -pub fn main() {} +const QUERY = 'hashmap'; +const FILTER_CRATE = 'core'; + +const EXPECTED = { + 'others': [ + ], +}; diff --git a/src/test/rustdoc-ui/.gitattributes b/src/test/rustdoc-ui/.gitattributes new file mode 100644 index 00000000000..2bcabdffb3d --- /dev/null +++ b/src/test/rustdoc-ui/.gitattributes @@ -0,0 +1 @@ +intra-links-warning-crlf.rs eol=crlf diff --git a/src/test/rustdoc-ui/failed-doctest-output.stdout b/src/test/rustdoc-ui/failed-doctest-output.stdout index cab7bda6c67..bd6fa1f84b4 100644 --- a/src/test/rustdoc-ui/failed-doctest-output.stdout +++ b/src/test/rustdoc-ui/failed-doctest-output.stdout @@ -12,16 +12,16 @@ error[E0425]: cannot find value `no` in this scope 3 | no | ^^ not found in this scope -thread '$DIR/failed-doctest-output.rs - OtherStruct (line 27)' panicked at 'couldn't compile the test', src/librustdoc/test.rs:323:13 -note: Run with `RUST_BACKTRACE=1` for a backtrace. +thread '$DIR/failed-doctest-output.rs - OtherStruct (line 27)' panicked at 'couldn't compile the test', src/librustdoc/test.rs:326:13 +note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace. ---- $DIR/failed-doctest-output.rs - SomeStruct (line 21) stdout ---- thread '$DIR/failed-doctest-output.rs - SomeStruct (line 21)' panicked at 'test executable failed: thread 'main' panicked at 'oh no', $DIR/failed-doctest-output.rs:3:1 -note: Run with `RUST_BACKTRACE=1` for a backtrace. +note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace. -', src/librustdoc/test.rs:358:17 +', src/librustdoc/test.rs:361:17 failures: diff --git a/src/test/rustdoc-ui/intra-links-warning-crlf.rs b/src/test/rustdoc-ui/intra-links-warning-crlf.rs new file mode 100644 index 00000000000..20f761fcf4f --- /dev/null +++ b/src/test/rustdoc-ui/intra-links-warning-crlf.rs @@ -0,0 +1,23 @@ +// ignore-tidy-cr + +// compile-pass + +// This file checks the spans of intra-link warnings in a file with CRLF line endings. The +// .gitattributes file in this directory should enforce it. + +/// [error] +pub struct A; + +/// +/// docs [error1] + +/// docs [error2] +/// +pub struct B; + +/** + * This is a multi-line comment. + * + * It also has an [error]. + */ +pub struct C; diff --git a/src/test/rustdoc-ui/intra-links-warning-crlf.stderr b/src/test/rustdoc-ui/intra-links-warning-crlf.stderr new file mode 100644 index 00000000000..62537f2ce2d --- /dev/null +++ b/src/test/rustdoc-ui/intra-links-warning-crlf.stderr @@ -0,0 +1,33 @@ +warning: `[error]` cannot be resolved, ignoring it... + --> $DIR/intra-links-warning-crlf.rs:8:6 + | +LL | /// [error] + | ^^^^^ cannot be resolved, ignoring + | + = note: #[warn(intra_doc_link_resolution_failure)] on by default + = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + +warning: `[error1]` cannot be resolved, ignoring it... + --> $DIR/intra-links-warning-crlf.rs:12:11 + | +LL | /// docs [error1] + | ^^^^^^ cannot be resolved, ignoring + | + = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + +warning: `[error2]` cannot be resolved, ignoring it... + --> $DIR/intra-links-warning-crlf.rs:14:11 + | +LL | /// docs [error2] + | ^^^^^^ cannot be resolved, ignoring + | + = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + +warning: `[error]` cannot be resolved, ignoring it... + --> $DIR/intra-links-warning-crlf.rs:21:20 + | +LL | * It also has an [error]. + | ^^^^^ cannot be resolved, ignoring + | + = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + diff --git a/src/test/rustdoc-ui/intra-links-warning.rs b/src/test/rustdoc-ui/intra-links-warning.rs index d6bc275b57a..db2fd3211f8 100644 --- a/src/test/rustdoc-ui/intra-links-warning.rs +++ b/src/test/rustdoc-ui/intra-links-warning.rs @@ -55,3 +55,33 @@ macro_rules! f { } } f!("Foo\nbar [BarF] bar\nbaz"); + +/** # for example, + * + * time to introduce a link [error]*/ +pub struct A; + +/** + * # for example, + * + * time to introduce a link [error] + */ +pub struct B; + +#[doc = "single line [error]"] +pub struct C; + +#[doc = "single line with \"escaping\" [error]"] +pub struct D; + +/// Item docs. +#[doc="Hello there!"] +/// [error] +pub struct E; + +/// +/// docs [error1] + +/// docs [error2] +/// +pub struct F; diff --git a/src/test/rustdoc-ui/intra-links-warning.stderr b/src/test/rustdoc-ui/intra-links-warning.stderr index c05f99fadc9..ed31421851b 100644 --- a/src/test/rustdoc-ui/intra-links-warning.stderr +++ b/src/test/rustdoc-ui/intra-links-warning.stderr @@ -55,6 +55,76 @@ LL | /// [Qux:Y] | = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` +warning: `[error]` cannot be resolved, ignoring it... + --> $DIR/intra-links-warning.rs:61:30 + | +LL | * time to introduce a link [error]*/ + | ^^^^^ cannot be resolved, ignoring + | + = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + +warning: `[error]` cannot be resolved, ignoring it... + --> $DIR/intra-links-warning.rs:67:30 + | +LL | * time to introduce a link [error] + | ^^^^^ cannot be resolved, ignoring + | + = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + +warning: `[error]` cannot be resolved, ignoring it... + --> $DIR/intra-links-warning.rs:71:1 + | +LL | #[doc = "single line [error]"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the link appears in this line: + + single line [error] + ^^^^^ + = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + +warning: `[error]` cannot be resolved, ignoring it... + --> $DIR/intra-links-warning.rs:74:1 + | +LL | #[doc = "single line with /"escaping/" [error]"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the link appears in this line: + + single line with "escaping" [error] + ^^^^^ + = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + +warning: `[error]` cannot be resolved, ignoring it... + --> $DIR/intra-links-warning.rs:77:1 + | +LL | / /// Item docs. +LL | | #[doc="Hello there!"] +LL | | /// [error] + | |___________^ + | + = note: the link appears in this line: + + [error] + ^^^^^ + = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + +warning: `[error1]` cannot be resolved, ignoring it... + --> $DIR/intra-links-warning.rs:83:11 + | +LL | /// docs [error1] + | ^^^^^^ cannot be resolved, ignoring + | + = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + +warning: `[error2]` cannot be resolved, ignoring it... + --> $DIR/intra-links-warning.rs:85:11 + | +LL | /// docs [error2] + | ^^^^^^ cannot be resolved, ignoring + | + = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + warning: `[BarA]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning.rs:24:10 | @@ -64,37 +134,19 @@ LL | /// bar [BarA] bar = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` warning: `[BarB]` cannot be resolved, ignoring it... - --> $DIR/intra-links-warning.rs:28:1 + --> $DIR/intra-links-warning.rs:30:9 | -LL | / /** -LL | | * Foo -LL | | * bar [BarB] bar -LL | | * baz -LL | | */ - | |___^ +LL | * bar [BarB] bar + | ^^^^ cannot be resolved, ignoring | - = note: the link appears in this line: - - bar [BarB] bar - ^^^^ = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` warning: `[BarC]` cannot be resolved, ignoring it... - --> $DIR/intra-links-warning.rs:35:1 + --> $DIR/intra-links-warning.rs:37:6 | -LL | / /** Foo -LL | | -LL | | bar [BarC] bar -LL | | baz -... | -LL | | -LL | | */ - | |__^ +LL | bar [BarC] bar + | ^^^^ cannot be resolved, ignoring | - = note: the link appears in this line: - - bar [BarC] bar - ^^^^ = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` warning: `[BarD]` cannot be resolved, ignoring it... diff --git a/src/test/rustdoc-ui/lint-group.rs b/src/test/rustdoc-ui/lint-group.rs new file mode 100644 index 00000000000..f82bfb52246 --- /dev/null +++ b/src/test/rustdoc-ui/lint-group.rs @@ -0,0 +1,34 @@ +// 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. + +//! Documenting the kinds of lints emitted by rustdoc. +//! +//! ``` +//! println!("sup"); +//! ``` + +#![deny(rustdoc)] + +/// what up, let's make an [error] +/// +/// ``` +/// println!("sup"); +/// ``` +pub fn link_error() {} //~^^^^^ ERROR cannot be resolved, ignoring it + +/// wait, this doesn't have a doctest? +pub fn no_doctest() {} //~^ ERROR Missing code example in this documentation + +/// wait, this *does* have a doctest? +/// +/// ``` +/// println!("sup"); +/// ``` +fn private_doctest() {} //~^^^^^ ERROR Documentation test in private item diff --git a/src/test/rustdoc-ui/lint-group.stderr b/src/test/rustdoc-ui/lint-group.stderr new file mode 100644 index 00000000000..2fd760d54c2 --- /dev/null +++ b/src/test/rustdoc-ui/lint-group.stderr @@ -0,0 +1,44 @@ +error: Documentation test in private item + --> $DIR/lint-group.rs:29:1 + | +LL | / /// wait, this *does* have a doctest? +LL | | /// +LL | | /// ``` +LL | | /// println!("sup"); +LL | | /// ``` + | |_______^ + | +note: lint level defined here + --> $DIR/lint-group.rs:17:9 + | +LL | #![deny(rustdoc)] + | ^^^^^^^ + = note: #[deny(private_doc_tests)] implied by #[deny(rustdoc)] + +error: `[error]` cannot be resolved, ignoring it... + --> $DIR/lint-group.rs:19:29 + | +LL | /// what up, let's make an [error] + | ^^^^^ cannot be resolved, ignoring + | +note: lint level defined here + --> $DIR/lint-group.rs:17:9 + | +LL | #![deny(rustdoc)] + | ^^^^^^^ + = note: #[deny(intra_doc_link_resolution_failure)] implied by #[deny(rustdoc)] + = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + +error: Missing code example in this documentation + --> $DIR/lint-group.rs:26:1 + | +LL | /// wait, this doesn't have a doctest? + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/lint-group.rs:17:9 + | +LL | #![deny(rustdoc)] + | ^^^^^^^ + = note: #[deny(missing_doc_code_examples)] implied by #[deny(rustdoc)] + diff --git a/src/test/run-pass/ctfe/const-fn-destructuring-arg.rs b/src/test/rustdoc/assoc-consts-version.rs similarity index 55% rename from src/test/run-pass/ctfe/const-fn-destructuring-arg.rs rename to src/test/rustdoc/assoc-consts-version.rs index 88f0d0714f9..2295be27258 100644 --- a/src/test/run-pass/ctfe/const-fn-destructuring-arg.rs +++ b/src/test/rustdoc/assoc-consts-version.rs @@ -8,19 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// run-pass -#![allow(dead_code)] +// ignore-tidy-linelength -// test that certain things are disallowed in constant functions +#![crate_name = "foo"] -#![feature(const_fn, const_let)] +#![feature(staged_api)] -// no destructuring -const fn i(( - a, - b - ): (u32, u32)) -> u32 { - a + b +#![stable(since="1.1.1", feature="rust1")] + +#[stable(since="1.1.1", feature="rust1")] +pub struct SomeStruct; + +impl SomeStruct { + // @has 'foo/struct.SomeStruct.html' '//*[@id="SOME_CONST.v"]//div[@class="since"]' '1.1.2' + #[stable(since="1.1.2", feature="rust2")] + pub const SOME_CONST: usize = 0; } - -fn main() {} diff --git a/src/test/rustdoc/assoc-types.rs b/src/test/rustdoc/assoc-types.rs index d152be33f4c..100bf7af0e9 100644 --- a/src/test/rustdoc/assoc-types.rs +++ b/src/test/rustdoc/assoc-types.rs @@ -15,9 +15,9 @@ // @has assoc_types/trait.Index.html pub trait Index { // @has - '//*[@id="associatedtype.Output"]//code' 'type Output: ?Sized' - // @has - '//*[@id="Output.t"]//code' 'type Output: ?Sized' + // @has - '//code[@id="Output.t"]' 'type Output: ?Sized' type Output: ?Sized; - // @has - '//*[@id="index.v"]//code' 'fn index' + // @has - '//code[@id="index.v"]' 'fn index' // @has - '//*[@id="tymethod.index"]//code' \ // "fn index<'a>(&'a self, index: I) -> &'a Self::Output" // @has - '//*[@id="tymethod.index"]//code//a[@href="../assoc_types/trait.Index.html#associatedtype.Output"]' \ diff --git a/src/test/rustdoc/comment-in-doctest.rs b/src/test/rustdoc/comment-in-doctest.rs new file mode 100644 index 00000000000..3468bb7bda4 --- /dev/null +++ b/src/test/rustdoc/comment-in-doctest.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. + +// compile-flags:--test + +// comments, both doc comments and regular ones, used to trick rustdoc's doctest parser into +// thinking that everything after it was part of the regular program. combined with the libsyntax +// parser loop failing to detect the manual main function, it would wrap everything in `fn main`, +// which would cause the doctest to fail as the "extern crate" declaration was no longer valid. +// oddly enough, it would pass in 2018 if a crate was in the extern prelude. see +// https://github.com/rust-lang/rust/issues/56727 + +//! ``` +//! // crate: proc-macro-test +//! //! this is a test +//! +//! // used to pull in proc-macro specific items +//! extern crate proc_macro; +//! +//! use proc_macro::TokenStream; +//! +//! # fn main() {} +//! ``` diff --git a/src/test/rustdoc/const-display.rs b/src/test/rustdoc/const-display.rs new file mode 100644 index 00000000000..8ac0d07ceef --- /dev/null +++ b/src/test/rustdoc/const-display.rs @@ -0,0 +1,43 @@ +// 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 = "foo"] + +#![unstable(feature = "humans", + reason = "who ever let humans program computers, we're apparently really bad at it", + issue = "0")] + +#![feature(rustc_const_unstable, const_fn, foo, foo2)] +#![feature(min_const_unsafe_fn)] +#![feature(staged_api)] + +// @has 'foo/fn.foo.html' '//pre' 'pub unsafe fn foo() -> u32' +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature="foo")] +pub const unsafe fn foo() -> u32 { 42 } + +// @has 'foo/fn.foo2.html' '//pre' 'pub fn foo2() -> u32' +#[unstable(feature = "humans", issue="0")] +pub const fn foo2() -> u32 { 42 } + +// @has 'foo/fn.bar2.html' '//pre' 'pub const fn bar2() -> u32' +#[stable(feature = "rust1", since = "1.0.0")] +pub const fn bar2() -> u32 { 42 } + +// @has 'foo/fn.foo2_gated.html' '//pre' 'pub unsafe fn foo2_gated() -> u32' +#[unstable(feature = "foo2", issue="0")] +pub const unsafe fn foo2_gated() -> u32 { 42 } + +// @has 'foo/fn.bar2_gated.html' '//pre' 'pub const unsafe fn bar2_gated() -> u32' +#[stable(feature = "rust1", since = "1.0.0")] +pub const unsafe fn bar2_gated() -> u32 { 42 } + +// @has 'foo/fn.bar_not_gated.html' '//pre' 'pub unsafe fn bar_not_gated() -> u32' +pub const unsafe fn bar_not_gated() -> u32 { 42 } diff --git a/src/test/rustdoc/deprecated.rs b/src/test/rustdoc/deprecated.rs index 744304a62c2..63447ad1690 100644 --- a/src/test/rustdoc/deprecated.rs +++ b/src/test/rustdoc/deprecated.rs @@ -10,7 +10,29 @@ #![feature(deprecated)] +// @matches deprecated/index.html '//*[@class="docblock-short"]' \ +// '^\[Deprecated\] Deprecated docs' // @has deprecated/struct.S.html '//*[@class="stab deprecated"]' \ // 'Deprecated since 1.0.0: text' +/// Deprecated docs #[deprecated(since = "1.0.0", note = "text")] pub struct S; + +// @matches deprecated/index.html '//*[@class="docblock-short"]' '^Docs' +/// Docs +pub struct T; + +// @matches deprecated/struct.U.html '//*[@class="stab deprecated"]' \ +// 'Deprecated since 1.0.0$' +#[deprecated(since = "1.0.0")] +pub struct U; + +// @matches deprecated/struct.V.html '//*[@class="stab deprecated"]' \ +// 'Deprecated: text$' +#[deprecated(note = "text")] +pub struct V; + +// @matches deprecated/struct.W.html '//*[@class="stab deprecated"]' \ +// 'Deprecated$' +#[deprecated] +pub struct W; diff --git a/src/test/rustdoc/inline_local/macro_by_example.rs b/src/test/rustdoc/inline_local/macro_by_example.rs new file mode 100644 index 00000000000..93d55ec0798 --- /dev/null +++ b/src/test/rustdoc/inline_local/macro_by_example.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. + + +/// docs for foo +#[deprecated(since = "1.2.3", note = "text")] +#[macro_export] +macro_rules! foo { + ($($tt:tt)*) => {} +} + +// @has macro_by_example/macros/index.html +pub mod macros { + // @!has - 'pub use foo as bar;' + // @has macro_by_example/macros/macro.bar.html + // @has - '//*[@class="docblock"]' 'docs for foo' + // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.2.3: text' + // @has - '//a/@href' 'macro_by_example.rs.html#15-17' + #[doc(inline)] + pub use foo as bar; +} diff --git a/src/test/rustdoc/internal.rs b/src/test/rustdoc/internal.rs new file mode 100644 index 00000000000..ba58da138a8 --- /dev/null +++ b/src/test/rustdoc/internal.rs @@ -0,0 +1,10 @@ +// compile-flags: -Z force-unstable-if-unmarked + +// @matches internal/index.html '//*[@class="docblock-short"]' \ +// '^\[Internal\] Docs' +// @has internal/struct.S.html '//*[@class="stab internal"]' \ +// 'This is an internal compiler API. (rustc_private)' +/// Docs +pub struct S; + +fn main() {} diff --git a/src/test/rustdoc/issue-27759.rs b/src/test/rustdoc/issue-27759.rs index e82e93230aa..4723b04a078 100644 --- a/src/test/rustdoc/issue-27759.rs +++ b/src/test/rustdoc/issue-27759.rs @@ -14,13 +14,11 @@ #![unstable(feature="test", issue="27759")] // @has issue_27759/unstable/index.html -// @has - 'test ' -// @has - '#27759' +// @has - 'test #27759' #[unstable(feature="test", issue="27759")] pub mod unstable { // @has issue_27759/unstable/fn.issue.html - // @has - 'test_function ' - // @has - '#1234567890' - #[unstable(feature="test_function", issue="1234567890")] + // @has - 'test_function #12345' + #[unstable(feature="test_function", issue="12345")] pub fn issue() {} } diff --git a/src/test/rustdoc/issue-32374.rs b/src/test/rustdoc/issue-32374.rs index 6d1f8bc1cf9..34423d0176d 100644 --- a/src/test/rustdoc/issue-32374.rs +++ b/src/test/rustdoc/issue-32374.rs @@ -13,15 +13,15 @@ #![unstable(feature="test", issue = "32374")] -// @has issue_32374/index.html '//*[@class="docblock-short"]' \ -// '[Deprecated] [Experimental]' +// @matches issue_32374/index.html '//*[@class="docblock-short"]' \ +// '^\[Deprecated\] \[Experimental\] Docs' // @has issue_32374/struct.T.html '//*[@class="stab deprecated"]' \ // 'Deprecated since 1.0.0: text' -// @has - 'test ' -// @has - '#32374' +// @has - 'test #32374' // @matches issue_32374/struct.T.html '//*[@class="stab unstable"]' \ -// '🔬 This is a nightly-only experimental API. \(test #32374\)$' +// '🔬 This is a nightly-only experimental API. \(test #32374\)$' +/// Docs #[rustc_deprecated(since = "1.0.0", reason = "text")] #[unstable(feature = "test", issue = "32374")] pub struct T; diff --git a/src/test/rustdoc/issue-50159.rs b/src/test/rustdoc/issue-50159.rs new file mode 100644 index 00000000000..3055c721624 --- /dev/null +++ b/src/test/rustdoc/issue-50159.rs @@ -0,0 +1,31 @@ +// 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 Signal { + type Item; +} + +pub trait Signal2 { + type Item2; +} + +impl Signal2 for B where B: Signal { + type Item2 = C; +} + +// @has issue_50159/struct.Switch.html +// @has - '//code' 'impl Send for Switch where ::Item: Send' +// @has - '//code' 'impl Sync for Switch where ::Item: Sync' +// @count - '//*[@id="implementations-list"]/*[@class="impl"]' 0 +// @count - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]' 2 +pub struct Switch { + pub inner: ::Item2, +} diff --git a/src/test/rustdoc/proc-macro.rs b/src/test/rustdoc/proc-macro.rs index 23d0d005807..05d64f82fbd 100644 --- a/src/test/rustdoc/proc-macro.rs +++ b/src/test/rustdoc/proc-macro.rs @@ -61,3 +61,16 @@ pub fn some_proc_attr(_attr: TokenStream, item: TokenStream) -> TokenStream { pub fn some_derive(_item: TokenStream) -> TokenStream { TokenStream::new() } + +// @has some_macros/foo/index.html +pub mod foo { + // @has - '//code' 'pub use some_proc_macro;' + // @has - '//a/@href' '../../some_macros/macro.some_proc_macro.html' + pub use some_proc_macro; + // @has - '//code' 'pub use some_proc_attr;' + // @has - '//a/@href' '../../some_macros/attr.some_proc_attr.html' + pub use some_proc_attr; + // @has - '//code' 'pub use some_derive;' + // @has - '//a/@href' '../../some_macros/derive.SomeDerive.html' + pub use some_derive; +} diff --git a/src/test/rustdoc/static-root-path.rs b/src/test/rustdoc/static-root-path.rs new file mode 100644 index 00000000000..7df3fee3365 --- /dev/null +++ b/src/test/rustdoc/static-root-path.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. + +// compile-flags:-Z unstable-options --static-root-path /cache/ + +// @has static_root_path/struct.SomeStruct.html +// @matches - '"/cache/main\.js"' +// @!matches - '"\.\./main\.js"' +// @matches - '"\.\./search-index\.js"' +// @!matches - '"/cache/search-index\.js"' +pub struct SomeStruct; + +// @has src/static_root_path/static-root-path.rs.html +// @matches - '"/cache/source-script\.js"' +// @!matches - '"\.\./\.\./source-script\.js"' +// @matches - '"\.\./\.\./source-files.js"' +// @!matches - '"/cache/source-files\.js"' diff --git a/src/test/rustdoc/synthetic_auto/self-referential.rs b/src/test/rustdoc/synthetic_auto/self-referential.rs new file mode 100644 index 00000000000..516a3c9a516 --- /dev/null +++ b/src/test/rustdoc/synthetic_auto/self-referential.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. + +// Some unusual code minimized from +// https://github.com/sile/handy_async/tree/7b619b762c06544fc67792c8ff8ebc24a88fdb98 + +pub trait Pattern { + type Value; +} + +pub struct Constrain(A, B, C); + +impl Pattern for Constrain + where A: Pattern, + B: Pattern, + C: Pattern, +{ + type Value = A::Value; +} + +pub struct Wrapper(T); + +impl Pattern for Wrapper { + type Value = T; +} + + +// @has self_referential/struct.WriteAndThen.html +// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl Send for \ +// WriteAndThen where ::Value: Send" +pub struct WriteAndThen(pub P1::Value,pub > as Pattern>::Value) + where P1: Pattern; + diff --git a/src/test/compile-fail-fulldeps/auxiliary/attr_plugin_test.rs b/src/test/ui-fulldeps/auxiliary/attr_plugin_test.rs similarity index 100% rename from src/test/compile-fail-fulldeps/auxiliary/attr_plugin_test.rs rename to src/test/ui-fulldeps/auxiliary/attr_plugin_test.rs diff --git a/src/test/compile-fail-fulldeps/auxiliary/lint_for_crate.rs b/src/test/ui-fulldeps/auxiliary/lint_for_crate.rs similarity index 100% rename from src/test/compile-fail-fulldeps/auxiliary/lint_for_crate.rs rename to src/test/ui-fulldeps/auxiliary/lint_for_crate.rs diff --git a/src/test/compile-fail-fulldeps/auxiliary/macro_crate_test.rs b/src/test/ui-fulldeps/auxiliary/macro_crate_test.rs similarity index 100% rename from src/test/compile-fail-fulldeps/auxiliary/macro_crate_test.rs rename to src/test/ui-fulldeps/auxiliary/macro_crate_test.rs diff --git a/src/test/compile-fail-fulldeps/auxiliary/rlib_crate_test.rs b/src/test/ui-fulldeps/auxiliary/rlib_crate_test.rs similarity index 100% rename from src/test/compile-fail-fulldeps/auxiliary/rlib_crate_test.rs rename to src/test/ui-fulldeps/auxiliary/rlib_crate_test.rs diff --git a/src/test/compile-fail-fulldeps/dropck_tarena_cycle_checked.rs b/src/test/ui-fulldeps/dropck_tarena_cycle_checked.rs similarity index 100% rename from src/test/compile-fail-fulldeps/dropck_tarena_cycle_checked.rs rename to src/test/ui-fulldeps/dropck_tarena_cycle_checked.rs diff --git a/src/test/ui-fulldeps/dropck_tarena_cycle_checked.stderr b/src/test/ui-fulldeps/dropck_tarena_cycle_checked.stderr new file mode 100644 index 00000000000..eae33bab453 --- /dev/null +++ b/src/test/ui-fulldeps/dropck_tarena_cycle_checked.stderr @@ -0,0 +1,13 @@ +error[E0597]: `arena` does not live long enough + --> $DIR/dropck_tarena_cycle_checked.rs:126:8 + | +LL | f(&arena); + | ^^^^^ borrowed value does not live long enough +LL | } //~^ ERROR `arena` does not live long enough + | - `arena` dropped here while still borrowed + | + = note: values in a scope are dropped in the opposite order they are created + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/compile-fail-fulldeps/dropck_tarena_unsound_drop.rs b/src/test/ui-fulldeps/dropck_tarena_unsound_drop.rs similarity index 100% rename from src/test/compile-fail-fulldeps/dropck_tarena_unsound_drop.rs rename to src/test/ui-fulldeps/dropck_tarena_unsound_drop.rs diff --git a/src/test/ui-fulldeps/dropck_tarena_unsound_drop.stderr b/src/test/ui-fulldeps/dropck_tarena_unsound_drop.stderr new file mode 100644 index 00000000000..75ceb692c75 --- /dev/null +++ b/src/test/ui-fulldeps/dropck_tarena_unsound_drop.stderr @@ -0,0 +1,13 @@ +error[E0597]: `arena` does not live long enough + --> $DIR/dropck_tarena_unsound_drop.rs:51:8 + | +LL | f(&arena); + | ^^^^^ borrowed value does not live long enough +LL | } //~^ ERROR `arena` does not live long enough + | - `arena` dropped here while still borrowed + | + = note: values in a scope are dropped in the opposite order they are created + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/compile-fail-fulldeps/gated-plugin.rs b/src/test/ui-fulldeps/gated-plugin.rs similarity index 100% rename from src/test/compile-fail-fulldeps/gated-plugin.rs rename to src/test/ui-fulldeps/gated-plugin.rs diff --git a/src/test/ui-fulldeps/gated-plugin.stderr b/src/test/ui-fulldeps/gated-plugin.stderr new file mode 100644 index 00000000000..075bc799b33 --- /dev/null +++ b/src/test/ui-fulldeps/gated-plugin.stderr @@ -0,0 +1,11 @@ +error[E0658]: compiler plugins are experimental and possibly buggy (see issue #29597) + --> $DIR/gated-plugin.rs:13:1 + | +LL | #![plugin(macro_crate_test)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(plugin)] 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/compile-fail-fulldeps/gated-quote.rs b/src/test/ui-fulldeps/gated-quote.rs similarity index 100% rename from src/test/compile-fail-fulldeps/gated-quote.rs rename to src/test/ui-fulldeps/gated-quote.rs diff --git a/src/test/ui-fulldeps/gated-quote.stderr b/src/test/ui-fulldeps/gated-quote.stderr new file mode 100644 index 00000000000..db091938c6e --- /dev/null +++ b/src/test/ui-fulldeps/gated-quote.stderr @@ -0,0 +1,80 @@ +error: cannot find macro `quote_path!` in this scope + --> $DIR/gated-quote.rs:65:13 + | +LL | let x = quote_path!(ecx, 3); + | ^^^^^^^^^^ + +error: cannot find macro `quote_meta_item!` in this scope + --> $DIR/gated-quote.rs:63:13 + | +LL | let x = quote_meta_item!(ecx, 3); + | ^^^^^^^^^^^^^^^ + +error: cannot find macro `quote_block!` in this scope + --> $DIR/gated-quote.rs:61:13 + | +LL | let x = quote_block!(ecx, 3); + | ^^^^^^^^^^^ + +error: cannot find macro `quote_arg!` in this scope + --> $DIR/gated-quote.rs:59:13 + | +LL | let x = quote_arg!(ecx, 3); + | ^^^^^^^^^ + +error: cannot find macro `quote_attr!` in this scope + --> $DIR/gated-quote.rs:57:13 + | +LL | let x = quote_attr!(ecx, 3); + | ^^^^^^^^^^ + +error: cannot find macro `quote_stmt!` in this scope + --> $DIR/gated-quote.rs:55:13 + | +LL | let x = quote_stmt!(ecx, 3); + | ^^^^^^^^^^ + +error: cannot find macro `quote_arm!` in this scope + --> $DIR/gated-quote.rs:53:13 + | +LL | let x = quote_arm!(ecx, 3); + | ^^^^^^^^^ + +error: cannot find macro `quote_pat!` in this scope + --> $DIR/gated-quote.rs:51:13 + | +LL | let x = quote_pat!(ecx, 3); + | ^^^^^^^^^ + +error: cannot find macro `quote_item!` in this scope + --> $DIR/gated-quote.rs:49:13 + | +LL | let x = quote_item!(ecx, 3); + | ^^^^^^^^^^ + +error: cannot find macro `quote_method!` in this scope + --> $DIR/gated-quote.rs:47:13 + | +LL | let x = quote_method!(ecx, 3); + | ^^^^^^^^^^^^ + +error: cannot find macro `quote_ty!` in this scope + --> $DIR/gated-quote.rs:45:13 + | +LL | let x = quote_ty!(ecx, 3); + | ^^^^^^^^ + +error: cannot find macro `quote_expr!` in this scope + --> $DIR/gated-quote.rs:43:13 + | +LL | let x = quote_expr!(ecx, 3); + | ^^^^^^^^^^ + +error: cannot find macro `quote_tokens!` in this scope + --> $DIR/gated-quote.rs:41:13 + | +LL | let x = quote_tokens!(ecx, 3); + | ^^^^^^^^^^^^ + +error: aborting due to 13 previous errors + diff --git a/src/test/compile-fail-fulldeps/issue-15778-fail.rs b/src/test/ui-fulldeps/issue-15778-fail.rs similarity index 100% rename from src/test/compile-fail-fulldeps/issue-15778-fail.rs rename to src/test/ui-fulldeps/issue-15778-fail.rs diff --git a/src/test/ui-fulldeps/issue-15778-fail.stderr b/src/test/ui-fulldeps/issue-15778-fail.stderr new file mode 100644 index 00000000000..49a2b260a1e --- /dev/null +++ b/src/test/ui-fulldeps/issue-15778-fail.stderr @@ -0,0 +1,13 @@ +error: crate is not marked with #![crate_okay] + --> $DIR/issue-15778-fail.rs:15:1 + | +LL | / #![feature(plugin)] //~ ERROR crate is not marked with #![crate_okay] +LL | | #![plugin(lint_for_crate)] +LL | | +LL | | pub fn main() { } + | |_________________^ + | + = note: requested on the command line with `-D crate-not-okay` + +error: aborting due to previous error + diff --git a/src/test/compile-fail-fulldeps/issue-48941.rs b/src/test/ui-fulldeps/issue-48941.rs similarity index 100% rename from src/test/compile-fail-fulldeps/issue-48941.rs rename to src/test/ui-fulldeps/issue-48941.rs diff --git a/src/test/ui-fulldeps/issue-48941.stderr b/src/test/ui-fulldeps/issue-48941.stderr new file mode 100644 index 00000000000..606c51fc500 --- /dev/null +++ b/src/test/ui-fulldeps/issue-48941.stderr @@ -0,0 +1,14 @@ +error: expected unsuffixed literal or identifier, found a + --> $DIR/issue-48941.rs:20:24 + | +LL | #[noop_attribute("hi", rank = a)] //~ ERROR expected unsuffixed literal or identifier, found a + | ^^^^ + +error: expected unsuffixed literal or identifier, found = + --> $DIR/issue-48941.rs:23:27 + | +LL | #[noop_attribute("/user", data= = " $DIR/lint-group-plugin-deny-cmdline.rs:18:1 + | +LL | fn lintme() { } //~ ERROR item is named 'lintme' + | ^^^^^^^^^^^^^^^ + | + = note: `-D test-lint` implied by `-D lint-me` + +error: item is named 'pleaselintme' + --> $DIR/lint-group-plugin-deny-cmdline.rs:20:1 + | +LL | fn pleaselintme() { } //~ ERROR item is named 'pleaselintme' + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D please-lint` implied by `-D lint-me` + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail-fulldeps/lint-plugin-deny-attr.rs b/src/test/ui-fulldeps/lint-plugin-deny-attr.rs similarity index 100% rename from src/test/compile-fail-fulldeps/lint-plugin-deny-attr.rs rename to src/test/ui-fulldeps/lint-plugin-deny-attr.rs diff --git a/src/test/ui-fulldeps/lint-plugin-deny-attr.stderr b/src/test/ui-fulldeps/lint-plugin-deny-attr.stderr new file mode 100644 index 00000000000..e0ea1e0065a --- /dev/null +++ b/src/test/ui-fulldeps/lint-plugin-deny-attr.stderr @@ -0,0 +1,14 @@ +error: item is named 'lintme' + --> $DIR/lint-plugin-deny-attr.rs:18:1 + | +LL | fn lintme() { } //~ ERROR item is named 'lintme' + | ^^^^^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/lint-plugin-deny-attr.rs:16:9 + | +LL | #![deny(test_lint)] + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/compile-fail-fulldeps/lint-plugin-deny-cmdline.rs b/src/test/ui-fulldeps/lint-plugin-deny-cmdline.rs similarity index 100% rename from src/test/compile-fail-fulldeps/lint-plugin-deny-cmdline.rs rename to src/test/ui-fulldeps/lint-plugin-deny-cmdline.rs diff --git a/src/test/ui-fulldeps/lint-plugin-deny-cmdline.stderr b/src/test/ui-fulldeps/lint-plugin-deny-cmdline.stderr new file mode 100644 index 00000000000..9084253b71e --- /dev/null +++ b/src/test/ui-fulldeps/lint-plugin-deny-cmdline.stderr @@ -0,0 +1,10 @@ +error: item is named 'lintme' + --> $DIR/lint-plugin-deny-cmdline.rs:18:1 + | +LL | fn lintme() { } //~ ERROR item is named 'lintme' + | ^^^^^^^^^^^^^^^ + | + = note: requested on the command line with `-D test-lint` + +error: aborting due to previous error + diff --git a/src/test/compile-fail-fulldeps/lint-plugin-forbid-cmdline.rs b/src/test/ui-fulldeps/lint-plugin-forbid-cmdline.rs similarity index 100% rename from src/test/compile-fail-fulldeps/lint-plugin-forbid-cmdline.rs rename to src/test/ui-fulldeps/lint-plugin-forbid-cmdline.rs diff --git a/src/test/ui-fulldeps/lint-plugin-forbid-cmdline.stderr b/src/test/ui-fulldeps/lint-plugin-forbid-cmdline.stderr new file mode 100644 index 00000000000..30043db41da --- /dev/null +++ b/src/test/ui-fulldeps/lint-plugin-forbid-cmdline.stderr @@ -0,0 +1,19 @@ +error[E0453]: allow(test_lint) overruled by outer forbid(test_lint) + --> $DIR/lint-plugin-forbid-cmdline.rs:20:9 + | +LL | #[allow(test_lint)] //~ ERROR allow(test_lint) overruled by outer forbid(test_lint) + | ^^^^^^^^^ overruled by previous forbid + | + = note: `forbid` lint level was set on command line + +error: item is named 'lintme' + --> $DIR/lint-plugin-forbid-cmdline.rs:18:1 + | +LL | fn lintme() { } //~ ERROR item is named 'lintme' + | ^^^^^^^^^^^^^^^ + | + = note: requested on the command line with `-F test-lint` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0453`. diff --git a/src/test/compile-fail-fulldeps/macro-crate-doesnt-resolve.rs b/src/test/ui-fulldeps/macro-crate-doesnt-resolve.rs similarity index 100% rename from src/test/compile-fail-fulldeps/macro-crate-doesnt-resolve.rs rename to src/test/ui-fulldeps/macro-crate-doesnt-resolve.rs diff --git a/src/test/ui-fulldeps/macro-crate-doesnt-resolve.stderr b/src/test/ui-fulldeps/macro-crate-doesnt-resolve.stderr new file mode 100644 index 00000000000..c45cfa9070f --- /dev/null +++ b/src/test/ui-fulldeps/macro-crate-doesnt-resolve.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find function `foo` in module `macro_crate_test` + --> $DIR/macro-crate-doesnt-resolve.rs:17:23 + | +LL | macro_crate_test::foo(); //~ ERROR cannot find function `foo` in module `macro_crate_test` + | ^^^ not found in `macro_crate_test` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/compile-fail-fulldeps/macro-crate-rlib.rs b/src/test/ui-fulldeps/macro-crate-rlib.rs similarity index 100% rename from src/test/compile-fail-fulldeps/macro-crate-rlib.rs rename to src/test/ui-fulldeps/macro-crate-rlib.rs diff --git a/src/test/ui-fulldeps/macro-crate-rlib.stderr b/src/test/ui-fulldeps/macro-crate-rlib.stderr new file mode 100644 index 00000000000..8a7f7883a10 --- /dev/null +++ b/src/test/ui-fulldeps/macro-crate-rlib.stderr @@ -0,0 +1,9 @@ +error[E0457]: plugin `rlib_crate_test` only found in rlib format, but must be available in dylib format + --> $DIR/macro-crate-rlib.rs:16:11 + | +LL | #![plugin(rlib_crate_test)] + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0457`. diff --git a/src/test/compile-fail-fulldeps/macro-crate-unexported-macro.rs b/src/test/ui-fulldeps/macro-crate-unexported-macro.rs similarity index 100% rename from src/test/compile-fail-fulldeps/macro-crate-unexported-macro.rs rename to src/test/ui-fulldeps/macro-crate-unexported-macro.rs diff --git a/src/test/ui-fulldeps/macro-crate-unexported-macro.stderr b/src/test/ui-fulldeps/macro-crate-unexported-macro.stderr new file mode 100644 index 00000000000..8d87c882a1a --- /dev/null +++ b/src/test/ui-fulldeps/macro-crate-unexported-macro.stderr @@ -0,0 +1,8 @@ +error: cannot find macro `unexported_macro!` in this scope + --> $DIR/macro-crate-unexported-macro.rs:17:5 + | +LL | unexported_macro!(); + | ^^^^^^^^^^^^^^^^ help: you could try the macro: `exported_macro` + +error: aborting due to previous error + diff --git a/src/test/compile-fail-fulldeps/plugin-as-extern-crate.rs b/src/test/ui-fulldeps/plugin-as-extern-crate.rs similarity index 100% rename from src/test/compile-fail-fulldeps/plugin-as-extern-crate.rs rename to src/test/ui-fulldeps/plugin-as-extern-crate.rs diff --git a/src/test/ui-fulldeps/plugin-as-extern-crate.stderr b/src/test/ui-fulldeps/plugin-as-extern-crate.stderr new file mode 100644 index 00000000000..713f1b07345 --- /dev/null +++ b/src/test/ui-fulldeps/plugin-as-extern-crate.stderr @@ -0,0 +1,14 @@ +error: compiler plugin used as an ordinary library + --> $DIR/plugin-as-extern-crate.rs:20:1 + | +LL | extern crate macro_crate_test; //~ ERROR compiler plugin used as an ordinary library + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/plugin-as-extern-crate.rs:17:9 + | +LL | #![deny(plugin_as_library)] + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/compile-fail-fulldeps/plugin-attr-register-deny.rs b/src/test/ui-fulldeps/plugin-attr-register-deny.rs similarity index 100% rename from src/test/compile-fail-fulldeps/plugin-attr-register-deny.rs rename to src/test/ui-fulldeps/plugin-attr-register-deny.rs diff --git a/src/test/ui-fulldeps/plugin-attr-register-deny.stderr b/src/test/ui-fulldeps/plugin-attr-register-deny.stderr new file mode 100644 index 00000000000..0bb2d1c9f5e --- /dev/null +++ b/src/test/ui-fulldeps/plugin-attr-register-deny.stderr @@ -0,0 +1,26 @@ +error: unused attribute + --> $DIR/plugin-attr-register-deny.rs:24:5 + | +LL | #[bar] + | ^^^^^^ + | +note: lint level defined here + --> $DIR/plugin-attr-register-deny.rs:16:9 + | +LL | #![deny(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +error: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/plugin-attr-register-deny.rs:24:5 + | +LL | #[bar] + | ^^^^^^ + +error: unused attribute + --> $DIR/plugin-attr-register-deny.rs:21:1 + | +LL | #[foo] + | ^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/compile-fail-fulldeps/plugin-plus-extern-crate.rs b/src/test/ui-fulldeps/plugin-plus-extern-crate.rs similarity index 100% rename from src/test/compile-fail-fulldeps/plugin-plus-extern-crate.rs rename to src/test/ui-fulldeps/plugin-plus-extern-crate.rs diff --git a/src/test/ui-fulldeps/plugin-plus-extern-crate.stderr b/src/test/ui-fulldeps/plugin-plus-extern-crate.stderr new file mode 100644 index 00000000000..faefe04e14a --- /dev/null +++ b/src/test/ui-fulldeps/plugin-plus-extern-crate.stderr @@ -0,0 +1,14 @@ +error: compiler plugin used as an ordinary library + --> $DIR/plugin-plus-extern-crate.rs:22:1 + | +LL | extern crate macro_crate_test; //~ ERROR compiler plugin used as an ordinary library + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/plugin-plus-extern-crate.rs:18:9 + | +LL | #![deny(plugin_as_library)] + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/compile-fail-fulldeps/qquote.rs b/src/test/ui-fulldeps/qquote.rs similarity index 100% rename from src/test/compile-fail-fulldeps/qquote.rs rename to src/test/ui-fulldeps/qquote.rs diff --git a/src/test/ui-fulldeps/qquote.stderr b/src/test/ui-fulldeps/qquote.stderr new file mode 100644 index 00000000000..4c136ad4b78 --- /dev/null +++ b/src/test/ui-fulldeps/qquote.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `abcd` in this scope + --> $DIR/qquote.rs:35:38 + | +LL | let expr = quote_expr!(&cx, 2 - $abcd + 7); //~ ERROR cannot find value `abcd` in this scope + | ^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/E0501.ast.nll.stderr b/src/test/ui/E0501.ast.nll.stderr index 72fda9079d6..8a3fce3a554 100644 --- a/src/test/ui/E0501.ast.nll.stderr +++ b/src/test/ui/E0501.ast.nll.stderr @@ -7,7 +7,7 @@ LL | inside_closure(a) | - first borrow occurs due to use of `a` in closure LL | }; LL | outside_closure_1(a); //[ast]~ ERROR cannot borrow `*a` as mutable because previous closure requires unique access - | ^ borrow occurs here + | ^ second borrow occurs here ... LL | drop(bar); | --- first borrow later used here @@ -21,7 +21,7 @@ LL | inside_closure(a) | - first borrow occurs due to use of `a` in closure ... LL | outside_closure_2(a); //[ast]~ ERROR cannot borrow `*a` as immutable because previous closure requires unique access - | ^ borrow occurs here + | ^ second borrow occurs here ... LL | drop(bar); | --- first borrow later used here diff --git a/src/test/ui/E0501.mir.stderr b/src/test/ui/E0501.mir.stderr index 72fda9079d6..8a3fce3a554 100644 --- a/src/test/ui/E0501.mir.stderr +++ b/src/test/ui/E0501.mir.stderr @@ -7,7 +7,7 @@ LL | inside_closure(a) | - first borrow occurs due to use of `a` in closure LL | }; LL | outside_closure_1(a); //[ast]~ ERROR cannot borrow `*a` as mutable because previous closure requires unique access - | ^ borrow occurs here + | ^ second borrow occurs here ... LL | drop(bar); | --- first borrow later used here @@ -21,7 +21,7 @@ LL | inside_closure(a) | - first borrow occurs due to use of `a` in closure ... LL | outside_closure_2(a); //[ast]~ ERROR cannot borrow `*a` as immutable because previous closure requires unique access - | ^ borrow occurs here + | ^ second borrow occurs here ... LL | drop(bar); | --- first borrow later used here diff --git a/src/test/ui/anon-params-denied-2018.stderr b/src/test/ui/anon-params-denied-2018.stderr index 24a1e6ecd93..dd9e933542f 100644 --- a/src/test/ui/anon-params-denied-2018.stderr +++ b/src/test/ui/anon-params-denied-2018.stderr @@ -2,13 +2,21 @@ error: expected one of `:` or `@`, found `)` --> $DIR/anon-params-denied-2018.rs:6:15 | LL | fn foo(i32); //~ expected one of `:` or `@`, found `)` - | ^ expected one of `:` or `@` here + | ---^ expected one of `:` or `@` here + | | + | help: explicitly ignore parameter: `_: i32` + | + = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) error: expected one of `:` or `@`, found `,` --> $DIR/anon-params-denied-2018.rs:8:36 | LL | fn bar_with_default_impl(String, String) {} - | ^ expected one of `:` or `@` here + | ------^ expected one of `:` or `@` here + | | + | help: explicitly ignore parameter: `_: String` + | + = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) error: aborting due to 2 previous errors diff --git a/src/test/compile-fail-fulldeps/auxiliary/pub_and_stability.rs b/src/test/ui/auxiliary/pub_and_stability.rs similarity index 100% rename from src/test/compile-fail-fulldeps/auxiliary/pub_and_stability.rs rename to src/test/ui/auxiliary/pub_and_stability.rs diff --git a/src/test/compile-fail-fulldeps/auxiliary/use_from_trait_xc.rs b/src/test/ui/auxiliary/use_from_trait_xc.rs similarity index 100% rename from src/test/compile-fail-fulldeps/auxiliary/use_from_trait_xc.rs rename to src/test/ui/auxiliary/use_from_trait_xc.rs diff --git a/src/test/ui/borrowck/borrowck-anon-fields-variant.nll.stderr b/src/test/ui/borrowck/borrowck-anon-fields-variant.nll.stderr index 17722bf226d..5ea0ce5ba41 100644 --- a/src/test/ui/borrowck/borrowck-anon-fields-variant.nll.stderr +++ b/src/test/ui/borrowck/borrowck-anon-fields-variant.nll.stderr @@ -1,3 +1,30 @@ +warning[E0503]: cannot use `y` because it was mutably borrowed + --> $DIR/borrowck-anon-fields-variant.rs:27:7 + | +LL | Foo::Y(ref mut a, _) => a, + | --------- borrow of `y.0` occurs here +... +LL | Foo::Y(_, ref mut b) => b, + | ^^^^^^^^^^^^^^^^^^^^ use of borrowed `y.0` +... +LL | *a += 1; + | ------- borrow later used here + | + = warning: this error has been downgraded to a warning for backwards compatibility with previous releases + = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future + +error[E0503]: cannot use `y` because it was mutably borrowed + --> $DIR/borrowck-anon-fields-variant.rs:44:7 + | +LL | Foo::Y(ref mut a, _) => a, + | --------- borrow of `y.0` occurs here +... +LL | Foo::Y(ref mut b, _) => b, //~ ERROR cannot borrow + | ^^^^^^^^^^^^^^^^^^^^ use of borrowed `y.0` +... +LL | *a += 1; + | ------- borrow later used here + error[E0499]: cannot borrow `y.0` as mutable more than once at a time --> $DIR/borrowck-anon-fields-variant.rs:44:14 | @@ -10,6 +37,7 @@ LL | Foo::Y(ref mut b, _) => b, //~ ERROR cannot borrow LL | *a += 1; | ------- first borrow later used here -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0499`. +Some errors occurred: E0499, E0503. +For more information about an error, try `rustc --explain E0499`. diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.ast.nll.stderr b/src/test/ui/borrowck/borrowck-describe-lvalue.ast.nll.stderr index c3aba793f19..3c457bff7cf 100644 --- a/src/test/ui/borrowck/borrowck-describe-lvalue.ast.nll.stderr +++ b/src/test/ui/borrowck/borrowck-describe-lvalue.ast.nll.stderr @@ -350,9 +350,8 @@ LL | let p: &'a u8 = &*block.current; LL | drop(x); | - mutable borrow later used here | - = warning: This error has been downgraded to a warning for backwards compatibility with previous releases. - It represents potential unsoundness in your code. - This warning will become a hard error in the future. + = warning: this error has been downgraded to a warning for backwards compatibility with previous releases + = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future warning[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable --> $DIR/borrowck-describe-lvalue.rs:260:33 @@ -365,9 +364,8 @@ LL | let p : *const u8 = &*(*block).current; LL | drop(x); | - mutable borrow later used here | - = warning: This error has been downgraded to a warning for backwards compatibility with previous releases. - It represents potential unsoundness in your code. - This warning will become a hard error in the future. + = warning: this error has been downgraded to a warning for backwards compatibility with previous releases + = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future error[E0382]: use of moved value: `x` --> $DIR/borrowck-describe-lvalue.rs:318:22 diff --git a/src/test/ui/borrowck/borrowck-insert-during-each.nll.stderr b/src/test/ui/borrowck/borrowck-insert-during-each.nll.stderr index 123d475f1c0..84fc69465cb 100644 --- a/src/test/ui/borrowck/borrowck-insert-during-each.nll.stderr +++ b/src/test/ui/borrowck/borrowck-insert-during-each.nll.stderr @@ -10,7 +10,7 @@ LL | | |a| { //~ ERROR closure requires unique access to `f` LL | | f.n.insert(*a); | | - first borrow occurs due to use of `f` in closure LL | | }) - | |__________^ borrow occurs here + | |__________^ second borrow occurs here error[E0500]: closure requires unique access to `f` but it is already borrowed --> $DIR/borrowck-insert-during-each.rs:27:9 diff --git a/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr b/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr index e7dbc6f6e3b..032b8ddcbca 100644 --- a/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr +++ b/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr @@ -4,7 +4,6 @@ warning[E0507]: cannot move out of borrowed content LL | (|| { let bar = foo; bar.take() })(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content | - = warning: This error has been downgraded to a warning for backwards compatibility with previous releases. - It represents potential unsoundness in your code. - This warning will become a hard error in the future. + = warning: this error has been downgraded to a warning for backwards compatibility with previous releases + = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future diff --git a/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr b/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr index e7dbc6f6e3b..032b8ddcbca 100644 --- a/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr +++ b/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr @@ -4,7 +4,6 @@ warning[E0507]: cannot move out of borrowed content LL | (|| { let bar = foo; bar.take() })(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content | - = warning: This error has been downgraded to a warning for backwards compatibility with previous releases. - It represents potential unsoundness in your code. - This warning will become a hard error in the future. + = warning: this error has been downgraded to a warning for backwards compatibility with previous releases + = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future diff --git a/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs b/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs index 30752e8ddb1..fd4c108b594 100644 --- a/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs +++ b/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs @@ -49,7 +49,7 @@ fn deref_coercion(x: &mut u32) { // // - [x] Resolving overloaded_call_traits (call, call_mut, call_once) // - [x] deref_coercion (shown above) -// - [x] coerce_unsized e.g. `&[T; n]`, `&mut [T; n] -> &[T]`, +// - [x] coerce_unsized e.g., `&[T; n]`, `&mut [T; n] -> &[T]`, // `&mut [T; n] -> &mut [T]`, `&Concrete -> &Trait` // - [x] Method Call Receivers (the case we want to support!) // - [x] ExprKind::Index and ExprKind::Unary Deref; only need to handle coerce_index_op diff --git a/src/test/ui/coercion/coerce-issue-49593-box-never.rs b/src/test/ui/coercion/coerce-issue-49593-box-never.rs new file mode 100644 index 00000000000..bea8586452e --- /dev/null +++ b/src/test/ui/coercion/coerce-issue-49593-box-never.rs @@ -0,0 +1,62 @@ +// 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. + +// compile-pass + +#![feature(never_type)] +#![allow(unreachable_code)] + +use std::error::Error; +use std::mem; + +fn raw_ptr_box(t: T) -> *mut T { + panic!() +} + +fn foo(x: !) -> Box { + /* *mut $0 is coerced to Box here */ Box::<_ /* ! */>::new(x) +} + +fn foo_raw_ptr(x: !) -> *mut dyn Error { + /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x) +} + +fn no_coercion(d: *mut dyn Error) -> *mut dyn Error { + /* an unsize coercion won't compile here, and it is indeed not used + because there is nothing requiring the _ to be Sized */ + d as *mut _ +} + +trait Xyz {} +struct S; +struct T; +impl Xyz for S {} +impl Xyz for T {} + +fn foo_no_never() { + let mut x /* : Option */ = None; + let mut first_iter = false; + loop { + if !first_iter { + let y: Box + = /* Box<$0> is coerced to Box here */ Box::new(x.unwrap()); + } + + x = Some(S); + first_iter = true; + } + + let mut y : Option = None; + // assert types are equal + mem::swap(&mut x, &mut y); +} + +fn main() { +} diff --git a/src/test/ui/coherence/auxiliary/coherence_fundamental_trait_lib.rs b/src/test/ui/coherence/auxiliary/coherence_fundamental_trait_lib.rs new file mode 100644 index 00000000000..21aaea47963 --- /dev/null +++ b/src/test/ui/coherence/auxiliary/coherence_fundamental_trait_lib.rs @@ -0,0 +1,7 @@ +#![crate_type = "rlib"] +#![feature(fundamental)] + +pub trait Misc {} + +#[fundamental] +pub trait Fundamental {} diff --git a/src/test/ui/coherence/coherence-all-remote.stderr b/src/test/ui/coherence/coherence-all-remote.stderr index 1f71969989b..718ab3dedc4 100644 --- a/src/test/ui/coherence/coherence-all-remote.stderr +++ b/src/test/ui/coherence/coherence-all-remote.stderr @@ -1,4 +1,4 @@ -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g. `MyStruct`) +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) --> $DIR/coherence-all-remote.rs:16:1 | LL | impl Remote1 for isize { } diff --git a/src/test/ui/coherence/coherence-bigint-param.stderr b/src/test/ui/coherence/coherence-bigint-param.stderr index 7d2796ee690..a5d9f5a403f 100644 --- a/src/test/ui/coherence/coherence-bigint-param.stderr +++ b/src/test/ui/coherence/coherence-bigint-param.stderr @@ -1,4 +1,4 @@ -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g. `MyStruct`) +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) --> $DIR/coherence-bigint-param.rs:18:1 | LL | impl Remote1 for T { } diff --git a/src/test/ui/coherence/coherence-cow.a.stderr b/src/test/ui/coherence/coherence-cow.a.stderr index f05333348ec..368935f4cfb 100644 --- a/src/test/ui/coherence/coherence-cow.a.stderr +++ b/src/test/ui/coherence/coherence-cow.a.stderr @@ -1,4 +1,4 @@ -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g. `MyStruct`) +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) --> $DIR/coherence-cow.rs:26:1 | LL | impl Remote for Pair> { } //[a]~ ERROR E0210 diff --git a/src/test/ui/coherence/coherence-cow.b.stderr b/src/test/ui/coherence/coherence-cow.b.stderr index 269bcd576af..74ad8502add 100644 --- a/src/test/ui/coherence/coherence-cow.b.stderr +++ b/src/test/ui/coherence/coherence-cow.b.stderr @@ -1,4 +1,4 @@ -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g. `MyStruct`) +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) --> $DIR/coherence-cow.rs:29:1 | LL | impl Remote for Pair,T> { } //[b]~ ERROR E0210 diff --git a/src/test/ui/coherence/coherence-cow.c.stderr b/src/test/ui/coherence/coherence-cow.c.stderr index e89308db054..2e3a6b54e84 100644 --- a/src/test/ui/coherence/coherence-cow.c.stderr +++ b/src/test/ui/coherence/coherence-cow.c.stderr @@ -1,4 +1,4 @@ -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g. `MyStruct`) +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) --> $DIR/coherence-cow.rs:32:1 | LL | impl Remote for Pair,U> { } diff --git a/src/test/ui/coherence/coherence-cross-crate-conflict.stderr b/src/test/ui/coherence/coherence-cross-crate-conflict.stderr index ee11967cc0d..31c41ab7234 100644 --- a/src/test/ui/coherence/coherence-cross-crate-conflict.stderr +++ b/src/test/ui/coherence/coherence-cross-crate-conflict.stderr @@ -7,7 +7,7 @@ LL | impl Foo for A { = note: conflicting implementation in crate `trait_impl_conflict`: - impl trait_impl_conflict::Foo for isize; -error[E0210]: type parameter `A` must be used as the type parameter for some local type (e.g. `MyStruct`) +error[E0210]: type parameter `A` must be used as the type parameter for some local type (e.g., `MyStruct`) --> $DIR/coherence-cross-crate-conflict.rs:18:1 | LL | impl Foo for A { diff --git a/src/test/ui/coherence/coherence-fundamental-trait-objects.rs b/src/test/ui/coherence/coherence-fundamental-trait-objects.rs new file mode 100644 index 00000000000..dd127bf7f4b --- /dev/null +++ b/src/test/ui/coherence/coherence-fundamental-trait-objects.rs @@ -0,0 +1,15 @@ +// Check that trait objects from #[fundamental] traits are not +// treated as #[fundamental] types - the 2 meanings of #[fundamental] +// are distinct. + +// aux-build:coherence_fundamental_trait_lib.rs + +extern crate coherence_fundamental_trait_lib; + +use coherence_fundamental_trait_lib::{Fundamental, Misc}; + +pub struct Local; +impl Misc for dyn Fundamental {} +//~^ ERROR E0117 + +fn main() {} diff --git a/src/test/ui/coherence/coherence-fundamental-trait-objects.stderr b/src/test/ui/coherence/coherence-fundamental-trait-objects.stderr new file mode 100644 index 00000000000..cefcac2c517 --- /dev/null +++ b/src/test/ui/coherence/coherence-fundamental-trait-objects.stderr @@ -0,0 +1,12 @@ +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence-fundamental-trait-objects.rs:12:1 + | +LL | impl Misc for dyn Fundamental {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate + | + = note: the impl does not reference any types defined in this crate + = note: define and implement a trait or new type instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0117`. diff --git a/src/test/ui/coherence/coherence-lone-type-parameter.stderr b/src/test/ui/coherence/coherence-lone-type-parameter.stderr index 6389bc0e7ab..e3a77229634 100644 --- a/src/test/ui/coherence/coherence-lone-type-parameter.stderr +++ b/src/test/ui/coherence/coherence-lone-type-parameter.stderr @@ -1,4 +1,4 @@ -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g. `MyStruct`) +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) --> $DIR/coherence-lone-type-parameter.rs:16:1 | LL | impl Remote for T { } diff --git a/src/test/ui/coherence/coherence-overlapping-pairs.stderr b/src/test/ui/coherence/coherence-overlapping-pairs.stderr index 41d47888554..286ebefba15 100644 --- a/src/test/ui/coherence/coherence-overlapping-pairs.stderr +++ b/src/test/ui/coherence/coherence-overlapping-pairs.stderr @@ -1,4 +1,4 @@ -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g. `MyStruct`) +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) --> $DIR/coherence-overlapping-pairs.rs:18:1 | LL | impl Remote for lib::Pair { } diff --git a/src/test/ui/coherence/coherence-pair-covered-uncovered-1.stderr b/src/test/ui/coherence/coherence-pair-covered-uncovered-1.stderr index 3545593fb6d..80ab0cc09f9 100644 --- a/src/test/ui/coherence/coherence-pair-covered-uncovered-1.stderr +++ b/src/test/ui/coherence/coherence-pair-covered-uncovered-1.stderr @@ -1,4 +1,4 @@ -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g. `MyStruct`) +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) --> $DIR/coherence-pair-covered-uncovered-1.rs:21:1 | LL | impl Remote1>> for i32 { } diff --git a/src/test/ui/coherence/coherence-pair-covered-uncovered.stderr b/src/test/ui/coherence/coherence-pair-covered-uncovered.stderr index f58cb4648cb..25b4948e083 100644 --- a/src/test/ui/coherence/coherence-pair-covered-uncovered.stderr +++ b/src/test/ui/coherence/coherence-pair-covered-uncovered.stderr @@ -1,4 +1,4 @@ -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g. `MyStruct`) +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) --> $DIR/coherence-pair-covered-uncovered.rs:18:1 | LL | impl Remote for Pair> { } diff --git a/src/test/ui/coherence/coherence-vec-local-2.stderr b/src/test/ui/coherence/coherence-vec-local-2.stderr index 2980d4a3392..0ccd938e900 100644 --- a/src/test/ui/coherence/coherence-vec-local-2.stderr +++ b/src/test/ui/coherence/coherence-vec-local-2.stderr @@ -1,4 +1,4 @@ -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g. `MyStruct`) +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) --> $DIR/coherence-vec-local-2.rs:21:1 | LL | impl Remote for Vec> { } //~ ERROR E0210 diff --git a/src/test/ui/conflicting-repr-hints.rs b/src/test/ui/conflicting-repr-hints.rs index 426f60c6b09..f16bd1003f9 100644 --- a/src/test/ui/conflicting-repr-hints.rs +++ b/src/test/ui/conflicting-repr-hints.rs @@ -9,7 +9,6 @@ // except according to those terms. #![allow(dead_code)] -#![feature(repr_packed)] #[repr(C)] enum A { A } diff --git a/src/test/ui/conflicting-repr-hints.stderr b/src/test/ui/conflicting-repr-hints.stderr index 7a4e5a5488a..01b72d93823 100644 --- a/src/test/ui/conflicting-repr-hints.stderr +++ b/src/test/ui/conflicting-repr-hints.stderr @@ -1,47 +1,47 @@ warning[E0566]: conflicting representation hints - --> $DIR/conflicting-repr-hints.rs:20:8 + --> $DIR/conflicting-repr-hints.rs:19:8 | LL | #[repr(C, u64)] //~ WARNING conflicting representation hints | ^ ^^^ warning[E0566]: conflicting representation hints - --> $DIR/conflicting-repr-hints.rs:23:8 + --> $DIR/conflicting-repr-hints.rs:22:8 | LL | #[repr(u32, u64)] //~ WARNING conflicting representation hints | ^^^ ^^^ error[E0587]: type has conflicting packed and align representation hints - --> $DIR/conflicting-repr-hints.rs:30:1 + --> $DIR/conflicting-repr-hints.rs:29:1 | LL | struct F(i32); //~ ERROR type has conflicting packed and align representation hints | ^^^^^^^^^^^^^^ error[E0587]: type has conflicting packed and align representation hints - --> $DIR/conflicting-repr-hints.rs:34:1 + --> $DIR/conflicting-repr-hints.rs:33:1 | LL | struct G(i32); //~ ERROR type has conflicting packed and align representation hints | ^^^^^^^^^^^^^^ error[E0587]: type has conflicting packed and align representation hints - --> $DIR/conflicting-repr-hints.rs:38:1 + --> $DIR/conflicting-repr-hints.rs:37:1 | LL | struct H(i32); //~ ERROR type has conflicting packed and align representation hints | ^^^^^^^^^^^^^^ error[E0634]: type has conflicting packed representation hints - --> $DIR/conflicting-repr-hints.rs:41:1 + --> $DIR/conflicting-repr-hints.rs:40:1 | LL | struct I(i32); //~ ERROR type has conflicting packed representation hints | ^^^^^^^^^^^^^^ error[E0634]: type has conflicting packed representation hints - --> $DIR/conflicting-repr-hints.rs:45:1 + --> $DIR/conflicting-repr-hints.rs:44:1 | LL | struct J(i32); //~ ERROR type has conflicting packed representation hints | ^^^^^^^^^^^^^^ error[E0587]: type has conflicting packed and align representation hints - --> $DIR/conflicting-repr-hints.rs:51:1 + --> $DIR/conflicting-repr-hints.rs:50:1 | LL | / union X { //~ ERROR type has conflicting packed and align representation hints LL | | i: i32 @@ -49,7 +49,7 @@ LL | | } | |_^ error[E0587]: type has conflicting packed and align representation hints - --> $DIR/conflicting-repr-hints.rs:57:1 + --> $DIR/conflicting-repr-hints.rs:56:1 | LL | / union Y { //~ ERROR type has conflicting packed and align representation hints LL | | i: i32 @@ -57,7 +57,7 @@ LL | | } | |_^ error[E0587]: type has conflicting packed and align representation hints - --> $DIR/conflicting-repr-hints.rs:63:1 + --> $DIR/conflicting-repr-hints.rs:62:1 | LL | / union Z { //~ ERROR type has conflicting packed and align representation hints LL | | i: i32 diff --git a/src/test/ui/constructor-lifetime-args.rs b/src/test/ui/constructor-lifetime-args.rs index 1fe50cfebba..a03599ada1c 100644 --- a/src/test/ui/constructor-lifetime-args.rs +++ b/src/test/ui/constructor-lifetime-args.rs @@ -9,7 +9,7 @@ // except according to those terms. // All lifetime parameters in struct constructors are currently considered early bound, -// i.e. `S::` is interpreted kinda like an associated item `S::::ctor`. +// i.e., `S::` is interpreted kinda like an associated item `S::::ctor`. // This behavior is a bit weird, because if equivalent constructor were written manually // it would get late bound lifetime parameters. // Variant constructors behave in the same way, lifetime parameters are considered diff --git a/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs b/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs index ef0de61d219..63e5bcccf5d 100644 --- a/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs +++ b/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs @@ -24,7 +24,7 @@ unsafe impl Sync for Foo {} static FOO: Foo = Foo(UnsafeCell::new(42)); static BAR: () = unsafe { - *FOO.0.get() = 5; //~ ERROR could not evaluate static initializer + *FOO.0.get() = 5; //~ ERROR contains unimplemented expression type }; fn main() {} diff --git a/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr b/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr index 0892b05a69d..740954c6c66 100644 --- a/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr +++ b/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr @@ -1,9 +1,9 @@ -error[E0080]: could not evaluate static initializer +error[E0019]: static contains unimplemented expression type --> $DIR/assign-to-static-within-other-static-2.rs:27:5 | -LL | *FOO.0.get() = 5; //~ ERROR could not evaluate static initializer - | ^^^^^^^^^^^^^^^^ tried to modify a static's initial value from another static's initializer +LL | *FOO.0.get() = 5; //~ ERROR contains unimplemented expression type + | ^^^^^^^^^^^^^^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0080`. +For more information about this error, try `rustc --explain E0019`. diff --git a/src/test/ui/consts/const-eval/const-eval-overflow2.rs b/src/test/ui/consts/const-eval/const-eval-overflow2.rs index 8e094a7f7dc..7819cafdb0f 100644 --- a/src/test/ui/consts/const-eval/const-eval-overflow2.rs +++ b/src/test/ui/consts/const-eval/const-eval-overflow2.rs @@ -11,7 +11,7 @@ #![allow(unused_imports)] // Note: the relevant lint pass here runs before some of the constant -// evaluation below (e.g. that performed by codegen and llvm), so if you +// evaluation below (e.g., that performed by codegen and llvm), so if you // change this warn to a deny, then the compiler will exit before // those errors are detected. diff --git a/src/test/ui/consts/const-eval/const-eval-overflow2b.rs b/src/test/ui/consts/const-eval/const-eval-overflow2b.rs index c69d03071e7..475a5117685 100644 --- a/src/test/ui/consts/const-eval/const-eval-overflow2b.rs +++ b/src/test/ui/consts/const-eval/const-eval-overflow2b.rs @@ -11,7 +11,7 @@ #![allow(unused_imports)] // Note: the relevant lint pass here runs before some of the constant -// evaluation below (e.g. that performed by codegen and llvm), so if you +// evaluation below (e.g., that performed by codegen and llvm), so if you // change this warn to a deny, then the compiler will exit before // those errors are detected. diff --git a/src/test/ui/consts/const-eval/const-eval-overflow2c.rs b/src/test/ui/consts/const-eval/const-eval-overflow2c.rs index f442661ec63..039e6b251cd 100644 --- a/src/test/ui/consts/const-eval/const-eval-overflow2c.rs +++ b/src/test/ui/consts/const-eval/const-eval-overflow2c.rs @@ -11,7 +11,7 @@ #![allow(unused_imports)] // Note: the relevant lint pass here runs before some of the constant -// evaluation below (e.g. that performed by codegen and llvm), so if you +// evaluation below (e.g., that performed by codegen and llvm), so if you // change this warn to a deny, then the compiler will exit before // those errors are detected. diff --git a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.nll.stderr b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.nll.stderr index 8c4806cddfe..d1250b9b5c0 100644 --- a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.nll.stderr +++ b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.nll.stderr @@ -4,7 +4,7 @@ error: `foo` is not yet stable as a const fn LL | const fn bar() -> u32 { foo() } //~ ERROR `foo` is not yet stable as a const fn | ^^^^^ | - = help: in Nightly builds, add `#![feature(foo)]` to the crate attributes to enable + = help: add `#![feature(foo)]` to the crate attributes to enable error[E0716]: temporary value dropped while borrowed --> $DIR/dont_promote_unstable_const_fn.rs:28:28 diff --git a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr index b3d7ba3e5c4..85b63f5c471 100644 --- a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr +++ b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr @@ -4,7 +4,7 @@ error: `foo` is not yet stable as a const fn LL | const fn bar() -> u32 { foo() } //~ ERROR `foo` is not yet stable as a const fn | ^^^^^ | - = help: in Nightly builds, add `#![feature(foo)]` to the crate attributes to enable + = help: add `#![feature(foo)]` to the crate attributes to enable error[E0597]: borrowed value does not live long enough --> $DIR/dont_promote_unstable_const_fn.rs:28:28 diff --git a/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs b/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs index 01fcc8307c0..6c2fdcc8615 100644 --- a/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs +++ b/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs @@ -27,9 +27,7 @@ fn foo() {} static BAR: () = unsafe { *FOO.0.get() = 5; - // we do not error on the above access, because that is not detectable statically. Instead, - // const evaluation will error when trying to evaluate it. Due to the error below, we never even - // attempt to const evaluate `BAR`, so we don't see the error + //~^ contains unimplemented expression foo(); //~^ ERROR calls in statics are limited to constant functions, tuple structs and tuple variants diff --git a/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr b/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr index 01ad1fc9a21..49b39e2f5c6 100644 --- a/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr +++ b/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr @@ -1,9 +1,16 @@ +error[E0019]: static contains unimplemented expression type + --> $DIR/mod-static-with-const-fn.rs:29:5 + | +LL | *FOO.0.get() = 5; + | ^^^^^^^^^^^^^^^^ + error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants - --> $DIR/mod-static-with-const-fn.rs:34:5 + --> $DIR/mod-static-with-const-fn.rs:32:5 | LL | foo(); | ^^^^^ -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0015`. +Some errors occurred: E0015, E0019. +For more information about an error, try `rustc --explain E0015`. diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.rs b/src/test/ui/consts/const-eval/ub-uninhabit.rs index 74713af2ea0..42cba02f579 100644 --- a/src/test/ui/consts/const-eval/ub-uninhabit.rs +++ b/src/test/ui/consts/const-eval/ub-uninhabit.rs @@ -1,13 +1,3 @@ -// 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(const_transmute)] #![allow(const_err)] // make sure we cannot allow away the errors tested here @@ -16,14 +6,18 @@ use std::mem; #[derive(Copy, Clone)] enum Bar {} -const BAD_BAD_BAD: Bar = unsafe { mem::transmute(()) }; +union TransmuteUnion { + a: A, + b: B, +} + +const BAD_BAD_BAD: Bar = unsafe { (TransmuteUnion::<(), Bar> { a: () }).b }; //~^ ERROR it is undefined behavior to use this value const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; //~^ ERROR it is undefined behavior to use this value -const BAD_BAD_ARRAY: [Bar; 1] = unsafe { mem::transmute(()) }; +const BAD_BAD_ARRAY: [Bar; 1] = unsafe { (TransmuteUnion::<(), [Bar; 1]> { a: () }).b }; //~^ ERROR it is undefined behavior to use this value -fn main() { -} +fn main() {} diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.stderr b/src/test/ui/consts/const-eval/ub-uninhabit.stderr index c5ac72b639c..c8842ecc23c 100644 --- a/src/test/ui/consts/const-eval/ub-uninhabit.stderr +++ b/src/test/ui/consts/const-eval/ub-uninhabit.stderr @@ -1,13 +1,13 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-uninhabit.rs:19:1 + --> $DIR/ub-uninhabit.rs:14:1 | -LL | const BAD_BAD_BAD: Bar = unsafe { mem::transmute(()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type +LL | const BAD_BAD_BAD: Bar = unsafe { (TransmuteUnion::<(), Bar> { a: () }).b }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-uninhabit.rs:22:1 + --> $DIR/ub-uninhabit.rs:17:1 | LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at . @@ -15,10 +15,10 @@ LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-uninhabit.rs:25:1 + --> $DIR/ub-uninhabit.rs:20:1 | -LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { mem::transmute(()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at [0] +LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { (TransmuteUnion::<(), [Bar; 1]> { a: () }).b }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior diff --git a/src/test/ui/consts/const-fn-not-safe-for-const.rs b/src/test/ui/consts/const-fn-not-safe-for-const.rs index 30a738a83a3..2f7e2ecaa4e 100644 --- a/src/test/ui/consts/const-fn-not-safe-for-const.rs +++ b/src/test/ui/consts/const-fn-not-safe-for-const.rs @@ -37,15 +37,13 @@ const fn get_Y_addr() -> &'static u32 { } const fn get() -> u32 { - let x = 22; - //~^ ERROR let bindings in constant functions are unstable - //~| ERROR statements in constant functions are unstable - let y = 44; - //~^ ERROR let bindings in constant functions are unstable - //~| ERROR statements in constant functions are unstable + let x = 22; //~ ERROR let bindings in constant functions are unstable +//~^ ERROR statements in constant functions + let y = 44; //~ ERROR let bindings in constant functions are unstable +//~^ ERROR statements in constant functions x + y - //~^ ERROR let bindings in constant functions are unstable - //~| ERROR let bindings in constant functions are unstable +//~^ ERROR let bindings in constant functions are unstable +//~| ERROR let bindings in constant functions are unstable } fn main() {} diff --git a/src/test/ui/consts/const-fn-not-safe-for-const.stderr b/src/test/ui/consts/const-fn-not-safe-for-const.stderr index 613670acc93..1a8c5f558a2 100644 --- a/src/test/ui/consts/const-fn-not-safe-for-const.stderr +++ b/src/test/ui/consts/const-fn-not-safe-for-const.stderr @@ -19,7 +19,7 @@ LL | &Y error[E0658]: let bindings in constant functions are unstable (see issue #48821) --> $DIR/const-fn-not-safe-for-const.rs:40:13 | -LL | let x = 22; +LL | let x = 22; //~ ERROR let bindings in constant functions are unstable | ^^ | = help: add #![feature(const_let)] to the crate attributes to enable @@ -27,29 +27,29 @@ LL | let x = 22; error[E0658]: statements in constant functions are unstable (see issue #48821) --> $DIR/const-fn-not-safe-for-const.rs:40:13 | -LL | let x = 22; +LL | let x = 22; //~ ERROR let bindings in constant functions are unstable | ^^ | = help: add #![feature(const_let)] to the crate attributes to enable error[E0658]: let bindings in constant functions are unstable (see issue #48821) - --> $DIR/const-fn-not-safe-for-const.rs:43:13 + --> $DIR/const-fn-not-safe-for-const.rs:42:13 | -LL | let y = 44; +LL | let y = 44; //~ ERROR let bindings in constant functions are unstable | ^^ | = help: add #![feature(const_let)] to the crate attributes to enable error[E0658]: statements in constant functions are unstable (see issue #48821) - --> $DIR/const-fn-not-safe-for-const.rs:43:13 + --> $DIR/const-fn-not-safe-for-const.rs:42:13 | -LL | let y = 44; +LL | let y = 44; //~ ERROR let bindings in constant functions are unstable | ^^ | = help: add #![feature(const_let)] to the crate attributes to enable error[E0658]: let bindings in constant functions are unstable (see issue #48821) - --> $DIR/const-fn-not-safe-for-const.rs:46:5 + --> $DIR/const-fn-not-safe-for-const.rs:44:5 | LL | x + y | ^ @@ -57,7 +57,7 @@ LL | x + y = help: add #![feature(const_let)] to the crate attributes to enable error[E0658]: let bindings in constant functions are unstable (see issue #48821) - --> $DIR/const-fn-not-safe-for-const.rs:46:9 + --> $DIR/const-fn-not-safe-for-const.rs:44:9 | LL | x + y | ^ diff --git a/src/test/ui/consts/const-match-check.eval1.stderr b/src/test/ui/consts/const-match-check.eval1.stderr index 3caf1491aba..703453e6bdd 100644 --- a/src/test/ui/consts/const-match-check.eval1.stderr +++ b/src/test/ui/consts/const-match-check.eval1.stderr @@ -1,8 +1,8 @@ -error[E0005]: refutable pattern in local binding: `_` not covered +error[E0005]: refutable pattern in local binding: `-2147483648i32..=-1i32` not covered --> $DIR/const-match-check.rs:35:15 | LL | A = { let 0 = 0; 0 }, - | ^ pattern `_` not covered + | ^ pattern `-2147483648i32..=-1i32` not covered error: aborting due to previous error diff --git a/src/test/ui/consts/const-match-check.eval2.stderr b/src/test/ui/consts/const-match-check.eval2.stderr index de85d4d73db..6caff93e642 100644 --- a/src/test/ui/consts/const-match-check.eval2.stderr +++ b/src/test/ui/consts/const-match-check.eval2.stderr @@ -1,8 +1,8 @@ -error[E0005]: refutable pattern in local binding: `_` not covered +error[E0005]: refutable pattern in local binding: `-2147483648i32..=-1i32` not covered --> $DIR/const-match-check.rs:41:24 | LL | let x: [i32; { let 0 = 0; 0 }] = []; - | ^ pattern `_` not covered + | ^ pattern `-2147483648i32..=-1i32` not covered error: aborting due to previous error diff --git a/src/test/ui/consts/const-match-check.matchck.stderr b/src/test/ui/consts/const-match-check.matchck.stderr index bbf1169c577..9e45045d27e 100644 --- a/src/test/ui/consts/const-match-check.matchck.stderr +++ b/src/test/ui/consts/const-match-check.matchck.stderr @@ -1,26 +1,26 @@ -error[E0005]: refutable pattern in local binding: `_` not covered +error[E0005]: refutable pattern in local binding: `-2147483648i32..=-1i32` not covered --> $DIR/const-match-check.rs:14:22 | LL | const X: i32 = { let 0 = 0; 0 }; - | ^ pattern `_` not covered + | ^ pattern `-2147483648i32..=-1i32` not covered -error[E0005]: refutable pattern in local binding: `_` not covered +error[E0005]: refutable pattern in local binding: `-2147483648i32..=-1i32` not covered --> $DIR/const-match-check.rs:18:23 | LL | static Y: i32 = { let 0 = 0; 0 }; - | ^ pattern `_` not covered + | ^ pattern `-2147483648i32..=-1i32` not covered -error[E0005]: refutable pattern in local binding: `_` not covered +error[E0005]: refutable pattern in local binding: `-2147483648i32..=-1i32` not covered --> $DIR/const-match-check.rs:23:26 | LL | const X: i32 = { let 0 = 0; 0 }; - | ^ pattern `_` not covered + | ^ pattern `-2147483648i32..=-1i32` not covered -error[E0005]: refutable pattern in local binding: `_` not covered +error[E0005]: refutable pattern in local binding: `-2147483648i32..=-1i32` not covered --> $DIR/const-match-check.rs:29:26 | LL | const X: i32 = { let 0 = 0; 0 }; - | ^ pattern `_` not covered + | ^ pattern `-2147483648i32..=-1i32` not covered error: aborting due to 4 previous errors diff --git a/src/test/ui/consts/const-pattern-irrefutable.rs b/src/test/ui/consts/const-pattern-irrefutable.rs index af0b95e002d..2f08d124848 100644 --- a/src/test/ui/consts/const-pattern-irrefutable.rs +++ b/src/test/ui/consts/const-pattern-irrefutable.rs @@ -19,8 +19,8 @@ use foo::d; const a: u8 = 2; fn main() { - let a = 4; //~ ERROR refutable pattern in local binding: `_` not covered - let c = 4; //~ ERROR refutable pattern in local binding: `_` not covered - let d = 4; //~ ERROR refutable pattern in local binding: `_` not covered - fn f() {} // Check that the `NOTE`s still work with an item here (c.f. issue #35115). + let a = 4; //~ ERROR refutable pattern in local binding: `0u8..=1u8` not covered + let c = 4; //~ ERROR refutable pattern in local binding: `0u8..=1u8` not covered + let d = 4; //~ ERROR refutable pattern in local binding: `0u8..=1u8` not covered + fn f() {} // Check that the `NOTE`s still work with an item here (cf. issue #35115). } diff --git a/src/test/ui/consts/const-pattern-irrefutable.stderr b/src/test/ui/consts/const-pattern-irrefutable.stderr index 6d5738f3328..d9ad16cd0e8 100644 --- a/src/test/ui/consts/const-pattern-irrefutable.stderr +++ b/src/test/ui/consts/const-pattern-irrefutable.stderr @@ -1,19 +1,19 @@ -error[E0005]: refutable pattern in local binding: `_` not covered +error[E0005]: refutable pattern in local binding: `0u8..=1u8` not covered --> $DIR/const-pattern-irrefutable.rs:22:9 | -LL | let a = 4; //~ ERROR refutable pattern in local binding: `_` not covered +LL | let a = 4; //~ ERROR refutable pattern in local binding: `0u8..=1u8` not covered | ^ interpreted as a constant pattern, not new variable -error[E0005]: refutable pattern in local binding: `_` not covered +error[E0005]: refutable pattern in local binding: `0u8..=1u8` not covered --> $DIR/const-pattern-irrefutable.rs:23:9 | -LL | let c = 4; //~ ERROR refutable pattern in local binding: `_` not covered +LL | let c = 4; //~ ERROR refutable pattern in local binding: `0u8..=1u8` not covered | ^ interpreted as a constant pattern, not new variable -error[E0005]: refutable pattern in local binding: `_` not covered +error[E0005]: refutable pattern in local binding: `0u8..=1u8` not covered --> $DIR/const-pattern-irrefutable.rs:24:9 | -LL | let d = 4; //~ ERROR refutable pattern in local binding: `_` not covered +LL | let d = 4; //~ ERROR refutable pattern in local binding: `0u8..=1u8` not covered | ^ interpreted as a constant pattern, not new variable error: aborting due to 3 previous errors diff --git a/src/test/ui/consts/const-typeid-of.stderr b/src/test/ui/consts/const-typeid-of.stderr index d13ced9a10a..ba5f65988e2 100644 --- a/src/test/ui/consts/const-typeid-of.stderr +++ b/src/test/ui/consts/const-typeid-of.stderr @@ -4,7 +4,7 @@ error: `std::any::TypeId::of` is not yet stable as a const fn LL | const A_ID: TypeId = TypeId::of::(); | ^^^^^^^^^^^^^^^^^ | - = help: in Nightly builds, add `#![feature(const_type_id)]` to the crate attributes to enable + = help: add `#![feature(const_type_id)]` to the crate attributes to enable error: aborting due to previous error diff --git a/src/test/ui/consts/const_let_assign3.rs b/src/test/ui/consts/const_let_assign3.rs index 83825456b5c..c2ed6cd85ab 100644 --- a/src/test/ui/consts/const_let_assign3.rs +++ b/src/test/ui/consts/const_let_assign3.rs @@ -8,6 +8,7 @@ struct S { impl S { const fn foo(&mut self, x: u32) { self.state = x; + //~^ contains unimplemented expression } } diff --git a/src/test/ui/consts/const_let_assign3.stderr b/src/test/ui/consts/const_let_assign3.stderr index 7f9a953c10f..0f294616d25 100644 --- a/src/test/ui/consts/const_let_assign3.stderr +++ b/src/test/ui/consts/const_let_assign3.stderr @@ -1,9 +1,16 @@ +error[E0019]: constant function contains unimplemented expression type + --> $DIR/const_let_assign3.rs:10:9 + | +LL | self.state = x; + | ^^^^^^^^^^^^^^ + error[E0017]: references in constants may only refer to immutable values - --> $DIR/const_let_assign3.rs:16:5 + --> $DIR/const_let_assign3.rs:17:5 | LL | s.foo(3); //~ ERROR references in constants may only refer to immutable values | ^ constants require immutable values -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0017`. +Some errors occurred: E0017, E0019. +For more information about an error, try `rustc --explain E0017`. diff --git a/src/test/ui/consts/const_let_eq.rs b/src/test/ui/consts/const_let_eq.rs new file mode 100644 index 00000000000..8739cb80e94 --- /dev/null +++ b/src/test/ui/consts/const_let_eq.rs @@ -0,0 +1,470 @@ +#![feature(const_let, const_fn)] + +// run-pass + +struct Foo(T); +struct Bar { x: T } +struct W(u32); +struct A { a: u32 } + +const fn basics((a,): (u32,)) -> u32 { + // Deferred assignment: + let b: u32; + b = a + 1; + + // Immediate assignment: + let c: u32 = b + 1; + + // Mutables: + let mut d: u32 = c + 1; + d = d + 1; + // +4 so far. + + // No effect statements work: + ; ; + 1; + + // Array projection + let mut arr: [u32; 1] = [0]; + arr[0] = 1; + d = d + arr[0]; + // +5 + + // Field projection: + let mut foo: Foo = Foo(0); + let mut bar: Bar = Bar { x: 0 }; + foo.0 = 1; + bar.x = 1; + d = d + foo.0 + bar.x; + // +7 + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(0)]; + arr[0].0 = 1; + d = d + arr[0].0; + let mut arr: [Bar; 1] = [Bar { x: 0 }]; + arr[0].x = 1; + d = d + arr[0].x; + // +9 + + // Field + Array projection: + let mut arr: Foo<[u32; 1]> = Foo([0]); + (arr.0)[0] = 1; + d = d + (arr.0)[0]; + let mut arr: Bar<[u32; 1]> = Bar { x: [0] }; + arr.x[0] = 1; + d = d + arr.x[0]; + // +11 + + d +} + +const fn add_assign(W(a): W) -> u32 { + // Mutables: + let mut d: u32 = a + 1; + d += 1; + // +2 so far. + + // Array projection + let mut arr: [u32; 1] = [0]; + arr[0] += 1; + d += arr[0]; + // +3 + + // Field projection: + let mut foo: Foo = Foo(0); + let mut bar: Bar = Bar { x: 0 }; + foo.0 += 1; + bar.x += 1; + d += foo.0 + bar.x; + // +5 + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(0)]; + arr[0].0 += 1; + d += arr[0].0; + let mut arr: [Bar; 1] = [Bar { x: 0 }]; + arr[0].x += 1; + d += arr[0].x; + // +7 + + // Field + Array projection: + let mut arr: Foo<[u32; 1]> = Foo([0]); + (arr.0)[0] += 1; + d += (arr.0)[0]; + let mut arr: Bar<[u32; 1]> = Bar { x: [0] }; + arr.x[0] += 1; + d += arr.x[0]; + // +9 + + d +} + +const fn mul_assign(A { a }: A) -> u32 { + // Mutables: + let mut d: u32 = a + 1; + d *= 2; + // 2^1 * (a + 1) + + // Array projection + let mut arr: [u32; 1] = [1]; + arr[0] *= 2; + d *= arr[0]; + // 2^2 * (a + 1) + + // Field projection: + let mut foo: Foo = Foo(1); + let mut bar: Bar = Bar { x: 1 }; + foo.0 *= 2; + bar.x *= 2; + d *= foo.0 + bar.x; + // 2^4 * (a + 1) + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(1)]; + arr[0].0 *= 2; + d *= arr[0].0; + let mut arr: [Bar; 1] = [Bar { x: 1 }]; + arr[0].x *= 2; + d *= arr[0].x; + // 2^6 * (a + 1) + + // Field + Array projection: + let mut arr: Foo<[u32; 1]> = Foo([1]); + (arr.0)[0] *= 2; + d *= (arr.0)[0]; + let mut arr: Bar<[u32; 1]> = Bar { x: [1] }; + arr.x[0] *= 2; + d *= arr.x[0]; + // 2^8 * (a + 1) + + d +} + +const fn div_assign(a: [u32; 1]) -> u32 { + let a = a[0]; + // Mutables: + let mut d: u32 = 1024 * a; + d /= 2; + // 512 + + // Array projection + let mut arr: [u32; 1] = [4]; + arr[0] /= 2; + d /= arr[0]; + // 256 + + // Field projection: + let mut foo: Foo = Foo(4); + let mut bar: Bar = Bar { x: 4 }; + foo.0 /= 2; + bar.x /= 2; + d /= foo.0; + d /= bar.x; + // 64 + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(4)]; + arr[0].0 /= 2; + d /= arr[0].0; + let mut arr: [Bar; 1] = [Bar { x: 4 }]; + arr[0].x /= 2; + d /= arr[0].x; + // 16 + + // Field + Array projection: + let mut arr: Foo<[u32; 1]> = Foo([4]); + (arr.0)[0] /= 2; + d /= (arr.0)[0]; + let mut arr: Bar<[u32; 1]> = Bar { x: [4] }; + arr.x[0] /= 2; + d /= arr.x[0]; + // 4 + + d +} + +const fn rem_assign(W(a): W) -> u32 { + // Mutables: + let mut d: u32 = a; + d %= 10; + d += 10; + + // Array projection + let mut arr: [u32; 1] = [3]; + arr[0] %= 2; + d %= 9 + arr[0]; + d += 10; + + // Field projection: + let mut foo: Foo = Foo(5); + let mut bar: Bar = Bar { x: 7 }; + foo.0 %= 2; + bar.x %= 2; + d %= 8 + foo.0 + bar.x; + d += 10; + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(4)]; + arr[0].0 %= 3; + d %= 9 + arr[0].0; + d += 10; + let mut arr: [Bar; 1] = [Bar { x: 7 }]; + arr[0].x %= 3; + d %= 9 + arr[0].x; + d += 10; + + // Field + Array projection: + let mut arr: Foo<[u32; 1]> = Foo([6]); + (arr.0)[0] %= 5; + d %= 9 + (arr.0)[0]; + let mut arr: Bar<[u32; 1]> = Bar { x: [11] }; + arr.x[0] %= 5; + d %= 9 + arr.x[0]; + + d +} + +const fn sub_assign(W(a): W) -> u32 { + // Mutables: + let mut d: u32 = a; + d -= 1; + + // Array projection + let mut arr: [u32; 1] = [2]; + arr[0] -= 1; + d -= arr[0]; + + // Field projection: + let mut foo: Foo = Foo(2); + let mut bar: Bar = Bar { x: 2 }; + foo.0 -= 1; + bar.x -= 1; + d -= foo.0 + bar.x; + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(2)]; + arr[0].0 -= 1; + d -= arr[0].0; + let mut arr: [Bar; 1] = [Bar { x: 2 }]; + arr[0].x -= 1; + d -= arr[0].x; + + // Field + Array projection: + let mut arr: Foo<[u32; 1]> = Foo([2]); + (arr.0)[0] -= 1; + d -= (arr.0)[0]; + let mut arr: Bar<[u32; 1]> = Bar { x: [2] }; + arr.x[0] -= 1; + d -= arr.x[0]; + + d +} + +const fn shl_assign(W(a): W) -> u32 { + // Mutables: + let mut d: u32 = a; + d <<= 1; // 10 + + // Array projection + let mut arr: [u32; 1] = [1]; + arr[0] <<= 1; + d <<= arr[0]; // 10 << 2 + + // Field projection: + let mut foo: Foo = Foo(1); + let mut bar: Bar = Bar { x: 1 }; + foo.0 <<= 1; + bar.x <<= 1; + d <<= foo.0 + bar.x; // 1000 << 4 + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(1)]; + arr[0].0 <<= 1; + d <<= arr[0].0; // 1000_0000 << 2 + let mut arr: [Bar; 1] = [Bar { x: 1 }]; + arr[0].x <<= 1; + d <<= arr[0].x; // 1000_0000_00 << 2 + + // Field + Array projection: + let mut arr: Foo<[u32; 1]> = Foo([1]); + (arr.0)[0] <<= 1; + d <<= (arr.0)[0]; // 1000_0000_0000 << 2 + let mut arr: Bar<[u32; 1]> = Bar { x: [1] }; + arr.x[0] <<= 1; + d <<= arr.x[0]; // 1000_0000_0000_00 << 2 + + d +} + +const fn shr_assign(W(a): W) -> u32 { + // Mutables: + let mut d: u32 = a; + d >>= 1; // /= 2 + + // Array projection + let mut arr: [u32; 1] = [2]; + arr[0] >>= 1; + d >>= arr[0]; // /= 4 + + // Field projection: + let mut foo: Foo = Foo(2); + let mut bar: Bar = Bar { x: 2 }; + foo.0 >>= 1; + bar.x >>= 1; + d >>= foo.0 + bar.x; // /= 16 + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(2)]; + arr[0].0 >>= 1; + d >>= arr[0].0; // /= 32 + let mut arr: [Bar; 1] = [Bar { x: 2 }]; + arr[0].x >>= 1; + d >>= arr[0].x; // /= 64 + + // Field + Array projection: + let mut arr: Foo<[u32; 1]> = Foo([2]); + (arr.0)[0] >>= 1; + d >>= (arr.0)[0]; // /= 128 + let mut arr: Bar<[u32; 1]> = Bar { x: [2] }; + arr.x[0] >>= 1; + d >>= arr.x[0]; // /= 256 + + d +} + +const fn bit_and_assign(W(a): W) -> u32 { + let f = 0b1111_1111_1111_1111; + + // Mutables: + let mut d: u32 = a; + d &= 0b1111_1111_1111_1110; + + // Array projection + let mut arr: [u32; 1] = [f]; + arr[0] &= 0b1111_1111_1111_1101; + d &= arr[0]; + + // Field projection: + let mut foo: Foo = Foo(f); + let mut bar: Bar = Bar { x: f }; + foo.0 &= 0b1111_1111_1111_0111; + bar.x &= 0b1111_1111_1101_1111; + d &= foo.0 & bar.x; + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(f)]; + arr[0].0 &= 0b1111_1110_1111_1111; + d &= arr[0].0; + let mut arr: [Bar; 1] = [Bar { x: f }]; + arr[0].x &= 0b1111_1101_1111_1111; + d &= arr[0].x; + + // Field + Array projection: + let mut arr: Foo<[u32; 1]> = Foo([f]); + (arr.0)[0] &= 0b1011_1111_1111_1111; + d &= (arr.0)[0]; + let mut arr: Bar<[u32; 1]> = Bar { x: [f] }; + arr.x[0] &= 0b0111_1111_1111_1111; + d &= arr.x[0]; + + d +} + +const fn bit_or_assign(W(a): W) -> u32 { + let f = 0b0000_0000_0000_0000; + + // Mutables: + let mut d: u32 = a; + d |= 0b0000_0000_0000_0001; + + // Array projection + let mut arr: [u32; 1] = [f]; + arr[0] |= 0b0000_0000_0000_1001; + d |= arr[0]; + + // Field projection: + let mut foo: Foo = Foo(f); + let mut bar: Bar = Bar { x: f }; + foo.0 |= 0b0000_0000_0001_0000; + bar.x |= 0b0000_0000_0100_0000; + d |= foo.0 | bar.x; + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(f)]; + arr[0].0 |= 0b0000_0001_0000_0000; + d |= arr[0].0; + let mut arr: [Bar; 1] = [Bar { x: f }]; + arr[0].x |= 0b0000_0010_0000_0000; + d |= arr[0].x; + + // Field + Array projection: + let mut arr: Foo<[u32; 1]> = Foo([f]); + (arr.0)[0] |= 0b1000_0000_0000_0000; + d |= (arr.0)[0]; // /= 128 + let mut arr: Bar<[u32; 1]> = Bar { x: [f] }; + arr.x[0] |= 0b1100_0000_0000_0000; + d |= arr.x[0]; // /= 256 + + d +} + +const fn bit_xor_assign(W(a): W) -> u32 { + let f = 0b0000_0000_0000_0000; + + // Mutables: + let mut d: u32 = a; + d ^= 0b0000_0000_0000_0001; + + // Array projection + let mut arr: [u32; 1] = [f]; + arr[0] ^= 0b0000_0000_0000_0010; + d ^= arr[0]; + + // Field projection: + let mut foo: Foo = Foo(f); + let mut bar: Bar = Bar { x: f }; + foo.0 ^= 0b0000_0000_0001_0000; + bar.x ^= 0b0000_0000_1000_0000; + d ^= foo.0 ^ bar.x; + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(f)]; + arr[0].0 ^= 0b0000_0001_0000_0000; + d ^= arr[0].0; + let mut arr: [Bar; 1] = [Bar { x: f }]; + arr[0].x ^= 0b0000_0010_0000_0000; + d ^= arr[0].x; + + // Field + Array projection: + let mut arr: Foo<[u32; 1]> = Foo([f]); + (arr.0)[0] ^= 0b0100_0000_0000_0000; + d ^= (arr.0)[0]; + let mut arr: Bar<[u32; 1]> = Bar { x: [f] }; + arr.x[0] ^= 0b1000_0000_0000_0000; + d ^= arr.x[0]; + + d +} + +macro_rules! test { + ($c:ident, $e:expr, $r:expr) => { + const $c: u32 = $e; + assert_eq!($c, $r); + assert_eq!($e, $r); + } +} + +fn main() { + test!(BASICS, basics((2,)), 13); + test!(ADD, add_assign(W(1)), 10); + test!(MUL, mul_assign(A { a: 0 }), 256); + test!(DIV, div_assign([1]), 4); + test!(REM, rem_assign(W(5)), 5); + test!(SUB, sub_assign(W(8)), 0); + test!(SHL, shl_assign(W(1)), 0b1000_0000_0000_0000); + test!(SHR, shr_assign(W(256)), 1); + test!(AND, bit_and_assign(W(0b1011_1111_1111_1111_1111)), 0b0011_1100_1101_0100); + test!(OR, bit_or_assign(W(0b1011_0000_0000_0000)), 0b1111_0011_0101_1001); + test!(XOR, bit_xor_assign(W(0b0000_0000_0000_0000)), 0b1100_0011_1001_0011); +} diff --git a/src/test/ui/consts/const_let_eq_float.rs b/src/test/ui/consts/const_let_eq_float.rs new file mode 100644 index 00000000000..2c7262df367 --- /dev/null +++ b/src/test/ui/consts/const_let_eq_float.rs @@ -0,0 +1,279 @@ +// compile-pass + +#![feature(const_let, const_fn)] + +struct Foo(T); +struct Bar { x: T } +struct W(f32); +struct A { a: f32 } + +const fn basics((a,): (f32,)) -> f32 { + // Deferred assignment: + let b: f32; + b = a + 1.0; + + // Immediate assignment: + let c: f32 = b + 1.0; + + // Mutables: + let mut d: f32 = c + 1.0; + d = d + 1.0; + // +4 so far. + + // No effect statements work: + ; ; + 1; + + // Array projection + let mut arr: [f32; 1] = [0.0]; + arr[0] = 1.0; + d = d + arr[0]; + // +5 + + // Field projection: + let mut foo: Foo = Foo(0.0); + let mut bar: Bar = Bar { x: 0.0 }; + foo.0 = 1.0; + bar.x = 1.0; + d = d + foo.0 + bar.x; + // +7 + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(0.0)]; + arr[0].0 = 1.0; + d = d + arr[0].0; + let mut arr: [Bar; 1] = [Bar { x: 0.0 }]; + arr[0].x = 1.0; + d = d + arr[0].x; + // +9 + + // Field + Array projection: + let mut arr: Foo<[f32; 1]> = Foo([0.0]); + (arr.0)[0] = 1.0; + d = d + (arr.0)[0]; + let mut arr: Bar<[f32; 1]> = Bar { x: [0.0] }; + arr.x[0] = 1.0; + d = d + arr.x[0]; + // +11 + + d +} + +const fn add_assign(W(a): W) -> f32 { + // Mutables: + let mut d: f32 = a + 1.0; + d += 1.0; + // +2 so far. + + // Array projection + let mut arr: [f32; 1] = [0.0]; + arr[0] += 1.0; + d += arr[0]; + // +3 + + // Field projection: + let mut foo: Foo = Foo(0.0); + let mut bar: Bar = Bar { x: 0.0 }; + foo.0 += 1.0; + bar.x += 1.0; + d += foo.0 + bar.x; + // +5 + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(0.0)]; + arr[0].0 += 1.0; + d += arr[0].0; + let mut arr: [Bar; 1] = [Bar { x: 0.0 }]; + arr[0].x += 1.0; + d += arr[0].x; + // +7 + + // Field + Array projection: + let mut arr: Foo<[f32; 1]> = Foo([0.0]); + (arr.0)[0] += 1.0; + d += (arr.0)[0]; + let mut arr: Bar<[f32; 1]> = Bar { x: [0.0] }; + arr.x[0] += 1.0; + d += arr.x[0]; + // +9 + + d +} + +const fn mul_assign(A { a }: A) -> f32 { + // Mutables: + let mut d: f32 = a + 1.0; + d *= 2.0; + // 2^1 * (a + 1) + + // Array projection + let mut arr: [f32; 1] = [1.0]; + arr[0] *= 2.0; + d *= arr[0]; + // 2^2 * (a + 1) + + // Field projection: + let mut foo: Foo = Foo(1.0); + let mut bar: Bar = Bar { x: 1.0 }; + foo.0 *= 2.0; + bar.x *= 2.0; + d *= foo.0 + bar.x; + // 2^4 * (a + 1) + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(1.0)]; + arr[0].0 *= 2.0; + d *= arr[0].0; + let mut arr: [Bar; 1] = [Bar { x: 1.0 }]; + arr[0].x *= 2.0; + d *= arr[0].x; + // 2^6 * (a + 1) + + // Field + Array projection: + let mut arr: Foo<[f32; 1]> = Foo([1.0]); + (arr.0)[0] *= 2.0; + d *= (arr.0)[0]; + let mut arr: Bar<[f32; 1]> = Bar { x: [1.0] }; + arr.x[0] *= 2.0; + d *= arr.x[0]; + // 2^8 * (a + 1) + + d +} + +const fn div_assign(a: [f32; 1]) -> f32 { + let a = a[0]; + // Mutables: + let mut d: f32 = 1024.0 * a; + d /= 2.0; + // 512 + + // Array projection + let mut arr: [f32; 1] = [4.0]; + arr[0] /= 2.0; + d /= arr[0]; + // 256 + + // Field projection: + let mut foo: Foo = Foo(4.0); + let mut bar: Bar = Bar { x: 4.0 }; + foo.0 /= 2.0; + bar.x /= 2.0; + d /= foo.0; + d /= bar.x; + // 64 + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(4.0)]; + arr[0].0 /= 2.0; + d /= arr[0].0; + let mut arr: [Bar; 1] = [Bar { x: 4.0 }]; + arr[0].x /= 2.0; + d /= arr[0].x; + // 16 + + // Field + Array projection: + let mut arr: Foo<[f32; 1]> = Foo([4.0]); + (arr.0)[0] /= 2.0; + d /= (arr.0)[0]; + let mut arr: Bar<[f32; 1]> = Bar { x: [4.0] }; + arr.x[0] /= 2.0; + d /= arr.x[0]; + // 4 + + d +} + +const fn rem_assign(W(a): W) -> f32 { + // Mutables: + let mut d: f32 = a; + d %= 10.0; + d += 10.0; + + // Array projection + let mut arr: [f32; 1] = [3.0]; + arr[0] %= 2.0; + d %= 9.0 + arr[0]; + d += 10.0; + + // Field projection: + let mut foo: Foo = Foo(5.0); + let mut bar: Bar = Bar { x: 7.0 }; + foo.0 %= 2.0; + bar.x %= 2.0; + d %= 8.0 + foo.0 + bar.x; + d += 10.0; + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(4.0)]; + arr[0].0 %= 3.0; + d %= 9.0 + arr[0].0; + d += 10.0; + let mut arr: [Bar; 1] = [Bar { x: 7.0 }]; + arr[0].x %= 3.0; + d %= 9.0 + arr[0].x; + d += 10.0; + + // Field + Array projection: + let mut arr: Foo<[f32; 1]> = Foo([6.0]); + (arr.0)[0] %= 5.0; + d %= 9.0 + (arr.0)[0]; + let mut arr: Bar<[f32; 1]> = Bar { x: [11.0] }; + arr.x[0] %= 5.0; + d %= 9.0 + arr.x[0]; + + d +} + +const fn sub_assign(W(a): W) -> f32 { + // Mutables: + let mut d: f32 = a; + d -= 1.0; + + // Array projection + let mut arr: [f32; 1] = [2.0]; + arr[0] -= 1.0; + d -= arr[0]; + + // Field projection: + let mut foo: Foo = Foo(2.0); + let mut bar: Bar = Bar { x: 2.0 }; + foo.0 -= 1.0; + bar.x -= 1.0; + d -= foo.0 + bar.x; + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(2.0)]; + arr[0].0 -= 1.0; + d -= arr[0].0; + let mut arr: [Bar; 1] = [Bar { x: 2.0 }]; + arr[0].x -= 1.0; + d -= arr[0].x; + + // Field + Array projection: + let mut arr: Foo<[f32; 1]> = Foo([2.0]); + (arr.0)[0] -= 1.0; + d -= (arr.0)[0]; + let mut arr: Bar<[f32; 1]> = Bar { x: [2.0] }; + arr.x[0] -= 1.0; + d -= arr.x[0]; + + d +} + +macro_rules! test { + ($c:ident, $e:expr, $r:expr) => { + const $c: f32 = $e; + assert_eq!($c, $r); + assert_eq!($e, $r); + } +} + +fn main() { + test!(BASICS, basics((2.0,)), 13.0); + test!(ADD, add_assign(W(1.0)), 10.0); + test!(MUL, mul_assign(A { a: 0.0 }), 256.0); + test!(DIV, div_assign([1.0]), 4.0); + test!(REM, rem_assign(W(5.0)), 5.0); + test!(SUB, sub_assign(W(8.0)), 0.0); +} diff --git a/src/test/ui/consts/const_short_circuit.rs b/src/test/ui/consts/const_short_circuit.rs new file mode 100644 index 00000000000..cc49e4696e5 --- /dev/null +++ b/src/test/ui/consts/const_short_circuit.rs @@ -0,0 +1,16 @@ +#![feature(underscore_const_names, const_let)] + +const _: bool = false && false; +const _: bool = true && false; +const _: bool = { + let mut x = true && false; + //~^ ERROR new features like let bindings are not permitted + x +}; +const _: bool = { + let x = true && false; + //~^ ERROR new features like let bindings are not permitted + x +}; + +fn main() {} diff --git a/src/test/ui/consts/const_short_circuit.stderr b/src/test/ui/consts/const_short_circuit.stderr new file mode 100644 index 00000000000..a67bb0b1b6d --- /dev/null +++ b/src/test/ui/consts/const_short_circuit.stderr @@ -0,0 +1,26 @@ +error: new features like let bindings are not permitted in constants which also use short circuiting operators + --> $DIR/const_short_circuit.rs:6:9 + | +LL | let mut x = true && false; + | ^^^^^ + | +note: use of `&&` operator here does not actually short circuit due to the const evaluator presently not being able to do control flow. See https://github.com/rust-lang/rust/issues/49146 for more information. + --> $DIR/const_short_circuit.rs:6:22 + | +LL | let mut x = true && false; + | ^^ + +error: new features like let bindings are not permitted in constants which also use short circuiting operators + --> $DIR/const_short_circuit.rs:11:9 + | +LL | let x = true && false; + | ^ + | +note: use of `&&` operator here does not actually short circuit due to the const evaluator presently not being able to do control flow. See https://github.com/rust-lang/rust/issues/49146 for more information. + --> $DIR/const_short_circuit.rs:11:18 + | +LL | let x = true && false; + | ^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr index f43befb37c1..916fc3e0d88 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr @@ -115,7 +115,7 @@ LL | const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn error: local variables in const fn are unstable --> $DIR/min_const_fn.rs:109:34 | -LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn are unstable +LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn | ^ error: `if`, `match`, `&&` and `||` are not stable in const fn @@ -199,9 +199,8 @@ LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } | |temporary value created here | returns a reference to data owned by the current function | - = warning: This error has been downgraded to a warning for backwards compatibility with previous releases. - It represents potential unsoundness in your code. - This warning will become a hard error in the future. + = warning: this error has been downgraded to a warning for backwards compatibility with previous releases + = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future error: trait bounds other than `Sized` on const fn parameters are unstable --> $DIR/min_const_fn.rs:147:41 diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.rs b/src/test/ui/consts/min_const_fn/min_const_fn.rs index 0dba3a7de53..ad983da4df9 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.rs +++ b/src/test/ui/consts/min_const_fn/min_const_fn.rs @@ -78,9 +78,9 @@ const fn i32_ops2(c: i32, d: i32) -> bool { c < d } const fn i32_ops3(c: i32, d: i32) -> bool { c != d } const fn i32_ops4(c: i32, d: i32) -> i32 { c + d } const fn char_cast(u: u8) -> char { u as char } -const unsafe fn foo4() -> i32 { 42 } -const unsafe fn foo5() -> *const T { 0 as *const T } -const unsafe fn foo6() -> *mut T { 0 as *mut T } +const unsafe fn ret_i32_no_unsafe() -> i32 { 42 } +const unsafe fn ret_null_ptr_no_unsafe() -> *const T { 0 as *const T } +const unsafe fn ret_null_mut_ptr_no_unsafe() -> *mut T { 0 as *mut T } // not ok const fn foo11(t: T) -> T { t } @@ -106,7 +106,7 @@ const fn foo30_2(x: *mut u32) -> usize { x as usize } const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } } //~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn -const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn are unstable +const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn const fn foo36(a: bool, b: bool) -> bool { a && b } //~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn const fn foo37(a: bool, b: bool) -> bool { a || b } diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr index bcb9be6e548..a93a4f817fc 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn.stderr @@ -115,7 +115,7 @@ LL | const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn error: local variables in const fn are unstable --> $DIR/min_const_fn.rs:109:34 | -LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn are unstable +LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn | ^ error: `if`, `match`, `&&` and `||` are not stable in const fn diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.nll.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.nll.stderr index 4ec00a16456..96abc104208 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.nll.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.nll.stderr @@ -19,9 +19,8 @@ LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) } | |creates a temporary which is freed while still in use | cast requires that borrow lasts for `'static` | - = warning: This error has been downgraded to a warning for backwards compatibility with previous releases. - It represents potential unsoundness in your code. - This warning will become a hard error in the future. + = warning: this error has been downgraded to a warning for backwards compatibility with previous releases + = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs index 67332c6d2cf..92e99c6228a 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs +++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs @@ -8,29 +8,33 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-min_const_unsafe_fn + // ok -const unsafe fn foo4() -> i32 { 42 } -const unsafe fn foo5() -> *const T { 0 as *const T } -const unsafe fn foo6() -> *mut T { 0 as *mut T } +const unsafe fn ret_i32_no_unsafe() -> i32 { 42 } +const unsafe fn ret_null_ptr_no_unsafe() -> *const T { 0 as *const T } +const unsafe fn ret_null_mut_ptr_no_unsafe() -> *mut T { 0 as *mut T } const fn no_unsafe() { unsafe {} } // not ok -const fn foo8() -> i32 { - unsafe { foo4() } //~ ERROR unsafe operations are not allowed in const fn +const fn call_unsafe_const_fn() -> i32 { + unsafe { ret_i32_no_unsafe() } //~ ERROR calls to `const unsafe fn` in const fns are unstable } -const fn foo9() -> *const String { - unsafe { foo5::() } //~ ERROR unsafe operations are not allowed in const fn +const fn call_unsafe_generic_const_fn() -> *const String { + unsafe { ret_null_ptr_no_unsafe::() } + //~^ ERROR calls to `const unsafe fn` in const fns are unstable } -const fn foo10() -> *const Vec> { - unsafe { foo6::>>() } //~ ERROR not allowed in const fn +const fn call_unsafe_generic_cell_const_fn() -> *const Vec> { + unsafe { ret_null_mut_ptr_no_unsafe::>>() } + //~^ ERROR calls to `const unsafe fn` in const fns } -const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn +const unsafe fn deref_forbidden(x: *mut usize) -> usize { *x } //~^ dereferencing raw pointers in constant functions fn main() {} const unsafe fn no_union() { union Foo { x: (), y: () } - Foo { x: () }.y //~ ERROR not allowed in const fn + Foo { x: () }.y //~^ unions in const fn } diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr index 8cff0d491d8..fafc89d1493 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr @@ -1,59 +1,43 @@ error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911) - --> $DIR/min_const_fn_unsafe.rs:27:51 + --> $DIR/min_const_fn_unsafe.rs:31:59 | -LL | const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn - | ^^ +LL | const unsafe fn deref_forbidden(x: *mut usize) -> usize { *x } + | ^^ | = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable error[E0658]: unions in const fn are unstable (see issue #51909) - --> $DIR/min_const_fn_unsafe.rs:34:5 + --> $DIR/min_const_fn_unsafe.rs:38:5 | -LL | Foo { x: () }.y //~ ERROR not allowed in const fn +LL | Foo { x: () }.y | ^^^^^^^^^^^^^^^ | = help: add #![feature(const_fn_union)] to the crate attributes to enable -error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn - --> $DIR/min_const_fn_unsafe.rs:19:14 +error[E0658]: calls to `const unsafe fn` in const fns are unstable (see issue #55607) + --> $DIR/min_const_fn_unsafe.rs:21:14 | -LL | unsafe { foo4() } //~ ERROR unsafe operations are not allowed in const fn - | ^^^^^^ call to unsafe function +LL | unsafe { ret_i32_no_unsafe() } //~ ERROR calls to `const unsafe fn` in const fns are unstable + | ^^^^^^^^^^^^^^^^^^^ | - = note: consult the function's documentation for information on how to avoid undefined behavior + = help: add #![feature(min_const_unsafe_fn)] to the crate attributes to enable -error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn - --> $DIR/min_const_fn_unsafe.rs:22:14 +error[E0658]: calls to `const unsafe fn` in const fns are unstable (see issue #55607) + --> $DIR/min_const_fn_unsafe.rs:24:14 | -LL | unsafe { foo5::() } //~ ERROR unsafe operations are not allowed in const fn - | ^^^^^^^^^^^^^^^^ call to unsafe function +LL | unsafe { ret_null_ptr_no_unsafe::() } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: consult the function's documentation for information on how to avoid undefined behavior + = help: add #![feature(min_const_unsafe_fn)] to the crate attributes to enable -error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn - --> $DIR/min_const_fn_unsafe.rs:25:14 +error[E0658]: calls to `const unsafe fn` in const fns are unstable (see issue #55607) + --> $DIR/min_const_fn_unsafe.rs:28:14 | -LL | unsafe { foo6::>>() } //~ ERROR not allowed in const fn - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function +LL | unsafe { ret_null_mut_ptr_no_unsafe::>>() } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: consult the function's documentation for information on how to avoid undefined behavior + = help: add #![feature(min_const_unsafe_fn)] to the crate attributes to enable -error: dereference of raw pointer is unsafe and unsafe operations are not allowed in const fn - --> $DIR/min_const_fn_unsafe.rs:27:51 - | -LL | const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn - | ^^ dereference of raw pointer - | - = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior - -error: access to union field is unsafe and unsafe operations are not allowed in const fn - --> $DIR/min_const_fn_unsafe.rs:34:5 - | -LL | Foo { x: () }.y //~ ERROR not allowed in const fn - | ^^^^^^^^^^^^^^^ access to union field - | - = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior - -error: aborting due to 7 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.rs b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.rs new file mode 100644 index 00000000000..67a48206126 --- /dev/null +++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.rs @@ -0,0 +1,61 @@ +// 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(min_const_unsafe_fn)] + +// ok +const unsafe fn foo4() -> i32 { 42 } +const unsafe fn foo5() -> *const T { 0 as *const T } +const unsafe fn foo6() -> *mut T { 0 as *mut T } +const fn no_unsafe() { unsafe {} } + +const fn foo8() -> i32 { + unsafe { foo4() } +} +const fn foo9() -> *const String { + unsafe { foo5::() } +} +const fn foo10() -> *const Vec> { + unsafe { foo6::>>() } +} +const unsafe fn foo8_3() -> i32 { + unsafe { foo4() } +} +const unsafe fn foo9_3() -> *const String { + unsafe { foo5::() } +} +const unsafe fn foo10_3() -> *const Vec> { + unsafe { foo6::>>() } +} +const unsafe fn foo8_2() -> i32 { + foo4() +} +const unsafe fn foo9_2() -> *const String { + foo5::() +} +const unsafe fn foo10_2() -> *const Vec> { + foo6::>>() +} +const unsafe fn foo30_3(x: *mut usize) -> usize { *x } +//~^ dereferencing raw pointers in constant functions + +const unsafe fn foo30_4(x: *mut usize) -> &'static usize { &*x } +//~^ dereferencing raw pointers in constant functions + +const fn foo30_5(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe +//~^ dereferencing raw pointers in constant functions + +fn main() {} + +const unsafe fn no_union() { + union Foo { x: (), y: () } + Foo { x: () }.y + //~^ unions in const fn +} diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.stderr new file mode 100644 index 00000000000..63bf9a53e50 --- /dev/null +++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.stderr @@ -0,0 +1,44 @@ +error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911) + --> $DIR/min_const_fn_unsafe_feature_gate.rs:46:51 + | +LL | const unsafe fn foo30_3(x: *mut usize) -> usize { *x } + | ^^ + | + = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable + +error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911) + --> $DIR/min_const_fn_unsafe_feature_gate.rs:49:60 + | +LL | const unsafe fn foo30_4(x: *mut usize) -> &'static usize { &*x } + | ^^^ + | + = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable + +error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911) + --> $DIR/min_const_fn_unsafe_feature_gate.rs:52:62 + | +LL | const fn foo30_5(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe + | ^^^ + | + = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable + +error[E0658]: unions in const fn are unstable (see issue #51909) + --> $DIR/min_const_fn_unsafe_feature_gate.rs:59:5 + | +LL | Foo { x: () }.y + | ^^^^^^^^^^^^^^^ + | + = help: add #![feature(const_fn_union)] to the crate attributes to enable + +error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block + --> $DIR/min_const_fn_unsafe_feature_gate.rs:52:62 + | +LL | const fn foo30_5(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe + | ^^^ dereference of raw pointer + | + = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + +error: aborting due to 5 previous errors + +Some errors occurred: E0133, E0658. +For more information about an error, try `rustc --explain E0133`. diff --git a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs new file mode 100644 index 00000000000..f559c23ff0f --- /dev/null +++ b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs @@ -0,0 +1,47 @@ +// 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. + +#![unstable(feature = "humans", + reason = "who ever let humans program computers, + we're apparently really bad at it", + issue = "0")] + +#![feature(rustc_const_unstable, const_fn, foo, foo2)] +#![feature(min_const_unsafe_fn)] +#![feature(staged_api)] + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature="foo")] +const unsafe fn foo() -> u32 { 42 } + +#[stable(feature = "rust1", since = "1.0.0")] +// can't call non-min_const_fn +const unsafe fn bar() -> u32 { unsafe { foo() } } //~ ERROR can only call other `min_const_fn` + +#[unstable(feature = "rust1", issue="0")] +const unsafe fn foo2() -> u32 { 42 } + +#[stable(feature = "rust1", since = "1.0.0")] +// can't call non-min_const_fn +const unsafe fn bar2() -> u32 { unsafe { foo2() } } //~ ERROR can only call other `min_const_fn` + +#[stable(feature = "rust1", since = "1.0.0")] +// conformity is required, even with `const_fn` feature gate +const unsafe fn bar3() -> u32 { (5f32 + 6f32) as u32 } //~ ERROR only int, `bool` and `char` op + +// check whether this function cannot be called even with the feature gate active +#[unstable(feature = "foo2", issue="0")] +const unsafe fn foo2_gated() -> u32 { 42 } + +#[stable(feature = "rust1", since = "1.0.0")] +// can't call non-min_const_fn +const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } } //~ ERROR can only call other + +fn main() {} diff --git a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr new file mode 100644 index 00000000000..37be2889173 --- /dev/null +++ b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr @@ -0,0 +1,26 @@ +error: can only call other `min_const_fn` within a `min_const_fn` + --> $DIR/min_const_unsafe_fn_libstd_stability.rs:26:41 + | +LL | const unsafe fn bar() -> u32 { unsafe { foo() } } //~ ERROR can only call other `min_const_fn` + | ^^^^^ + +error: can only call other `min_const_fn` within a `min_const_fn` + --> $DIR/min_const_unsafe_fn_libstd_stability.rs:33:42 + | +LL | const unsafe fn bar2() -> u32 { unsafe { foo2() } } //~ ERROR can only call other `min_const_fn` + | ^^^^^^ + +error: only int, `bool` and `char` operations are stable in const fn + --> $DIR/min_const_unsafe_fn_libstd_stability.rs:37:33 + | +LL | const unsafe fn bar3() -> u32 { (5f32 + 6f32) as u32 } //~ ERROR only int, `bool` and `char` op + | ^^^^^^^^^^^^^ + +error: can only call other `min_const_fn` within a `min_const_fn` + --> $DIR/min_const_unsafe_fn_libstd_stability.rs:45:48 + | +LL | const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } } //~ ERROR can only call other + | ^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs new file mode 100644 index 00000000000..131bc97c85a --- /dev/null +++ b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs @@ -0,0 +1,43 @@ +// 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. + +#![unstable(feature = "humans", + reason = "who ever let humans program computers, + we're apparently really bad at it", + issue = "0")] + +#![feature(rustc_const_unstable, const_fn, foo, foo2)] +#![feature(min_const_unsafe_fn)] +#![feature(staged_api)] + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature="foo")] +const fn foo() -> u32 { 42 } + +#[stable(feature = "rust1", since = "1.0.0")] +// can't call non-min_const_fn +const unsafe fn bar() -> u32 { foo() } //~ ERROR can only call other `min_const_fn` + +#[unstable(feature = "rust1", issue="0")] +const fn foo2() -> u32 { 42 } + +#[stable(feature = "rust1", since = "1.0.0")] +// can't call non-min_const_fn +const unsafe fn bar2() -> u32 { foo2() } //~ ERROR can only call other `min_const_fn` + +// check whether this function cannot be called even with the feature gate active +#[unstable(feature = "foo2", issue="0")] +const fn foo2_gated() -> u32 { 42 } + +#[stable(feature = "rust1", since = "1.0.0")] +// can't call non-min_const_fn +const unsafe fn bar2_gated() -> u32 { foo2_gated() } //~ ERROR can only call other `min_const_fn` + +fn main() {} diff --git a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr new file mode 100644 index 00000000000..0b58dc1294b --- /dev/null +++ b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr @@ -0,0 +1,20 @@ +error: can only call other `min_const_fn` within a `min_const_fn` + --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:26:32 + | +LL | const unsafe fn bar() -> u32 { foo() } //~ ERROR can only call other `min_const_fn` + | ^^^^^ + +error: can only call other `min_const_fn` within a `min_const_fn` + --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:33:33 + | +LL | const unsafe fn bar2() -> u32 { foo2() } //~ ERROR can only call other `min_const_fn` + | ^^^^^^ + +error: can only call other `min_const_fn` within a `min_const_fn` + --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:41:39 + | +LL | const unsafe fn bar2_gated() -> u32 { foo2_gated() } //~ ERROR can only call other `min_const_fn` + | ^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/consts/min_const_fn/mutable_borrow.rs b/src/test/ui/consts/min_const_fn/mutable_borrow.rs new file mode 100644 index 00000000000..3dd76b630a8 --- /dev/null +++ b/src/test/ui/consts/min_const_fn/mutable_borrow.rs @@ -0,0 +1,17 @@ +const fn mutable_ref_in_const() -> u8 { + let mut a = 0; //~ ERROR local variables in const fn + let b = &mut a; + *b +} + +struct X; + +impl X { + const fn inherent_mutable_ref_in_const() -> u8 { + let mut a = 0; //~ ERROR local variables in const fn + let b = &mut a; + *b + } +} + +fn main() {} diff --git a/src/test/ui/consts/min_const_fn/mutable_borrow.stderr b/src/test/ui/consts/min_const_fn/mutable_borrow.stderr new file mode 100644 index 00000000000..fa46f5c804f --- /dev/null +++ b/src/test/ui/consts/min_const_fn/mutable_borrow.stderr @@ -0,0 +1,14 @@ +error: local variables in const fn are unstable + --> $DIR/mutable_borrow.rs:2:9 + | +LL | let mut a = 0; //~ ERROR local variables in const fn + | ^^^^^ + +error: local variables in const fn are unstable + --> $DIR/mutable_borrow.rs:11:13 + | +LL | let mut a = 0; //~ ERROR local variables in const fn + | ^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/consts/projection_qualif.rs b/src/test/ui/consts/projection_qualif.rs index 34e8eaba9f2..5863429a2f2 100644 --- a/src/test/ui/consts/projection_qualif.rs +++ b/src/test/ui/consts/projection_qualif.rs @@ -7,6 +7,7 @@ const FOO: &u32 = { { let b: *mut u32 = &mut a; //~ ERROR may only refer to immutable values unsafe { *b = 5; } //~ ERROR dereferencing raw pointers in constants + //~^ contains unimplemented expression } &{a} }; diff --git a/src/test/ui/consts/projection_qualif.stderr b/src/test/ui/consts/projection_qualif.stderr index d5252f199be..cc3635a979b 100644 --- a/src/test/ui/consts/projection_qualif.stderr +++ b/src/test/ui/consts/projection_qualif.stderr @@ -4,6 +4,12 @@ error[E0017]: references in constants may only refer to immutable values LL | let b: *mut u32 = &mut a; //~ ERROR may only refer to immutable values | ^^^^^^ constants require immutable values +error[E0019]: constant contains unimplemented expression type + --> $DIR/projection_qualif.rs:9:18 + | +LL | unsafe { *b = 5; } //~ ERROR dereferencing raw pointers in constants + | ^^^^^^ + error[E0658]: dereferencing raw pointers in constants is unstable (see issue #51911) --> $DIR/projection_qualif.rs:9:18 | @@ -12,7 +18,7 @@ LL | unsafe { *b = 5; } //~ ERROR dereferencing raw pointers in constant | = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -Some errors occurred: E0017, E0658. +Some errors occurred: E0017, E0019, E0658. For more information about an error, try `rustc --explain E0017`. diff --git a/src/test/ui/consts/promoted_regression.rs b/src/test/ui/consts/promoted_regression.rs new file mode 100644 index 00000000000..68b9a20ecf9 --- /dev/null +++ b/src/test/ui/consts/promoted_regression.rs @@ -0,0 +1,9 @@ +// compile-pass + +fn main() { + let _ = &[("", ""); 3]; +} + +const FOO: &[(&str, &str)] = &[("", ""); 3]; +const BAR: &[(&str, &str); 5] = &[("", ""); 5]; +const BAA: &[[&str; 12]; 11] = &[[""; 12]; 11]; diff --git a/src/test/ui/consts/single_variant_match_ice.rs b/src/test/ui/consts/single_variant_match_ice.rs index 67a41bc5dc4..79dde3c18e8 100644 --- a/src/test/ui/consts/single_variant_match_ice.rs +++ b/src/test/ui/consts/single_variant_match_ice.rs @@ -2,6 +2,14 @@ enum Foo { Prob, } +const FOO: u32 = match Foo::Prob { + Foo::Prob => 42, //~ ERROR unimplemented expression type +}; + +const BAR: u32 = match Foo::Prob { + x => 42, //~ ERROR unimplemented expression type +}; + impl Foo { pub const fn as_val(&self) -> u8 { use self::Foo::*; diff --git a/src/test/ui/consts/single_variant_match_ice.stderr b/src/test/ui/consts/single_variant_match_ice.stderr index a0222b0d489..f5c2cb5e0e9 100644 --- a/src/test/ui/consts/single_variant_match_ice.stderr +++ b/src/test/ui/consts/single_variant_match_ice.stderr @@ -1,8 +1,21 @@ +error[E0019]: constant contains unimplemented expression type + --> $DIR/single_variant_match_ice.rs:6:5 + | +LL | Foo::Prob => 42, //~ ERROR unimplemented expression type + | ^^^^^^^^^ + +error[E0019]: constant contains unimplemented expression type + --> $DIR/single_variant_match_ice.rs:10:5 + | +LL | x => 42, //~ ERROR unimplemented expression type + | ^ + error: `if`, `match`, `&&` and `||` are not stable in const fn - --> $DIR/single_variant_match_ice.rs:10:13 + --> $DIR/single_variant_match_ice.rs:18:13 | LL | Prob => 0x1, //~ ERROR `if`, `match`, `&&` and `||` are not stable in const fn | ^^^^ -error: aborting due to previous error +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0019`. diff --git a/src/test/ui/consts/validate_never_arrays.stderr b/src/test/ui/consts/validate_never_arrays.stderr index 0b639240bb3..b9d181a76dd 100644 --- a/src/test/ui/consts/validate_never_arrays.stderr +++ b/src/test/ui/consts/validate_never_arrays.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/validate_never_arrays.rs:3:1 | LL | const FOO: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; //~ ERROR undefined behavior - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at .[0] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at . | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior diff --git a/src/test/ui/deprecation/deprecation-in-future.rs b/src/test/ui/deprecation/deprecation-in-future.rs new file mode 100644 index 00000000000..c6c60177e9d --- /dev/null +++ b/src/test/ui/deprecation/deprecation-in-future.rs @@ -0,0 +1,12 @@ +// ignore-tidy-linelength + +#![deny(deprecated_in_future)] + +#[deprecated(since = "99.99.99", note = "text")] +pub fn deprecated_future() {} + +fn test() { + deprecated_future(); //~ ERROR use of item 'deprecated_future' that will be deprecated in future version 99.99.99: text +} + +fn main() {} diff --git a/src/test/ui/deprecation/deprecation-in-future.stderr b/src/test/ui/deprecation/deprecation-in-future.stderr new file mode 100644 index 00000000000..38392cf9608 --- /dev/null +++ b/src/test/ui/deprecation/deprecation-in-future.stderr @@ -0,0 +1,14 @@ +error: use of item 'deprecated_future' that will be deprecated in future version 99.99.99: text + --> $DIR/deprecation-in-future.rs:9:5 + | +LL | deprecated_future(); //~ ERROR use of item 'deprecated_future' that will be deprecated in future version 99.99.99: text + | ^^^^^^^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/deprecation-in-future.rs:3:9 + | +LL | #![deny(deprecated_in_future)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/dropck/dropck-eyepatch.rs b/src/test/ui/dropck/dropck-eyepatch.rs index d7a671fd33c..fb1c03b6786 100644 --- a/src/test/ui/dropck/dropck-eyepatch.rs +++ b/src/test/ui/dropck/dropck-eyepatch.rs @@ -31,7 +31,7 @@ // - D means "I implement Drop" // // - P means "I implement Drop but guarantee my (first) parameter is -// pure, i.e. not accessed from the destructor"; no other parameters +// pure, i.e., not accessed from the destructor"; no other parameters // are pure. // // - S means "I do not implement Drop" diff --git a/src/test/ui/e0119/complex-impl.stderr b/src/test/ui/e0119/complex-impl.stderr index 1fc4c28d67c..d60f9c4e6a8 100644 --- a/src/test/ui/e0119/complex-impl.stderr +++ b/src/test/ui/e0119/complex-impl.stderr @@ -8,7 +8,7 @@ LL | impl External for (Q, R) {} //~ ERROR must be used - impl<'a, 'b, 'c, T, U, V, W> complex_impl_support::External for (T, complex_impl_support::M<'a, 'b, 'c, std::boxed::Box, V, W>) where >::Output == V, ::Item == T, 'b : 'a, T : 'a, U: std::ops::FnOnce<(T,)>, U : 'static, V: std::iter::Iterator, V: std::clone::Clone, W: std::ops::Add, ::Output: std::marker::Copy; -error[E0210]: type parameter `R` must be used as the type parameter for some local type (e.g. `MyStruct`) +error[E0210]: type parameter `R` must be used as the type parameter for some local type (e.g., `MyStruct`) --> $DIR/complex-impl.rs:19:1 | LL | impl External for (Q, R) {} //~ ERROR must be used diff --git a/src/test/ui/e0119/issue-28981.stderr b/src/test/ui/e0119/issue-28981.stderr index 76ff88d6cc6..b5ec1c8454b 100644 --- a/src/test/ui/e0119/issue-28981.stderr +++ b/src/test/ui/e0119/issue-28981.stderr @@ -8,7 +8,7 @@ LL | impl Deref for Foo { } //~ ERROR must be used - impl std::ops::Deref for &T where T: ?Sized; -error[E0210]: type parameter `Foo` must be used as the type parameter for some local type (e.g. `MyStruct`) +error[E0210]: type parameter `Foo` must be used as the type parameter for some local type (e.g., `MyStruct`) --> $DIR/issue-28981.rs:15:1 | LL | impl Deref for Foo { } //~ ERROR must be used diff --git a/src/test/ui/error-codes/E0050.stderr b/src/test/ui/error-codes/E0050.stderr index bff3b7b16b9..6c797e00731 100644 --- a/src/test/ui/error-codes/E0050.stderr +++ b/src/test/ui/error-codes/E0050.stderr @@ -2,7 +2,7 @@ error[E0050]: method `foo` has 1 parameter but the declaration in trait `Foo::fo --> $DIR/E0050.rs:20:12 | LL | fn foo(&self, x: u8) -> bool; - | -- trait requires 2 parameters + | ------------ trait requires 2 parameters ... LL | fn foo(&self) -> bool { true } //~ ERROR E0050 | ^^^^^ expected 2 parameters, found 1 @@ -11,19 +11,19 @@ error[E0050]: method `bar` has 1 parameter but the declaration in trait `Foo::ba --> $DIR/E0050.rs:21:12 | LL | fn bar(&self, x: u8, y: u8, z: u8); - | -- trait requires 4 parameters + | -------------------------- trait requires 4 parameters ... LL | fn bar(&self) { } //~ ERROR E0050 | ^^^^^ expected 4 parameters, found 1 error[E0050]: method `less` has 4 parameters but the declaration in trait `Foo::less` has 1 - --> $DIR/E0050.rs:22:37 + --> $DIR/E0050.rs:22:13 | LL | fn less(&self); | ----- trait requires 1 parameter ... LL | fn less(&self, x: u8, y: u8, z: u8) { } //~ ERROR E0050 - | ^^ expected 1 parameter, found 4 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 parameter, found 4 error: aborting due to 3 previous errors diff --git a/src/test/ui/error-codes/E0259.rs b/src/test/ui/error-codes/E0259.rs index 5a47541c708..b3e633a7017 100644 --- a/src/test/ui/error-codes/E0259.rs +++ b/src/test/ui/error-codes/E0259.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(alloc, libc)] +#![feature(alloc, rustc_private)] #![allow(unused_extern_crates)] extern crate alloc; diff --git a/src/test/ui/error-codes/E0424.rs b/src/test/ui/error-codes/E0424.rs index 445d0c5f3ed..20d42da1c0c 100644 --- a/src/test/ui/error-codes/E0424.rs +++ b/src/test/ui/error-codes/E0424.rs @@ -19,4 +19,5 @@ impl Foo { } fn main () { + let self = "self"; //~ ERROR E0424 } diff --git a/src/test/ui/error-codes/E0424.stderr b/src/test/ui/error-codes/E0424.stderr index a1b7a5f6533..5eccd7d2283 100644 --- a/src/test/ui/error-codes/E0424.stderr +++ b/src/test/ui/error-codes/E0424.stderr @@ -4,6 +4,12 @@ error[E0424]: expected value, found module `self` LL | self.bar(); //~ ERROR E0424 | ^^^^ `self` value is a keyword only available in methods with `self` parameter -error: aborting due to previous error +error[E0424]: expected unit struct/variant or constant, found module `self` + --> $DIR/E0424.rs:22:9 + | +LL | let self = "self"; //~ ERROR E0424 + | ^^^^ `self` value is a keyword and may not be bound to variables or shadowed + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0424`. diff --git a/src/test/ui/exhaustive_integer_patterns.rs b/src/test/ui/exhaustive_integer_patterns.rs index 7825aaa2912..020382d9fe1 100644 --- a/src/test/ui/exhaustive_integer_patterns.rs +++ b/src/test/ui/exhaustive_integer_patterns.rs @@ -8,11 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(exhaustive_integer_patterns)] +#![feature(precise_pointer_size_matching)] #![feature(exclusive_range_pattern)] + #![deny(unreachable_patterns)] -use std::{char, usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128}; +use std::{char, u8, u16, u32, u64, u128, i8, i16, i32, i64, i128}; fn main() { let x: u8 = 0; @@ -68,10 +69,6 @@ fn main() { '\u{E000}' ..= '\u{10_FFFF}' => {} } - match 0usize { - 0 ..= usize::MAX => {} // ok - } - match 0u16 { 0 ..= u16::MAX => {} // ok } @@ -88,10 +85,6 @@ fn main() { 0 ..= u128::MAX => {} // ok } - match 0isize { - isize::MIN ..= isize::MAX => {} // ok - } - match 0i8 { -128 ..= 127 => {} // ok } diff --git a/src/test/ui/exhaustive_integer_patterns.stderr b/src/test/ui/exhaustive_integer_patterns.stderr index 44b05a12aeb..011e93683fb 100644 --- a/src/test/ui/exhaustive_integer_patterns.stderr +++ b/src/test/ui/exhaustive_integer_patterns.stderr @@ -1,83 +1,83 @@ error: unreachable pattern - --> $DIR/exhaustive_integer_patterns.rs:32:9 + --> $DIR/exhaustive_integer_patterns.rs:33:9 | LL | 200 => {} //~ ERROR unreachable pattern | ^^^ | note: lint level defined here - --> $DIR/exhaustive_integer_patterns.rs:13:9 + --> $DIR/exhaustive_integer_patterns.rs:14:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error[E0004]: non-exhaustive patterns: `128u8..=255u8` not covered - --> $DIR/exhaustive_integer_patterns.rs:37:11 + --> $DIR/exhaustive_integer_patterns.rs:38:11 | LL | match x { //~ ERROR non-exhaustive patterns | ^ pattern `128u8..=255u8` not covered error[E0004]: non-exhaustive patterns: `11u8..=19u8`, `31u8..=34u8`, `36u8..=69u8` and 1 more not covered - --> $DIR/exhaustive_integer_patterns.rs:42:11 + --> $DIR/exhaustive_integer_patterns.rs:43:11 | LL | match x { //~ ERROR non-exhaustive patterns | ^ patterns `11u8..=19u8`, `31u8..=34u8`, `36u8..=69u8` and 1 more not covered error: unreachable pattern - --> $DIR/exhaustive_integer_patterns.rs:53:9 + --> $DIR/exhaustive_integer_patterns.rs:54:9 | LL | -2..=20 => {} //~ ERROR unreachable pattern | ^^^^^^^ error[E0004]: non-exhaustive patterns: `-128i8..=-8i8`, `-6i8`, `121i8..=124i8` and 1 more not covered - --> $DIR/exhaustive_integer_patterns.rs:50:11 + --> $DIR/exhaustive_integer_patterns.rs:51:11 | LL | match x { //~ ERROR non-exhaustive patterns | ^ patterns `-128i8..=-8i8`, `-6i8`, `121i8..=124i8` and 1 more not covered error[E0004]: non-exhaustive patterns: `-128i8` not covered - --> $DIR/exhaustive_integer_patterns.rs:99:11 + --> $DIR/exhaustive_integer_patterns.rs:92:11 | LL | match 0i8 { //~ ERROR non-exhaustive patterns | ^^^ pattern `-128i8` not covered error[E0004]: non-exhaustive patterns: `0i16` not covered - --> $DIR/exhaustive_integer_patterns.rs:107:11 + --> $DIR/exhaustive_integer_patterns.rs:100:11 | LL | match 0i16 { //~ ERROR non-exhaustive patterns | ^^^^ pattern `0i16` not covered error[E0004]: non-exhaustive patterns: `128u8..=255u8` not covered - --> $DIR/exhaustive_integer_patterns.rs:125:11 + --> $DIR/exhaustive_integer_patterns.rs:118:11 | LL | match 0u8 { //~ ERROR non-exhaustive patterns | ^^^ pattern `128u8..=255u8` not covered error[E0004]: non-exhaustive patterns: `(0u8, Some(_))` and `(2u8..=255u8, Some(_))` not covered - --> $DIR/exhaustive_integer_patterns.rs:137:11 + --> $DIR/exhaustive_integer_patterns.rs:130:11 | LL | match (0u8, Some(())) { //~ ERROR non-exhaustive patterns | ^^^^^^^^^^^^^^^ patterns `(0u8, Some(_))` and `(2u8..=255u8, Some(_))` not covered error[E0004]: non-exhaustive patterns: `(126u8..=127u8, false)` not covered - --> $DIR/exhaustive_integer_patterns.rs:142:11 + --> $DIR/exhaustive_integer_patterns.rs:135:11 | LL | match (0u8, true) { //~ ERROR non-exhaustive patterns | ^^^^^^^^^^^ pattern `(126u8..=127u8, false)` not covered error[E0004]: non-exhaustive patterns: `340282366920938463463374607431768211455u128` not covered - --> $DIR/exhaustive_integer_patterns.rs:162:11 + --> $DIR/exhaustive_integer_patterns.rs:155:11 | LL | match 0u128 { //~ ERROR non-exhaustive patterns | ^^^^^ pattern `340282366920938463463374607431768211455u128` not covered error[E0004]: non-exhaustive patterns: `5u128..=340282366920938463463374607431768211455u128` not covered - --> $DIR/exhaustive_integer_patterns.rs:166:11 + --> $DIR/exhaustive_integer_patterns.rs:159:11 | LL | match 0u128 { //~ ERROR non-exhaustive patterns | ^^^^^ pattern `5u128..=340282366920938463463374607431768211455u128` not covered error[E0004]: non-exhaustive patterns: `0u128..=3u128` not covered - --> $DIR/exhaustive_integer_patterns.rs:170:11 + --> $DIR/exhaustive_integer_patterns.rs:163:11 | LL | match 0u128 { //~ ERROR non-exhaustive patterns | ^^^^^ pattern `0u128..=3u128` not covered diff --git a/src/test/ui/existential_types/private_unused.rs b/src/test/ui/existential_types/private_unused.rs new file mode 100644 index 00000000000..736d812bc0a --- /dev/null +++ b/src/test/ui/existential_types/private_unused.rs @@ -0,0 +1,13 @@ +// compile-pass + +#[deny(warnings)] + +enum Empty { } +trait Bar {} +impl Bar for () {} + +fn boo() -> impl Bar {} + +fn main() { + boo(); +} diff --git a/src/test/compile-fail-fulldeps/explore-issue-38412.rs b/src/test/ui/explore-issue-38412.rs similarity index 100% rename from src/test/compile-fail-fulldeps/explore-issue-38412.rs rename to src/test/ui/explore-issue-38412.rs diff --git a/src/test/ui/explore-issue-38412.stderr b/src/test/ui/explore-issue-38412.stderr new file mode 100644 index 00000000000..8e31c1c7e01 --- /dev/null +++ b/src/test/ui/explore-issue-38412.stderr @@ -0,0 +1,132 @@ +error[E0658]: use of unstable library feature 'unstable_undeclared' (see issue #38412) + --> $DIR/explore-issue-38412.rs:31:63 + | +LL | let Record { a_stable_pub: _, a_unstable_declared_pub: _, a_unstable_undeclared_pub: _, .. } = + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(unstable_undeclared)] to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_undeclared' (see issue #38412) + --> $DIR/explore-issue-38412.rs:40:5 + | +LL | r.a_unstable_undeclared_pub; //~ ERROR use of unstable library feature + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(unstable_undeclared)] to the crate attributes to enable + +error[E0616]: field `b_crate` of struct `pub_and_stability::Record` is private + --> $DIR/explore-issue-38412.rs:41:5 + | +LL | r.b_crate; //~ ERROR is private + | ^^^^^^^^^ + +error[E0616]: field `c_mod` of struct `pub_and_stability::Record` is private + --> $DIR/explore-issue-38412.rs:42:5 + | +LL | r.c_mod; //~ ERROR is private + | ^^^^^^^ + +error[E0616]: field `d_priv` of struct `pub_and_stability::Record` is private + --> $DIR/explore-issue-38412.rs:43:5 + | +LL | r.d_priv; //~ ERROR is private + | ^^^^^^^^ + +error[E0658]: use of unstable library feature 'unstable_undeclared' (see issue #38412) + --> $DIR/explore-issue-38412.rs:47:5 + | +LL | t.2; //~ ERROR use of unstable library feature + | ^^^ + | + = help: add #![feature(unstable_undeclared)] to the crate attributes to enable + +error[E0616]: field `3` of struct `pub_and_stability::Tuple` is private + --> $DIR/explore-issue-38412.rs:48:5 + | +LL | t.3; //~ ERROR is private + | ^^^ + +error[E0616]: field `4` of struct `pub_and_stability::Tuple` is private + --> $DIR/explore-issue-38412.rs:49:5 + | +LL | t.4; //~ ERROR is private + | ^^^ + +error[E0616]: field `5` of struct `pub_and_stability::Tuple` is private + --> $DIR/explore-issue-38412.rs:50:5 + | +LL | t.5; //~ ERROR is private + | ^^^ + +error[E0658]: use of unstable library feature 'unstable_undeclared' (see issue #38412) + --> $DIR/explore-issue-38412.rs:54:7 + | +LL | r.unstable_undeclared_trait_method(); //~ ERROR use of unstable library feature + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(unstable_undeclared)] to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_undeclared' (see issue #38412) + --> $DIR/explore-issue-38412.rs:58:7 + | +LL | r.unstable_undeclared(); //~ ERROR use of unstable library feature + | ^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(unstable_undeclared)] to the crate attributes to enable + +error[E0624]: method `pub_crate` is private + --> $DIR/explore-issue-38412.rs:60:7 + | +LL | r.pub_crate(); //~ ERROR `pub_crate` is private + | ^^^^^^^^^ + +error[E0624]: method `pub_mod` is private + --> $DIR/explore-issue-38412.rs:61:7 + | +LL | r.pub_mod(); //~ ERROR `pub_mod` is private + | ^^^^^^^ + +error[E0624]: method `private` is private + --> $DIR/explore-issue-38412.rs:62:7 + | +LL | r.private(); //~ ERROR `private` is private + | ^^^^^^^ + +error[E0658]: use of unstable library feature 'unstable_undeclared' (see issue #38412) + --> $DIR/explore-issue-38412.rs:67:7 + | +LL | t.unstable_undeclared_trait_method(); //~ ERROR use of unstable library feature + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(unstable_undeclared)] to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_undeclared' (see issue #38412) + --> $DIR/explore-issue-38412.rs:71:7 + | +LL | t.unstable_undeclared(); //~ ERROR use of unstable library feature + | ^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(unstable_undeclared)] to the crate attributes to enable + +error[E0624]: method `pub_crate` is private + --> $DIR/explore-issue-38412.rs:73:7 + | +LL | t.pub_crate(); //~ ERROR `pub_crate` is private + | ^^^^^^^^^ + +error[E0624]: method `pub_mod` is private + --> $DIR/explore-issue-38412.rs:74:7 + | +LL | t.pub_mod(); //~ ERROR `pub_mod` is private + | ^^^^^^^ + +error[E0624]: method `private` is private + --> $DIR/explore-issue-38412.rs:75:7 + | +LL | t.private(); //~ ERROR `private` is private + | ^^^^^^^ + +error: aborting due to 19 previous errors + +Some errors occurred: E0616, E0624, E0658. +For more information about an error, try `rustc --explain E0616`. diff --git a/src/test/ui/extern/auxiliary/invalid-utf8.txt b/src/test/ui/extern/auxiliary/invalid-utf8.txt new file mode 100644 index 00000000000..dc1115b82db --- /dev/null +++ b/src/test/ui/extern/auxiliary/invalid-utf8.txt @@ -0,0 +1 @@ +Ã( \ No newline at end of file diff --git a/src/test/ui/extern/extern-const.fixed b/src/test/ui/extern/extern-const.fixed index dca5698a70c..fb17934fa9b 100644 --- a/src/test/ui/extern/extern-const.fixed +++ b/src/test/ui/extern/extern-const.fixed @@ -7,7 +7,7 @@ // run-rustfix // ignore-wasm32 no external library to link to. // compile-flags: -g -Z continue-parse-after-error -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; #[link(name = "rust_test_helpers", kind = "static")] diff --git a/src/test/ui/extern/extern-const.rs b/src/test/ui/extern/extern-const.rs index 07dbe545a85..f2585f5199e 100644 --- a/src/test/ui/extern/extern-const.rs +++ b/src/test/ui/extern/extern-const.rs @@ -7,7 +7,7 @@ // run-rustfix // ignore-wasm32 no external library to link to. // compile-flags: -g -Z continue-parse-after-error -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; #[link(name = "rust_test_helpers", kind = "static")] diff --git a/src/test/ui/extern/external-doc-error.rs b/src/test/ui/extern/external-doc-error.rs index 5c6f6e49b3d..e17dda65568 100644 --- a/src/test/ui/extern/external-doc-error.rs +++ b/src/test/ui/extern/external-doc-error.rs @@ -2,7 +2,31 @@ #![feature(external_doc)] -#[doc(include = "not-a-file.md")] //~ ERROR: couldn't read -pub struct SomeStruct; +#[doc(include = "not-a-file.md")] +pub struct SomeStruct; //~^ ERROR couldn't read + //~| HELP external doc paths are relative to the crate root + +#[doc(include = "auxiliary/invalid-utf8.txt")] +pub struct InvalidUtf8; //~^ ERROR wasn't a utf-8 file + +#[doc(include)] +pub struct MissingPath; //~^ ERROR expected path + //~| HELP provide a file path with `=` + //~| SUGGESTION include = "" + +#[doc(include("../README.md"))] +pub struct InvalidPathSyntax; //~^ ERROR expected path + //~| HELP provide a file path with `=` + //~| SUGGESTION include = "../README.md" + +#[doc(include = 123)] +pub struct InvalidPathType; //~^ ERROR expected path + //~| HELP provide a file path with `=` + //~| SUGGESTION include = "" + +#[doc(include(123))] +pub struct InvalidPathSyntaxAndType; //~^ ERROR expected path + //~| HELP provide a file path with `=` + //~| SUGGESTION include = "" fn main() {} diff --git a/src/test/ui/extern/external-doc-error.stderr b/src/test/ui/extern/external-doc-error.stderr index 5cc7551ee03..a3be3277de5 100644 --- a/src/test/ui/extern/external-doc-error.stderr +++ b/src/test/ui/extern/external-doc-error.stderr @@ -1,8 +1,40 @@ error: couldn't read $DIR/not-a-file.md: $FILE_NOT_FOUND_MSG (os error 2) - --> $DIR/external-doc-error.rs:5:1 + --> $DIR/external-doc-error.rs:5:17 | -LL | #[doc(include = "not-a-file.md")] //~ ERROR: couldn't read - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[doc(include = "not-a-file.md")] + | ^^^^^^^^^^^^^^^ couldn't read file + | + = help: external doc paths are relative to the crate root -error: aborting due to previous error +error: $DIR/auxiliary/invalid-utf8.txt wasn't a utf-8 file + --> $DIR/external-doc-error.rs:9:17 + | +LL | #[doc(include = "auxiliary/invalid-utf8.txt")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ contains invalid utf-8 + +error: expected path to external documentation + --> $DIR/external-doc-error.rs:12:7 + | +LL | #[doc(include)] + | ^^^^^^^ help: provide a file path with `=`: `include = ""` + +error: expected path to external documentation + --> $DIR/external-doc-error.rs:17:7 + | +LL | #[doc(include("../README.md"))] + | ^^^^^^^^^^^^^^^^^^^^^^^ help: provide a file path with `=`: `include = "../README.md"` + +error: expected path to external documentation + --> $DIR/external-doc-error.rs:22:7 + | +LL | #[doc(include = 123)] + | ^^^^^^^^^^^^^ help: provide a file path with `=`: `include = ""` + +error: expected path to external documentation + --> $DIR/external-doc-error.rs:27:7 + | +LL | #[doc(include(123))] + | ^^^^^^^^^^^^ help: provide a file path with `=`: `include = ""` + +error: aborting due to 6 previous errors diff --git a/src/test/ui/feature-gate-exhaustive_integer_patterns.stderr b/src/test/ui/feature-gate-exhaustive_integer_patterns.stderr deleted file mode 100644 index 63d98f6b5eb..00000000000 --- a/src/test/ui/feature-gate-exhaustive_integer_patterns.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/feature-gate-exhaustive_integer_patterns.rs:13:11 - | -LL | match x { //~ ERROR non-exhaustive patterns: `_` not covered - | ^ pattern `_` not covered - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.rs b/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.rs index ff0306f1993..84cd5c2bffa 100644 --- a/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.rs +++ b/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.rs @@ -8,20 +8,32 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::rc::Rc; +use std::{ + ops::Deref, +}; + +struct Ptr(Box); + +impl Deref for Ptr { + type Target = T; + + fn deref(&self) -> &T { + &*self.0 + } +} trait Foo { - fn foo(self: Rc>); //~ ERROR arbitrary `self` types are unstable + fn foo(self: Ptr); //~ ERROR `Ptr` cannot be used as the type of `self` without } struct Bar; impl Foo for Bar { - fn foo(self: Rc>) {} //~ ERROR arbitrary `self` types are unstable + fn foo(self: Ptr) {} //~ ERROR `Ptr` cannot be used as the type of `self` without } impl Bar { - fn bar(self: Box>) {} //~ ERROR arbitrary `self` types are unstable + fn bar(self: Box>) {} //~ ERROR `std::boxed::Box>` cannot be used as the } fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.stderr b/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.stderr index ea259aa22ad..c70774b3710 100644 --- a/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.stderr +++ b/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.stderr @@ -1,26 +1,26 @@ -error[E0658]: arbitrary `self` types are unstable (see issue #44874) - --> $DIR/feature-gate-arbitrary-self-types.rs:14:18 +error[E0658]: `Ptr` cannot be used as the type of `self` without the `arbitrary_self_types` feature (see issue #44874) + --> $DIR/feature-gate-arbitrary-self-types.rs:26:18 | -LL | fn foo(self: Rc>); //~ ERROR arbitrary `self` types are unstable - | ^^^^^^^^^^^^^ +LL | fn foo(self: Ptr); //~ ERROR `Ptr` cannot be used as the type of `self` without + | ^^^^^^^^^ | = help: add #![feature(arbitrary_self_types)] to the crate attributes to enable = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box` -error[E0658]: arbitrary `self` types are unstable (see issue #44874) - --> $DIR/feature-gate-arbitrary-self-types.rs:20:18 +error[E0658]: `Ptr` cannot be used as the type of `self` without the `arbitrary_self_types` feature (see issue #44874) + --> $DIR/feature-gate-arbitrary-self-types.rs:32:18 | -LL | fn foo(self: Rc>) {} //~ ERROR arbitrary `self` types are unstable - | ^^^^^^^^^^^^^ +LL | fn foo(self: Ptr) {} //~ ERROR `Ptr` cannot be used as the type of `self` without + | ^^^^^^^^^ | = help: add #![feature(arbitrary_self_types)] to the crate attributes to enable = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box` -error[E0658]: arbitrary `self` types are unstable (see issue #44874) - --> $DIR/feature-gate-arbitrary-self-types.rs:24:18 +error[E0658]: `std::boxed::Box>` cannot be used as the type of `self` without the `arbitrary_self_types` feature (see issue #44874) + --> $DIR/feature-gate-arbitrary-self-types.rs:36:18 | -LL | fn bar(self: Box>) {} //~ ERROR arbitrary `self` types are unstable - | ^^^^^^^^^^^^^ +LL | fn bar(self: Box>) {} //~ ERROR `std::boxed::Box>` cannot be used as the + | ^^^^^^^^^^^^^^ | = help: add #![feature(arbitrary_self_types)] to the crate attributes to enable = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box` diff --git a/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.rs b/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.rs index 29e51727edc..6d42460ba56 100644 --- a/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.rs +++ b/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.rs @@ -12,17 +12,17 @@ struct Foo; impl Foo { fn foo(self: *const Self) {} - //~^ ERROR raw pointer `self` is unstable + //~^ ERROR `*const Foo` cannot be used as the type of `self` without } trait Bar { fn bar(self: *const Self); - //~^ ERROR raw pointer `self` is unstable + //~^ ERROR `*const Self` cannot be used as the type of `self` without } impl Bar for () { fn bar(self: *const Self) {} - //~^ ERROR raw pointer `self` is unstable + //~^ ERROR `*const ()` cannot be used as the type of `self` without } fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr b/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr index 5ed9a0f4ed0..b8cc7dee986 100644 --- a/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr +++ b/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr @@ -1,4 +1,4 @@ -error[E0658]: raw pointer `self` is unstable (see issue #44874) +error[E0658]: `*const Self` cannot be used as the type of `self` without the `arbitrary_self_types` feature (see issue #44874) --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:19:18 | LL | fn bar(self: *const Self); @@ -7,7 +7,7 @@ LL | fn bar(self: *const Self); = help: add #![feature(arbitrary_self_types)] to the crate attributes to enable = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box` -error[E0658]: raw pointer `self` is unstable (see issue #44874) +error[E0658]: `*const Foo` cannot be used as the type of `self` without the `arbitrary_self_types` feature (see issue #44874) --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:14:18 | LL | fn foo(self: *const Self) {} @@ -16,7 +16,7 @@ LL | fn foo(self: *const Self) {} = help: add #![feature(arbitrary_self_types)] to the crate attributes to enable = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box` -error[E0658]: raw pointer `self` is unstable (see issue #44874) +error[E0658]: `*const ()` cannot be used as the type of `self` without the `arbitrary_self_types` feature (see issue #44874) --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:24:18 | LL | fn bar(self: *const Self) {} diff --git a/src/test/ui/feature-gates/feature-gate-const_let.rs b/src/test/ui/feature-gates/feature-gate-const_let.rs index 05d02e62bc8..9bf957a5f1e 100644 --- a/src/test/ui/feature-gates/feature-gate-const_let.rs +++ b/src/test/ui/feature-gates/feature-gate-const_let.rs @@ -10,13 +10,22 @@ // Test use of const let without feature gate. -#![feature(const_fn)] - -const fn foo() -> usize { +const FOO: usize = { + //~^ ERROR statements in constants are unstable + //~| ERROR: let bindings in constants are unstable let x = 42; - //~^ ERROR statements in constant functions are unstable - //~| ERROR: let bindings in constant functions are unstable + //~^ ERROR statements in constants are unstable + //~| ERROR: let bindings in constants are unstable 42 -} +}; + +static BAR: usize = { + //~^ ERROR statements in statics are unstable + //~| ERROR: let bindings in statics are unstable + let x = 42; + //~^ ERROR statements in statics are unstable + //~| ERROR: let bindings in statics are unstable + 42 +}; fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-const_let.stderr b/src/test/ui/feature-gates/feature-gate-const_let.stderr index 6a7f6255678..acb5165918e 100644 --- a/src/test/ui/feature-gates/feature-gate-const_let.stderr +++ b/src/test/ui/feature-gates/feature-gate-const_let.stderr @@ -1,4 +1,4 @@ -error[E0658]: let bindings in constant functions are unstable (see issue #48821) +error[E0658]: let bindings in constants are unstable (see issue #48821) --> $DIR/feature-gate-const_let.rs:16:13 | LL | let x = 42; @@ -6,7 +6,7 @@ LL | let x = 42; | = help: add #![feature(const_let)] to the crate attributes to enable -error[E0658]: statements in constant functions are unstable (see issue #48821) +error[E0658]: statements in constants are unstable (see issue #48821) --> $DIR/feature-gate-const_let.rs:16:13 | LL | let x = 42; @@ -14,6 +14,78 @@ LL | let x = 42; | = help: add #![feature(const_let)] to the crate attributes to enable -error: aborting due to 2 previous errors +error[E0658]: let bindings in constants are unstable (see issue #48821) + --> $DIR/feature-gate-const_let.rs:13:1 + | +LL | / const FOO: usize = { +LL | | //~^ ERROR statements in constants are unstable +LL | | //~| ERROR: let bindings in constants are unstable +LL | | let x = 42; +... | +LL | | 42 +LL | | }; + | |__^ + | + = help: add #![feature(const_let)] to the crate attributes to enable + +error[E0658]: statements in constants are unstable (see issue #48821) + --> $DIR/feature-gate-const_let.rs:13:1 + | +LL | / const FOO: usize = { +LL | | //~^ ERROR statements in constants are unstable +LL | | //~| ERROR: let bindings in constants are unstable +LL | | let x = 42; +... | +LL | | 42 +LL | | }; + | |__^ + | + = help: add #![feature(const_let)] to the crate attributes to enable + +error[E0658]: let bindings in statics are unstable (see issue #48821) + --> $DIR/feature-gate-const_let.rs:25:13 + | +LL | let x = 42; + | ^^ + | + = help: add #![feature(const_let)] to the crate attributes to enable + +error[E0658]: statements in statics are unstable (see issue #48821) + --> $DIR/feature-gate-const_let.rs:25:13 + | +LL | let x = 42; + | ^^ + | + = help: add #![feature(const_let)] to the crate attributes to enable + +error[E0658]: let bindings in statics are unstable (see issue #48821) + --> $DIR/feature-gate-const_let.rs:22:1 + | +LL | / static BAR: usize = { +LL | | //~^ ERROR statements in statics are unstable +LL | | //~| ERROR: let bindings in statics are unstable +LL | | let x = 42; +... | +LL | | 42 +LL | | }; + | |__^ + | + = help: add #![feature(const_let)] to the crate attributes to enable + +error[E0658]: statements in statics are unstable (see issue #48821) + --> $DIR/feature-gate-const_let.rs:22:1 + | +LL | / static BAR: usize = { +LL | | //~^ ERROR statements in statics are unstable +LL | | //~| ERROR: let bindings in statics are unstable +LL | | let x = 42; +... | +LL | | 42 +LL | | }; + | |__^ + | + = help: add #![feature(const_let)] to the crate attributes to enable + +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-custom_derive.stderr b/src/test/ui/feature-gates/feature-gate-custom_derive.stderr deleted file mode 100644 index 0979372daea..00000000000 --- a/src/test/ui/feature-gates/feature-gate-custom_derive.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0658]: attributes of the form `#[derive_*]` are reserved for the compiler (see issue #29644) - --> $DIR/feature-gate-custom_derive.rs:11:3 - | -LL | #[derive_Clone] - | ^^^^^^^^^^^^ - | - = help: add #![feature(custom_derive)] 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-linker-flavor.stderr b/src/test/ui/feature-gates/feature-gate-linker-flavor.stderr deleted file mode 100644 index 7019a666548..00000000000 --- a/src/test/ui/feature-gates/feature-gate-linker-flavor.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: attribute must be applied to a `static` variable - --> $DIR/feature-gate-linker-flavor.rs:16:1 - | -LL | #[used] - | ^^^^^^^ - -error: aborting due to previous error - diff --git a/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.rs b/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.rs new file mode 100644 index 00000000000..1208552d256 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.rs @@ -0,0 +1,14 @@ +#![feature(exclusive_range_pattern)] + +use std::usize::MAX; + +fn main() { + match 0usize { //~ERROR non-exhaustive patterns: `_` not covered + 0..=MAX => {} + } + + match 0isize { //~ERROR non-exhaustive patterns: `_` not covered + 1..=20 => {} + -5..3 => {} + } +} diff --git a/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr b/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr new file mode 100644 index 00000000000..5806f6f0391 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr @@ -0,0 +1,15 @@ +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/feature-gate-precise_pointer_size_matching.rs:6:11 + | +LL | match 0usize { //~ERROR non-exhaustive patterns: `_` not covered + | ^^^^^^ pattern `_` not covered + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/feature-gate-precise_pointer_size_matching.rs:10:11 + | +LL | match 0isize { //~ERROR non-exhaustive patterns: `_` not covered + | ^^^^^^ pattern `_` not covered + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/feature-gates/feature-gate-repr_packed.stderr b/src/test/ui/feature-gates/feature-gate-repr_packed.stderr deleted file mode 100644 index ed89a3f6b31..00000000000 --- a/src/test/ui/feature-gates/feature-gate-repr_packed.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0658]: the `#[repr(packed(n))]` attribute is experimental (see issue #33158) - --> $DIR/feature-gate-repr_packed.rs:11:1 - | -LL | #[repr(packed(1))] //~ error: the `#[repr(packed(n))]` attribute is experimental - | ^^^^^^^^^^^^^^^^^^ - | - = help: add #![feature(repr_packed)] to the crate attributes to enable - -error[E0658]: the `#[repr(packed(n))]` attribute is experimental (see issue #33158) - --> $DIR/feature-gate-repr_packed.rs:15:1 - | -LL | #[repr(packed(1))] //~ error: the `#[repr(packed(n))]` attribute is experimental - | ^^^^^^^^^^^^^^^^^^ - | - = help: add #![feature(repr_packed)] to the crate attributes to enable - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-underscore-imports.stderr b/src/test/ui/feature-gates/feature-gate-underscore-imports.stderr deleted file mode 100644 index 2eea95260d5..00000000000 --- a/src/test/ui/feature-gates/feature-gate-underscore-imports.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0658]: renaming extern crates with `_` is unstable (see issue #48216) - --> $DIR/feature-gate-underscore-imports.rs:11:1 - | -LL | extern crate std as _; //~ ERROR renaming extern crates with `_` is unstable - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = help: add #![feature(underscore_imports)] to the crate attributes to enable - -error[E0658]: renaming imports with `_` is unstable (see issue #48216) - --> $DIR/feature-gate-underscore-imports.rs:12:5 - | -LL | use std::vec as _; //~ ERROR renaming imports with `_` is unstable - | ^^^^^^^^^^^^^ - | - = help: add #![feature(underscore_imports)] to the crate attributes to enable - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-uniform-paths.stderr b/src/test/ui/feature-gates/feature-gate-uniform-paths.stderr index ec8937bbc5f..0631f2c355f 100644 --- a/src/test/ui/feature-gates/feature-gate-uniform-paths.stderr +++ b/src/test/ui/feature-gates/feature-gate-uniform-paths.stderr @@ -25,11 +25,7 @@ LL | use inline; //~ ERROR imports can only refer to extern crate names | ^^^^^^ not an extern crate passed with `--extern` | = help: add #![feature(uniform_paths)] to the crate attributes to enable -note: this import refers to the built-in attribute imported here - --> $DIR/feature-gate-uniform-paths.rs:21:5 - | -LL | use inline; //~ ERROR imports can only refer to extern crate names - | ^^^^^^ + = note: this import refers to a built-in attribute error[E0658]: imports can only refer to extern crate names passed with `--extern` on stable channel (see issue #53130) --> $DIR/feature-gate-uniform-paths.rs:23:5 @@ -38,11 +34,7 @@ LL | use Vec; //~ ERROR imports can only refer to extern crate names | ^^^ not an extern crate passed with `--extern` | = help: add #![feature(uniform_paths)] to the crate attributes to enable -note: this import refers to the struct imported here - --> $DIR/feature-gate-uniform-paths.rs:23:5 - | -LL | use Vec; //~ ERROR imports can only refer to extern crate names - | ^^^ + = note: this import refers to a struct from prelude error[E0658]: imports can only refer to extern crate names passed with `--extern` on stable channel (see issue #53130) --> $DIR/feature-gate-uniform-paths.rs:25:5 @@ -51,11 +43,7 @@ LL | use vec; //~ ERROR imports can only refer to extern crate names | ^^^ not an extern crate passed with `--extern` | = help: add #![feature(uniform_paths)] to the crate attributes to enable -note: this import refers to the macro imported here - --> $DIR/feature-gate-uniform-paths.rs:25:5 - | -LL | use vec; //~ ERROR imports can only refer to extern crate names - | ^^^ + = note: this import refers to a macro from prelude error: aborting due to 4 previous errors diff --git a/src/test/ui/underscore_const_names_feature_gate.rs b/src/test/ui/feature-gates/underscore_const_names_feature_gate.rs similarity index 92% rename from src/test/ui/underscore_const_names_feature_gate.rs rename to src/test/ui/feature-gates/underscore_const_names_feature_gate.rs index b2174036ded..b41e3503d7a 100644 --- a/src/test/ui/underscore_const_names_feature_gate.rs +++ b/src/test/ui/feature-gates/underscore_const_names_feature_gate.rs @@ -9,6 +9,5 @@ // except according to those terms. const _: () = (); //~ ERROR is unstable -static _: () = (); //~ ERROR is unstable fn main() {} diff --git a/src/test/ui/underscore_const_names_feature_gate.stderr b/src/test/ui/feature-gates/underscore_const_names_feature_gate.stderr similarity index 51% rename from src/test/ui/underscore_const_names_feature_gate.stderr rename to src/test/ui/feature-gates/underscore_const_names_feature_gate.stderr index c97b3f8d4d3..192cc258cf4 100644 --- a/src/test/ui/underscore_const_names_feature_gate.stderr +++ b/src/test/ui/feature-gates/underscore_const_names_feature_gate.stderr @@ -6,14 +6,6 @@ LL | const _: () = (); //~ ERROR is unstable | = help: add #![feature(underscore_const_names)] to the crate attributes to enable -error[E0658]: naming constants with `_` is unstable (see issue #54912) - --> $DIR/underscore_const_names_feature_gate.rs:12:1 - | -LL | static _: () = (); //~ ERROR is unstable - | ^^^^^^^^^^^^^^^^^^ - | - = help: add #![feature(underscore_const_names)] to the crate attributes to enable - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/for/for-loop-refutable-pattern-error-message.stderr b/src/test/ui/for/for-loop-refutable-pattern-error-message.stderr index b76c2ffc240..9b19fc80e2b 100644 --- a/src/test/ui/for/for-loop-refutable-pattern-error-message.stderr +++ b/src/test/ui/for/for-loop-refutable-pattern-error-message.stderr @@ -1,8 +1,8 @@ -error[E0005]: refutable pattern in `for` loop binding: `&_` not covered +error[E0005]: refutable pattern in `for` loop binding: `&-2147483648i32..=0i32` not covered --> $DIR/for-loop-refutable-pattern-error-message.rs:12:9 | LL | for &1 in [1].iter() {} //~ ERROR refutable pattern in `for` loop binding - | ^^ pattern `&_` not covered + | ^^ pattern `&-2147483648i32..=0i32` not covered error: aborting due to previous error diff --git a/src/test/ui/generator/yield-while-ref-reborrowed.nll.stderr b/src/test/ui/generator/yield-while-ref-reborrowed.nll.stderr index 8dabb3c2505..60163d78e78 100644 --- a/src/test/ui/generator/yield-while-ref-reborrowed.nll.stderr +++ b/src/test/ui/generator/yield-while-ref-reborrowed.nll.stderr @@ -7,7 +7,7 @@ LL | let a = &mut *x; | - first borrow occurs due to use of `x` in generator ... LL | println!("{}", x); //~ ERROR - | ^ borrow occurs here + | ^ second borrow occurs here LL | b.resume(); | - first borrow later used here diff --git a/src/test/ui/imports/issue-56125.rs b/src/test/ui/imports/issue-56125.rs index 843b52f1843..0327522e4b8 100644 --- a/src/test/ui/imports/issue-56125.rs +++ b/src/test/ui/imports/issue-56125.rs @@ -7,13 +7,11 @@ mod m1 { use issue_56125::last_segment::*; //~^ ERROR `issue_56125` is ambiguous - //~| ERROR unresolved import `issue_56125::last_segment` } mod m2 { use issue_56125::non_last_segment::non_last_segment::*; //~^ ERROR `issue_56125` is ambiguous - //~| ERROR failed to resolve: could not find `non_last_segment` in `issue_56125` } mod m3 { diff --git a/src/test/ui/imports/issue-56125.stderr b/src/test/ui/imports/issue-56125.stderr index b1292ef8f78..559979e5d51 100644 --- a/src/test/ui/imports/issue-56125.stderr +++ b/src/test/ui/imports/issue-56125.stderr @@ -1,17 +1,5 @@ -error[E0433]: failed to resolve: could not find `non_last_segment` in `issue_56125` - --> $DIR/issue-56125.rs:14:22 - | -LL | use issue_56125::non_last_segment::non_last_segment::*; - | ^^^^^^^^^^^^^^^^ could not find `non_last_segment` in `issue_56125` - -error[E0432]: unresolved import `issue_56125::last_segment` - --> $DIR/issue-56125.rs:8:22 - | -LL | use issue_56125::last_segment::*; - | ^^^^^^^^^^^^ could not find `last_segment` in `issue_56125` - error[E0432]: unresolved import `empty::issue_56125` - --> $DIR/issue-56125.rs:21:9 + --> $DIR/issue-56125.rs:19:9 | LL | use empty::issue_56125; //~ ERROR unresolved import `empty::issue_56125` | ^^^^^^^^^^^^^^^^^^ no `issue_56125` in `m3::empty` @@ -32,7 +20,7 @@ LL | use issue_56125::last_segment::*; = help: use `self::issue_56125` to refer to this module unambiguously error[E0659]: `issue_56125` is ambiguous (name vs any other name during import resolution) - --> $DIR/issue-56125.rs:14:9 + --> $DIR/issue-56125.rs:13:9 | LL | use issue_56125::non_last_segment::non_last_segment::*; | ^^^^^^^^^^^ ambiguous name @@ -40,14 +28,14 @@ LL | use issue_56125::non_last_segment::non_last_segment::*; = note: `issue_56125` could refer to an extern crate passed with `--extern` = help: use `::issue_56125` to refer to this extern crate unambiguously note: `issue_56125` could also refer to the module imported here - --> $DIR/issue-56125.rs:14:9 + --> $DIR/issue-56125.rs:13:9 | LL | use issue_56125::non_last_segment::non_last_segment::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: use `self::issue_56125` to refer to this module unambiguously error[E0659]: `issue_56125` is ambiguous (name vs any other name during import resolution) - --> $DIR/issue-56125.rs:22:9 + --> $DIR/issue-56125.rs:20:9 | LL | use issue_56125::*; //~ ERROR `issue_56125` is ambiguous | ^^^^^^^^^^^ ambiguous name @@ -55,13 +43,13 @@ LL | use issue_56125::*; //~ ERROR `issue_56125` is ambiguous = note: `issue_56125` could refer to an extern crate passed with `--extern` = help: use `::issue_56125` to refer to this extern crate unambiguously note: `issue_56125` could also refer to the unresolved item imported here - --> $DIR/issue-56125.rs:21:9 + --> $DIR/issue-56125.rs:19:9 | LL | use empty::issue_56125; //~ ERROR unresolved import `empty::issue_56125` | ^^^^^^^^^^^^^^^^^^ = help: use `self::issue_56125` to refer to this unresolved item unambiguously -error: aborting due to 6 previous errors +error: aborting due to 4 previous errors -Some errors occurred: E0432, E0433, E0659. +Some errors occurred: E0432, E0659. For more information about an error, try `rustc --explain E0432`. diff --git a/src/test/ui/imports/unused.rs b/src/test/ui/imports/unused.rs index 1eb756fe9e4..d241ab62976 100644 --- a/src/test/ui/imports/unused.rs +++ b/src/test/ui/imports/unused.rs @@ -23,7 +23,7 @@ mod foo { } mod m3 { - pub(super) use super::f; // Check that this is counted as used (c.f. #36249). + pub(super) use super::f; // Check that this is counted as used (cf. issue #36249). } pub mod m4 { diff --git a/src/test/compile-fail-fulldeps/issue-18986.rs b/src/test/ui/issue-18986.rs similarity index 100% rename from src/test/compile-fail-fulldeps/issue-18986.rs rename to src/test/ui/issue-18986.rs diff --git a/src/test/ui/issue-18986.stderr b/src/test/ui/issue-18986.stderr new file mode 100644 index 00000000000..241cc4250a3 --- /dev/null +++ b/src/test/ui/issue-18986.stderr @@ -0,0 +1,9 @@ +error[E0574]: expected struct, variant or union type, found trait `Trait` + --> $DIR/issue-18986.rs:18:9 + | +LL | Trait { x: 42 } => () //~ ERROR expected struct, variant or union type, found trait `Trait` + | ^^^^^ not a struct, variant or union type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0574`. diff --git a/src/test/ui/issue-55846.rs b/src/test/ui/issue-55846.rs new file mode 100644 index 00000000000..bd766752360 --- /dev/null +++ b/src/test/ui/issue-55846.rs @@ -0,0 +1,39 @@ +// run-pass + +// Regression test for #55846, which once caused an ICE. + +use std::marker::PhantomData; + +struct Foo; + +struct Bar { + a: PhantomData, +} + +impl Fooifier for Foo { + type Assoc = Foo; +} + +trait Fooifier { + type Assoc; +} + +trait Barifier { + fn barify(); +} + +impl Barifier for Bar { + fn barify() { + println!("All correct!"); + } +} + +impl Bar<::Assoc> { + fn this_shouldnt_crash() { + ::Assoc>>::barify(); + } +} + +fn main() { + Bar::::this_shouldnt_crash(); +} diff --git a/src/test/ui/issues/issue-1251.rs b/src/test/ui/issues/issue-1251.rs index b42404ce773..125f6e1faa6 100644 --- a/src/test/ui/issues/issue-1251.rs +++ b/src/test/ui/issues/issue-1251.rs @@ -14,7 +14,7 @@ // pretty-expanded FIXME #23616 // ignore-wasm32-bare no libc to test ffi with -#![feature(libc)] +#![feature(rustc_private)] #![crate_id="rust_get_test_int"] diff --git a/src/test/ui/issues/issue-20261.rs b/src/test/ui/issues/issue-20261.rs index bb4dbdcd0cb..0330ac658d8 100644 --- a/src/test/ui/issues/issue-20261.rs +++ b/src/test/ui/issues/issue-20261.rs @@ -9,7 +9,7 @@ // except according to those terms. fn main() { - // NB: this (almost) typechecks when default binding modes are enabled. + // N.B., this (almost) typechecks when default binding modes are enabled. for (ref i,) in [].iter() { i.clone(); //~^ ERROR type annotations needed diff --git a/src/test/ui/issues/issue-22034.rs b/src/test/ui/issues/issue-22034.rs index 2708de2c13a..bee324f8746 100644 --- a/src/test/ui/issues/issue-22034.rs +++ b/src/test/ui/issues/issue-22034.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; diff --git a/src/test/ui/issues/issue-27842.stderr b/src/test/ui/issues/issue-27842.stderr index 026594811e4..dea7acd9bf8 100644 --- a/src/test/ui/issues/issue-27842.stderr +++ b/src/test/ui/issues/issue-27842.stderr @@ -10,7 +10,7 @@ error[E0608]: cannot index into a value of type `({integer}, {integer}, {integer LL | let _ = tup[i]; | ^^^^^^ | - = help: to access tuple elements, use tuple indexing syntax (e.g. `tuple.0`) + = help: to access tuple elements, use tuple indexing syntax (e.g., `tuple.0`) error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr index e2630b5b8ce..ed6b325a01d 100644 --- a/src/test/ui/issues/issue-31173.stderr +++ b/src/test/ui/issues/issue-31173.stderr @@ -14,8 +14,8 @@ LL | .collect(); //~ ERROR no method named `collect` | ^^^^^^^ | = note: the method `collect` exists but the following trait bounds were not satisfied: - `std::iter::Cloned, [closure@$DIR/issue-31173.rs:16:39: 19:6 found_e:_]>> : std::iter::Iterator` `&mut std::iter::Cloned, [closure@$DIR/issue-31173.rs:16:39: 19:6 found_e:_]>> : std::iter::Iterator` + `std::iter::Cloned, [closure@$DIR/issue-31173.rs:16:39: 19:6 found_e:_]>> : std::iter::Iterator` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-32655.rs b/src/test/ui/issues/issue-32655.rs index 25ecd5d0862..bbe95a4371e 100644 --- a/src/test/ui/issues/issue-32655.rs +++ b/src/test/ui/issues/issue-32655.rs @@ -13,7 +13,7 @@ macro_rules! foo ( () => ( - #[derive_Clone] //~ ERROR attributes of the form + #[derive_Clone] //~ ERROR attribute `derive_Clone` is currently unknown struct T; ); ); @@ -25,7 +25,7 @@ macro_rules! bar ( foo!(); bar!( - #[derive_Clone] //~ ERROR attributes of the form + #[derive_Clone] //~ ERROR attribute `derive_Clone` is currently unknown struct S; ); diff --git a/src/test/ui/issues/issue-32655.stderr b/src/test/ui/issues/issue-32655.stderr index f930217fe9e..88da51a478a 100644 --- a/src/test/ui/issues/issue-32655.stderr +++ b/src/test/ui/issues/issue-32655.stderr @@ -1,21 +1,21 @@ -error[E0658]: attributes of the form `#[derive_*]` are reserved for the compiler (see issue #29644) +error[E0658]: The attribute `derive_Clone` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) --> $DIR/issue-32655.rs:16:11 | -LL | #[derive_Clone] //~ ERROR attributes of the form +LL | #[derive_Clone] //~ ERROR attribute `derive_Clone` is currently unknown | ^^^^^^^^^^^^ ... LL | foo!(); | ------- in this macro invocation | - = help: add #![feature(custom_derive)] to the crate attributes to enable + = help: add #![feature(custom_attribute)] to the crate attributes to enable -error[E0658]: attributes of the form `#[derive_*]` are reserved for the compiler (see issue #29644) +error[E0658]: The attribute `derive_Clone` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) --> $DIR/issue-32655.rs:28:7 | -LL | #[derive_Clone] //~ ERROR attributes of the form +LL | #[derive_Clone] //~ ERROR attribute `derive_Clone` is currently unknown | ^^^^^^^^^^^^ | - = help: add #![feature(custom_derive)] to the crate attributes to enable + = help: add #![feature(custom_attribute)] to the crate attributes to enable error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-33140.rs b/src/test/ui/issues/issue-33140.rs new file mode 100644 index 00000000000..fef5a82d9f8 --- /dev/null +++ b/src/test/ui/issues/issue-33140.rs @@ -0,0 +1,62 @@ +// 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. + +#![deny(order_dependent_trait_objects)] + +trait Trait { + fn xyz() -> bool; +} + +impl Trait for dyn Send + Sync { + fn xyz() -> bool { false } +} + +impl Trait for dyn Sync + Send { +//~^ ERROR conflicting implementations +//~| hard error + fn xyz() -> bool { true } +} + +trait Trait2 { + fn uvw() -> bool; +} + +impl Trait2 for dyn Send + Sync { + fn uvw() -> bool { false } +} + +impl Trait2 for dyn Sync + Send + Sync { +//~^ ERROR conflicting implementations +//~| hard error + fn uvw() -> bool { true } +} + +struct Foo(T); +impl Foo { + fn abc() -> bool { //~ ERROR duplicate definitions with name `abc` + //~| hard error + false + } +} + +impl Foo { + fn abc() -> bool { + true + } +} + +fn main() { + assert_eq!(::xyz(), false); + assert_eq!(::xyz(), true); + assert_eq!(::uvw(), false); + assert_eq!(::uvw(), true); + assert_eq!(>::abc(), false); + assert_eq!(>::abc(), true); +} diff --git a/src/test/ui/issues/issue-33140.stderr b/src/test/ui/issues/issue-33140.stderr new file mode 100644 index 00000000000..240137f863a --- /dev/null +++ b/src/test/ui/issues/issue-33140.stderr @@ -0,0 +1,48 @@ +error: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119) + --> $DIR/issue-33140.rs:21:1 + | +LL | impl Trait for dyn Send + Sync { + | ------------------------------ first implementation here +... +LL | impl Trait for dyn Sync + Send { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)` + | +note: lint level defined here + --> $DIR/issue-33140.rs:11:9 + | +LL | #![deny(order_dependent_trait_objects)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 + +error: conflicting implementations of trait `Trait2` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119) + --> $DIR/issue-33140.rs:35:1 + | +LL | impl Trait2 for dyn Send + Sync { + | ------------------------------- first implementation here +... +LL | impl Trait2 for dyn Sync + Send + Sync { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 + +error: duplicate definitions with name `abc` (E0592) + --> $DIR/issue-33140.rs:43:5 + | +LL | / fn abc() -> bool { //~ ERROR duplicate definitions with name `abc` +LL | | //~| hard error +LL | | false +LL | | } + | |_____^ duplicate definitions for `abc` +... +LL | / fn abc() -> bool { +LL | | true +LL | | } + | |_____- other definition for `abc` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/issues/issue-35677.rs b/src/test/ui/issues/issue-35677.rs new file mode 100644 index 00000000000..46d3f7e4af0 --- /dev/null +++ b/src/test/ui/issues/issue-35677.rs @@ -0,0 +1,5 @@ +use std::collections::HashMap; +fn intersect_map(this: &mut HashMap, other: HashMap) -> bool { + this.drain() + //~^ ERROR no method named +} diff --git a/src/test/ui/issues/issue-35677.stderr b/src/test/ui/issues/issue-35677.stderr new file mode 100644 index 00000000000..dca096b93f5 --- /dev/null +++ b/src/test/ui/issues/issue-35677.stderr @@ -0,0 +1,18 @@ +error[E0601]: `main` function not found in crate `issue_35677` + | + = note: consider adding a `main` function to `$DIR/issue-35677.rs` + +error[E0599]: no method named `drain` found for type `&mut std::collections::HashMap` in the current scope + --> $DIR/issue-35677.rs:3:10 + | +LL | this.drain() + | ^^^^^ + | + = note: the method `drain` exists but the following trait bounds were not satisfied: + `K : std::cmp::Eq` + `K : std::hash::Hash` + +error: aborting due to 2 previous errors + +Some errors occurred: E0599, E0601. +For more information about an error, try `rustc --explain E0599`. diff --git a/src/test/ui/issues/issue-36744-without-calls.rs b/src/test/ui/issues/issue-36744-without-calls.rs index 8a47ebbd0a8..c15840090ea 100644 --- a/src/test/ui/issues/issue-36744-without-calls.rs +++ b/src/test/ui/issues/issue-36744-without-calls.rs @@ -11,7 +11,7 @@ // compile-pass // Tests for an LLVM abort when storing a lifetime-parametric fn into // context that is expecting one that is not lifetime-parametric -// (i.e. has no `for <'_>`). +// (i.e., has no `for <'_>`). pub struct A<'a>(&'a ()); pub struct S(T); diff --git a/src/test/ui/issues/issue-37550.rs b/src/test/ui/issues/issue-37550.rs index af1f6ef5ed4..a2f40b3f539 100644 --- a/src/test/ui/issues/issue-37550.rs +++ b/src/test/ui/issues/issue-37550.rs @@ -8,15 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(const_fn)] - const fn x() { - let t = true; - //~^ ERROR let bindings in constant functions are unstable - //~| ERROR statements in constant functions are unstable + let t = true; //~ ERROR local variables in const fn let x = || t; - //~^ ERROR let bindings in constant functions are unstable - //~| ERROR statements in constant functions are unstable } fn main() {} diff --git a/src/test/ui/issues/issue-37550.stderr b/src/test/ui/issues/issue-37550.stderr index 7468510de6a..5a7d1ad043e 100644 --- a/src/test/ui/issues/issue-37550.stderr +++ b/src/test/ui/issues/issue-37550.stderr @@ -1,35 +1,8 @@ -error[E0658]: let bindings in constant functions are unstable (see issue #48821) - --> $DIR/issue-37550.rs:14:13 +error: local variables in const fn are unstable + --> $DIR/issue-37550.rs:12:9 | -LL | let t = true; - | ^^^^ - | - = help: add #![feature(const_let)] to the crate attributes to enable +LL | let t = true; //~ ERROR local variables in const fn + | ^ -error[E0658]: statements in constant functions are unstable (see issue #48821) - --> $DIR/issue-37550.rs:14:13 - | -LL | let t = true; - | ^^^^ - | - = help: add #![feature(const_let)] to the crate attributes to enable +error: aborting due to previous error -error[E0658]: let bindings in constant functions are unstable (see issue #48821) - --> $DIR/issue-37550.rs:17:13 - | -LL | let x = || t; - | ^^^^ - | - = help: add #![feature(const_let)] to the crate attributes to enable - -error[E0658]: statements in constant functions are unstable (see issue #48821) - --> $DIR/issue-37550.rs:17:13 - | -LL | let x = || t; - | ^^^^ - | - = help: add #![feature(const_let)] to the crate attributes to enable - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/issues/issue-37887.stderr b/src/test/ui/issues/issue-37887.stderr index 48fb6c2e6fa..7a5a5cde469 100644 --- a/src/test/ui/issues/issue-37887.stderr +++ b/src/test/ui/issues/issue-37887.stderr @@ -4,13 +4,13 @@ error[E0432]: unresolved import `libc` LL | use libc::*; //~ ERROR unresolved import | ^^^^ maybe a missing `extern crate libc;`? -error[E0658]: use of unstable library feature 'libc': use `libc` from crates.io (see issue #27783) +error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? (see issue #27812) --> $DIR/issue-37887.rs:12:5 | LL | extern crate libc; //~ ERROR use of unstable | ^^^^^^^^^^^^^^^^^^ | - = help: add #![feature(libc)] to the crate attributes to enable + = help: add #![feature(rustc_private)] to the crate attributes to enable error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-40510-1.nll.stderr b/src/test/ui/issues/issue-40510-1.nll.stderr index 723b6f3111c..1601f6d4467 100644 --- a/src/test/ui/issues/issue-40510-1.nll.stderr +++ b/src/test/ui/issues/issue-40510-1.nll.stderr @@ -8,7 +8,6 @@ LL | &mut x | = note: `FnMut` closures only have access to their captured variables while they are executing... = note: ...therefore, they cannot allow references to captured variables to escape - = warning: This error has been downgraded to a warning for backwards compatibility with previous releases. - It represents potential unsoundness in your code. - This warning will become a hard error in the future. + = warning: this error has been downgraded to a warning for backwards compatibility with previous releases + = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future diff --git a/src/test/ui/issues/issue-40510-3.nll.stderr b/src/test/ui/issues/issue-40510-3.nll.stderr index e8e82ee8fda..3c7e60520cc 100644 --- a/src/test/ui/issues/issue-40510-3.nll.stderr +++ b/src/test/ui/issues/issue-40510-3.nll.stderr @@ -10,7 +10,6 @@ LL | | } | = note: `FnMut` closures only have access to their captured variables while they are executing... = note: ...therefore, they cannot allow references to captured variables to escape - = warning: This error has been downgraded to a warning for backwards compatibility with previous releases. - It represents potential unsoundness in your code. - This warning will become a hard error in the future. + = warning: this error has been downgraded to a warning for backwards compatibility with previous releases + = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future diff --git a/src/test/ui/issues/issue-40861.stderr b/src/test/ui/issues/issue-40861.stderr index dbde40fb25e..660f0ff7073 100644 --- a/src/test/ui/issues/issue-40861.stderr +++ b/src/test/ui/issues/issue-40861.stderr @@ -4,7 +4,7 @@ error[E0608]: cannot index into a value of type `()` LL | ()[f(&[1.0])]; | ^^^^^^^^^^^^^ | - = help: to access tuple elements, use tuple indexing syntax (e.g. `tuple.0`) + = help: to access tuple elements, use tuple indexing syntax (e.g., `tuple.0`) error: aborting due to previous error diff --git a/src/test/ui/issues/issue-41974.stderr b/src/test/ui/issues/issue-41974.stderr index eca40ed4355..d6d4f7b5515 100644 --- a/src/test/ui/issues/issue-41974.stderr +++ b/src/test/ui/issues/issue-41974.stderr @@ -15,7 +15,7 @@ error[E0120]: the Drop trait may only be implemented on structures LL | impl Drop for T where T: A { //~ ERROR E0119 | ^ implementing Drop requires a struct -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g. `MyStruct`) +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) --> $DIR/issue-41974.rs:17:1 | LL | impl Drop for T where T: A { //~ ERROR E0119 diff --git a/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.ast.stderr b/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.ast.stderr index 6172a5e35a8..8f8105508b3 100644 --- a/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.ast.stderr +++ b/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.ast.stderr @@ -1,5 +1,5 @@ error: compilation successful - --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:89:1 + --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:92:1 | LL | / fn main() { //[ast]~ ERROR compilation successful LL | | //[migrate]~^ ERROR compilation successful diff --git a/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.migrate.stderr b/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.migrate.stderr index 00df5c859bf..7efc9ce744e 100644 --- a/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.migrate.stderr +++ b/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.migrate.stderr @@ -9,12 +9,11 @@ LL | &mut *s.0 //[nll]~ ERROR borrow may still be in use when destructor run LL | } | - here, drop of `s` needs exclusive access to `*s.0`, because the type `Scribble<'_>` implements the `Drop` trait | - = warning: This error has been downgraded to a warning for backwards compatibility with previous releases. - It represents potential unsoundness in your code. - This warning will become a hard error in the future. + = warning: this error has been downgraded to a warning for backwards compatibility with previous releases + = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future warning[E0713]: borrow may still be in use when destructor runs - --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:73:5 + --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:74:5 | LL | fn boxed_scribbled<'a>(s: Box>) -> &'a mut u32 { | -- lifetime `'a` defined here @@ -24,12 +23,11 @@ LL | &mut *(*s).0 //[nll]~ ERROR borrow may still be in use when destructor LL | } | - here, drop of `s` needs exclusive access to `*s.0`, because the type `Scribble<'_>` implements the `Drop` trait | - = warning: This error has been downgraded to a warning for backwards compatibility with previous releases. - It represents potential unsoundness in your code. - This warning will become a hard error in the future. + = warning: this error has been downgraded to a warning for backwards compatibility with previous releases + = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future warning[E0713]: borrow may still be in use when destructor runs - --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:83:5 + --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:85:5 | LL | fn boxed_boxed_scribbled<'a>(s: Box>>) -> &'a mut u32 { | -- lifetime `'a` defined here @@ -39,12 +37,11 @@ LL | &mut *(**s).0 //[nll]~ ERROR borrow may still be in use when destructor LL | } | - here, drop of `s` needs exclusive access to `*s.0`, because the type `Scribble<'_>` implements the `Drop` trait | - = warning: This error has been downgraded to a warning for backwards compatibility with previous releases. - It represents potential unsoundness in your code. - This warning will become a hard error in the future. + = warning: this error has been downgraded to a warning for backwards compatibility with previous releases + = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future error: compilation successful - --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:89:1 + --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:92:1 | LL | / fn main() { //[ast]~ ERROR compilation successful LL | | //[migrate]~^ ERROR compilation successful diff --git a/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.nll.stderr b/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.nll.stderr index 5640dbd4e8c..45815fb589c 100644 --- a/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.nll.stderr +++ b/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.nll.stderr @@ -10,7 +10,7 @@ LL | } | - here, drop of `s` needs exclusive access to `*s.0`, because the type `Scribble<'_>` implements the `Drop` trait error[E0713]: borrow may still be in use when destructor runs - --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:73:5 + --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:74:5 | LL | fn boxed_scribbled<'a>(s: Box>) -> &'a mut u32 { | -- lifetime `'a` defined here @@ -21,7 +21,7 @@ LL | } | - here, drop of `s` needs exclusive access to `*s.0`, because the type `Scribble<'_>` implements the `Drop` trait error[E0713]: borrow may still be in use when destructor runs - --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:83:5 + --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:85:5 | LL | fn boxed_boxed_scribbled<'a>(s: Box>>) -> &'a mut u32 { | -- lifetime `'a` defined here diff --git a/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.rs b/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.rs index 2af05172d24..0d0d22f993f 100644 --- a/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.rs +++ b/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.rs @@ -62,7 +62,8 @@ fn boxed_boxed_borrowed_scribble<'a>(s: Box>) -> &'a mut u fn scribbled<'a>(s: Scribble<'a>) -> &'a mut u32 { &mut *s.0 //[nll]~ ERROR borrow may still be in use when destructor runs [E0713] //[migrate]~^ WARNING borrow may still be in use when destructor runs [E0713] - //[migrate]~| WARNING This error has been downgraded to a warning for backwards compatibility + //[migrate]~| WARNING this error has been downgraded to a warning for backwards compatibility + //[migrate]~| WARNING this represents potential undefined behavior in your code } // This, by analogy to previous case, is *also* not okay. @@ -72,7 +73,8 @@ fn scribbled<'a>(s: Scribble<'a>) -> &'a mut u32 { fn boxed_scribbled<'a>(s: Box>) -> &'a mut u32 { &mut *(*s).0 //[nll]~ ERROR borrow may still be in use when destructor runs [E0713] //[migrate]~^ WARNING borrow may still be in use when destructor runs [E0713] - //[migrate]~| WARNING This error has been downgraded to a warning for backwards compatibility + //[migrate]~| WARNING this error has been downgraded to a warning for backwards compatibility + //[migrate]~| WARNING this represents potential undefined behavior in your code } // This, by analogy to previous case, is *also* not okay. @@ -82,7 +84,8 @@ fn boxed_scribbled<'a>(s: Box>) -> &'a mut u32 { fn boxed_boxed_scribbled<'a>(s: Box>>) -> &'a mut u32 { &mut *(**s).0 //[nll]~ ERROR borrow may still be in use when destructor runs [E0713] //[migrate]~^ WARNING borrow may still be in use when destructor runs [E0713] - //[migrate]~| WARNING This error has been downgraded to a warning for backwards compatibility + //[migrate]~| WARNING this error has been downgraded to a warning for backwards compatibility + //[migrate]~| WARNING this represents potential undefined behavior in your code } #[rustc_error] diff --git a/src/test/ui/issues/issue-49824.nll.stderr b/src/test/ui/issues/issue-49824.nll.stderr index 555558c99d9..2300d84a3ff 100644 --- a/src/test/ui/issues/issue-49824.nll.stderr +++ b/src/test/ui/issues/issue-49824.nll.stderr @@ -10,9 +10,8 @@ LL | | } | = note: `FnMut` closures only have access to their captured variables while they are executing... = note: ...therefore, they cannot allow references to captured variables to escape - = warning: This error has been downgraded to a warning for backwards compatibility with previous releases. - It represents potential unsoundness in your code. - This warning will become a hard error in the future. + = warning: this error has been downgraded to a warning for backwards compatibility with previous releases + = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future error: compilation successful --> $DIR/issue-49824.rs:18:1 diff --git a/src/test/ui/issues/issue-52060.stderr b/src/test/ui/issues/issue-52060.stderr index 988bfd480e6..7c3f7695549 100644 --- a/src/test/ui/issues/issue-52060.stderr +++ b/src/test/ui/issues/issue-52060.stderr @@ -10,7 +10,7 @@ error: `core::slice::::len` is not yet stable as a const fn LL | static B: [u32; 1] = [0; A.len()]; | ^^^^^^^ | - = help: in Nightly builds, add `#![feature(const_slice_len)]` to the crate attributes to enable + = help: add `#![feature(const_slice_len)]` to the crate attributes to enable error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-56199.rs b/src/test/ui/issues/issue-56199.rs new file mode 100644 index 00000000000..83d4e31b5d1 --- /dev/null +++ b/src/test/ui/issues/issue-56199.rs @@ -0,0 +1,23 @@ + +enum Foo {} +struct Bar {} + +impl Foo { + fn foo() { + let _ = Self; + //~^ ERROR the `Self` constructor can only be used with tuple or unit structs + let _ = Self(); + //~^ ERROR the `Self` constructor can only be used with tuple or unit structs + } +} + +impl Bar { + fn bar() { + let _ = Self; + //~^ ERROR the `Self` constructor can only be used with tuple or unit structs + let _ = Self(); + //~^ ERROR the `Self` constructor can only be used with tuple or unit structs + } +} + +fn main() {} diff --git a/src/test/ui/issues/issue-56199.stderr b/src/test/ui/issues/issue-56199.stderr new file mode 100644 index 00000000000..6e3c7fd17b4 --- /dev/null +++ b/src/test/ui/issues/issue-56199.stderr @@ -0,0 +1,30 @@ +error: the `Self` constructor can only be used with tuple or unit structs + --> $DIR/issue-56199.rs:7:17 + | +LL | let _ = Self; + | ^^^^ + | + = note: did you mean to use one of the enum's variants? + +error: the `Self` constructor can only be used with tuple or unit structs + --> $DIR/issue-56199.rs:9:17 + | +LL | let _ = Self(); + | ^^^^ + | + = note: did you mean to use one of the enum's variants? + +error: the `Self` constructor can only be used with tuple or unit structs + --> $DIR/issue-56199.rs:16:17 + | +LL | let _ = Self; + | ^^^^ did you mean `Self { /* fields */ }`? + +error: the `Self` constructor can only be used with tuple or unit structs + --> $DIR/issue-56199.rs:18:17 + | +LL | let _ = Self(); + | ^^^^ did you mean `Self { /* fields */ }`? + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/issues/issue-56762.rs b/src/test/ui/issues/issue-56762.rs new file mode 100644 index 00000000000..97b66b2c7c9 --- /dev/null +++ b/src/test/ui/issues/issue-56762.rs @@ -0,0 +1,18 @@ +// only-x86_64 +const HUGE_SIZE: usize = !0usize / 8; + + +pub struct TooBigArray { + arr: [u8; HUGE_SIZE], +} + +impl TooBigArray { + pub const fn new() -> Self { + TooBigArray { arr: [0x00; HUGE_SIZE], } + } +} + +static MY_TOO_BIG_ARRAY_1: TooBigArray = TooBigArray::new(); +static MY_TOO_BIG_ARRAY_2: [u8; HUGE_SIZE] = [0x00; HUGE_SIZE]; + +fn main() { } diff --git a/src/test/ui/issues/issue-56762.stderr b/src/test/ui/issues/issue-56762.stderr new file mode 100644 index 00000000000..83d5dc62e61 --- /dev/null +++ b/src/test/ui/issues/issue-56762.stderr @@ -0,0 +1,4 @@ +error: the type `[u8; 2305843009213693951]` is too big for the current architecture + +error: aborting due to previous error + diff --git a/src/test/ui/issues/issue-56835.rs b/src/test/ui/issues/issue-56835.rs new file mode 100644 index 00000000000..c16550e3701 --- /dev/null +++ b/src/test/ui/issues/issue-56835.rs @@ -0,0 +1,10 @@ + +pub struct Foo {} + +impl Foo { + fn bar(Self(foo): Self) {} + //~^ ERROR the `Self` constructor can only be used with tuple or unit structs + //~^^ ERROR expected tuple struct/variant, found self constructor `Self` [E0164] +} + +fn main() {} diff --git a/src/test/ui/issues/issue-56835.stderr b/src/test/ui/issues/issue-56835.stderr new file mode 100644 index 00000000000..b7c3b142ec4 --- /dev/null +++ b/src/test/ui/issues/issue-56835.stderr @@ -0,0 +1,15 @@ +error: the `Self` constructor can only be used with tuple or unit structs + --> $DIR/issue-56835.rs:5:12 + | +LL | fn bar(Self(foo): Self) {} + | ^^^^^^^^^ did you mean `Self { /* fields */ }`? + +error[E0164]: expected tuple struct/variant, found self constructor `Self` + --> $DIR/issue-56835.rs:5:12 + | +LL | fn bar(Self(foo): Self) {} + | ^^^^^^^^^ not a tuple variant or struct + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0164`. diff --git a/src/test/ui/iterators/array-of-ranges.stderr b/src/test/ui/iterators/array-of-ranges.stderr index 495659720c3..3dbed9a1065 100644 --- a/src/test/ui/iterators/array-of-ranges.stderr +++ b/src/test/ui/iterators/array-of-ranges.stderr @@ -75,7 +75,7 @@ LL | for _ in [0..1, 2..3] {} | ^^^^^^^^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it | = help: the trait `std::iter::Iterator` is not implemented for `[std::ops::Range<{integer}>; 2]` - = note: arrays are not an iterators, but slices like the following are: `&[1, 2, 3]` + = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` = note: required by `std::iter::IntoIterator::into_iter` error[E0277]: `[std::ops::RangeInclusive<{integer}>; 1]` is not an iterator diff --git a/src/test/ui/iterators/array.stderr b/src/test/ui/iterators/array.stderr index 582c812a8d6..94731f1c745 100644 --- a/src/test/ui/iterators/array.stderr +++ b/src/test/ui/iterators/array.stderr @@ -5,7 +5,7 @@ LL | for _ in [1, 2] {} | ^^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it | = help: the trait `std::iter::Iterator` is not implemented for `[{integer}; 2]` - = note: arrays are not an iterators, but slices like the following are: `&[1, 2, 3]` + = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` = note: required by `std::iter::IntoIterator::into_iter` error[E0277]: `[{integer}; 2]` is not an iterator @@ -15,7 +15,7 @@ LL | for _ in x {} | ^ borrow the array with `&` or call `.iter()` on it to iterate over it | = help: the trait `std::iter::Iterator` is not implemented for `[{integer}; 2]` - = note: arrays are not an iterators, but slices like the following are: `&[1, 2, 3]` + = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` = note: required by `std::iter::IntoIterator::into_iter` error[E0277]: `[{float}; 2]` is not an iterator @@ -25,7 +25,7 @@ LL | for _ in [1.0, 2.0] {} | ^^^^^^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it | = help: the trait `std::iter::Iterator` is not implemented for `[{float}; 2]` - = note: arrays are not an iterators, but slices like the following are: `&[1, 2, 3]` + = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` = note: required by `std::iter::IntoIterator::into_iter` error: aborting due to 3 previous errors diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr index a8b0e3e4250..6b9e1dc7057 100644 --- a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr +++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr @@ -55,6 +55,7 @@ note: lint level defined here LL | #![warn(unused)] // UI tests pass `-A unused` (#43896) | ^^^^^^ = note: #[warn(unused_assignments)] implied by #[warn(unused)] + = help: maybe it is overwritten before being read? warning: unused variable: `fire` --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:54:32 diff --git a/src/test/ui/lint/lint-ctypes.rs b/src/test/ui/lint/lint-ctypes.rs index e09aabaf692..4c9f1f980bd 100644 --- a/src/test/ui/lint/lint-ctypes.rs +++ b/src/test/ui/lint/lint-ctypes.rs @@ -9,7 +9,7 @@ // except according to those terms. #![deny(improper_ctypes)] -#![feature(libc)] +#![feature(rustc_private)] #![allow(private_in_public)] diff --git a/src/test/ui/lint/lint-unexported-no-mangle.stderr b/src/test/ui/lint/lint-unexported-no-mangle.stderr index 063915d5b5f..1df2d7babe9 100644 --- a/src/test/ui/lint/lint-unexported-no-mangle.stderr +++ b/src/test/ui/lint/lint-unexported-no-mangle.stderr @@ -1,8 +1,8 @@ -warning: lint `private_no_mangle_fns` has been removed: `no longer an warning, #[no_mangle] functions always exported` +warning: lint `private_no_mangle_fns` has been removed: `no longer a warning, #[no_mangle] functions always exported` | = note: requested on the command line with `-F private_no_mangle_fns` -warning: lint `private_no_mangle_statics` has been removed: `no longer an warning, #[no_mangle] statics always exported` +warning: lint `private_no_mangle_statics` has been removed: `no longer a warning, #[no_mangle] statics always exported` | = note: requested on the command line with `-F private_no_mangle_statics` diff --git a/src/test/ui/lint/lint-unknown-lint-cmdline.rs b/src/test/ui/lint/lint-unknown-lint-cmdline.rs index 0c41959f8a7..33fb46dce6e 100644 --- a/src/test/ui/lint/lint-unknown-lint-cmdline.rs +++ b/src/test/ui/lint/lint-unknown-lint-cmdline.rs @@ -8,9 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags:-D bogus +// compile-flags:-D bogus -D dead_cod -// error-pattern:unknown lint +// error-pattern:unknown lint: `bogus` // error-pattern:requested on the command line with `-D bogus` +// error-pattern:unknown lint: `dead_cod` +// error-pattern:requested on the command line with `-D dead_cod` +// error-pattern:did you mean: `dead_code` fn main() { } diff --git a/src/test/ui/lint/lint-unknown-lint-cmdline.stderr b/src/test/ui/lint/lint-unknown-lint-cmdline.stderr index 86360041026..58fdae3333c 100644 --- a/src/test/ui/lint/lint-unknown-lint-cmdline.stderr +++ b/src/test/ui/lint/lint-unknown-lint-cmdline.stderr @@ -2,6 +2,11 @@ error[E0602]: unknown lint: `bogus` | = note: requested on the command line with `-D bogus` -error: aborting due to previous error +error[E0602]: unknown lint: `dead_cod` + | + = help: did you mean: `dead_code` + = note: requested on the command line with `-D dead_cod` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0602`. diff --git a/src/test/ui/lint/lint-unknown-lint.rs b/src/test/ui/lint/lint-unknown-lint.rs index 2de8d849d19..5d3fd0f1972 100644 --- a/src/test/ui/lint/lint-unknown-lint.rs +++ b/src/test/ui/lint/lint-unknown-lint.rs @@ -8,6 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(not_a_real_lint)] //~ WARN unknown lint -#![deny(unused)] -fn main() { let unused = (); } //~ ERROR unused variable +#![deny(unknown_lints)] + +#![allow(not_a_real_lint)] //~ ERROR unknown lint + +#![deny(dead_cod)] //~ ERROR unknown lint + //~| HELP did you mean + //~| SUGGESTION dead_code + +fn main() {} diff --git a/src/test/ui/lint/lint-unknown-lint.stderr b/src/test/ui/lint/lint-unknown-lint.stderr index b398a2f3690..6fc2da39a7c 100644 --- a/src/test/ui/lint/lint-unknown-lint.stderr +++ b/src/test/ui/lint/lint-unknown-lint.stderr @@ -1,23 +1,20 @@ -warning: unknown lint: `not_a_real_lint` - --> $DIR/lint-unknown-lint.rs:11:10 +error: unknown lint: `not_a_real_lint` + --> $DIR/lint-unknown-lint.rs:13:10 | -LL | #![allow(not_a_real_lint)] //~ WARN unknown lint +LL | #![allow(not_a_real_lint)] //~ ERROR unknown lint | ^^^^^^^^^^^^^^^ | - = note: #[warn(unknown_lints)] on by default - -error: unused variable: `unused` - --> $DIR/lint-unknown-lint.rs:13:17 - | -LL | fn main() { let unused = (); } //~ ERROR unused variable - | ^^^^^^ help: consider using `_unused` instead - | note: lint level defined here - --> $DIR/lint-unknown-lint.rs:12:9 + --> $DIR/lint-unknown-lint.rs:11:9 | -LL | #![deny(unused)] - | ^^^^^^ - = note: #[deny(unused_variables)] implied by #[deny(unused)] +LL | #![deny(unknown_lints)] + | ^^^^^^^^^^^^^ -error: aborting due to previous error +error: unknown lint: `dead_cod` + --> $DIR/lint-unknown-lint.rs:15:9 + | +LL | #![deny(dead_cod)] //~ ERROR unknown lint + | ^^^^^^^^ help: did you mean: `dead_code` + +error: aborting due to 2 previous errors diff --git a/src/test/ui/lint/lint-unused-imports.rs b/src/test/ui/lint/lint-unused-imports.rs index 5bb2ab75c53..64a48511bac 100644 --- a/src/test/ui/lint/lint-unused-imports.rs +++ b/src/test/ui/lint/lint-unused-imports.rs @@ -81,7 +81,7 @@ fn g() { } } -// c.f. issue #35135 +// cf. issue #35135. #[allow(unused_variables)] fn h() { use test2::foo; //~ ERROR unused import: `test2::foo` diff --git a/src/test/ui/lint/not_found.stderr b/src/test/ui/lint/not_found.stderr index 603b5410444..dedbc829913 100644 --- a/src/test/ui/lint/not_found.stderr +++ b/src/test/ui/lint/not_found.stderr @@ -10,11 +10,11 @@ warning: unknown lint: `DEAD_CODE` --> $DIR/not_found.rs:18:8 | LL | #[warn(DEAD_CODE)] - | ^^^^^^^^^ help: lowercase the lint name: `dead_code` + | ^^^^^^^^^ help: did you mean: `dead_code` warning: unknown lint: `Warnings` --> $DIR/not_found.rs:20:8 | LL | #[deny(Warnings)] - | ^^^^^^^^ help: lowercase the lint name: `warnings` + | ^^^^^^^^ help: did you mean: `warnings` diff --git a/src/test/ui/liveness/liveness-dead.stderr b/src/test/ui/liveness/liveness-dead.stderr index 6709fee0abb..6e43cccdccf 100644 --- a/src/test/ui/liveness/liveness-dead.stderr +++ b/src/test/ui/liveness/liveness-dead.stderr @@ -9,24 +9,31 @@ note: lint level defined here | LL | #![deny(unused_assignments)] | ^^^^^^^^^^^^^^^^^^ + = help: maybe it is overwritten before being read? error: value assigned to `x` is never read --> $DIR/liveness-dead.rs:27:5 | LL | x = 4; //~ ERROR: value assigned to `x` is never read | ^ + | + = help: maybe it is overwritten before being read? error: value passed to `x` is never read --> $DIR/liveness-dead.rs:30:11 | LL | fn f4(mut x: i32) { //~ ERROR: value passed to `x` is never read | ^ + | + = help: maybe it is overwritten before being read? error: value assigned to `x` is never read --> $DIR/liveness-dead.rs:37:5 | LL | x = 4; //~ ERROR: value assigned to `x` is never read | ^ + | + = help: maybe it is overwritten before being read? error: aborting due to 4 previous errors diff --git a/src/test/ui/liveness/liveness-unused.stderr b/src/test/ui/liveness/liveness-unused.stderr index 2846f242fbe..35ccc79a19a 100644 --- a/src/test/ui/liveness/liveness-unused.stderr +++ b/src/test/ui/liveness/liveness-unused.stderr @@ -60,6 +60,7 @@ note: lint level defined here | LL | #![deny(unused_assignments)] | ^^^^^^^^^^^^^^^^^^ + = help: maybe it is overwritten before being read? error: variable `z` is assigned to, but never used --> $DIR/liveness-unused.rs:47:13 @@ -106,6 +107,8 @@ error: value assigned to `x` is never read | LL | x = 0; //~ ERROR value assigned to `x` is never read | ^ + | + = help: maybe it is overwritten before being read? error: aborting due to 13 previous errors diff --git a/src/test/ui/macros/assert.rs b/src/test/ui/macros/assert.rs new file mode 100644 index 00000000000..8732cb58d74 --- /dev/null +++ b/src/test/ui/macros/assert.rs @@ -0,0 +1,4 @@ +fn main() { + assert!(); //~ ERROR requires a boolean expression + debug_assert!(); //~ ERROR requires a boolean expression +} diff --git a/src/test/ui/macros/assert.stderr b/src/test/ui/macros/assert.stderr new file mode 100644 index 00000000000..89faba0cf63 --- /dev/null +++ b/src/test/ui/macros/assert.stderr @@ -0,0 +1,16 @@ +error: macro requires a boolean expression as an argument + --> $DIR/assert.rs:2:5 + | +LL | assert!(); //~ ERROR requires a boolean expression + | ^^^^^^^^^^ boolean expression required + +error: macro requires a boolean expression as an argument + --> $DIR/assert.rs:3:5 + | +LL | debug_assert!(); //~ ERROR requires a boolean expression + | ^^^^^^^^^^^^^^^^ boolean expression required + | + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/match/match-non-exhaustive.stderr b/src/test/ui/match/match-non-exhaustive.stderr index 04f09caceed..ad895b448dd 100644 --- a/src/test/ui/match/match-non-exhaustive.stderr +++ b/src/test/ui/match/match-non-exhaustive.stderr @@ -1,8 +1,8 @@ -error[E0004]: non-exhaustive patterns: `_` not covered +error[E0004]: non-exhaustive patterns: `-2147483648i32..=0i32` and `2i32..=2147483647i32` not covered --> $DIR/match-non-exhaustive.rs:12:11 | LL | match 0 { 1 => () } //~ ERROR non-exhaustive patterns - | ^ pattern `_` not covered + | ^ patterns `-2147483648i32..=0i32` and `2i32..=2147483647i32` not covered error[E0004]: non-exhaustive patterns: `_` not covered --> $DIR/match-non-exhaustive.rs:13:11 diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index 86a92a70287..1fbac9d6881 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -5,8 +5,8 @@ LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); | ^^^^^ | = note: the method `count` exists but the following trait bounds were not satisfied: - `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:17:39: 17:53]> : std::iter::Iterator` `&mut std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:17:39: 17:53]> : std::iter::Iterator` + `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:17:39: 17:53]> : std::iter::Iterator` error[E0631]: type mismatch in closure arguments --> $DIR/issue-36053-2.rs:17:32 diff --git a/src/test/ui/namespace/namespace-mix.rs b/src/test/ui/namespace/namespace-mix.rs index c1c724fc431..22a9da8d9a6 100644 --- a/src/test/ui/namespace/namespace-mix.rs +++ b/src/test/ui/namespace/namespace-mix.rs @@ -26,7 +26,7 @@ mod c { pub struct Item; } -// Use something emitting the type argument name, e.g. unsatisfied bound. +// Use something emitting the type argument name, e.g., unsatisfied bound. trait Impossible {} fn check(_: T) {} diff --git a/src/test/ui/nll/closure-borrow-spans.stderr b/src/test/ui/nll/closure-borrow-spans.stderr index 3e423dadd19..98a261657b1 100644 --- a/src/test/ui/nll/closure-borrow-spans.stderr +++ b/src/test/ui/nll/closure-borrow-spans.stderr @@ -126,7 +126,7 @@ LL | let f = || *x = 0; | | | closure construction occurs here LL | let y = &x; //~ ERROR - | ^^ borrow occurs here + | ^^ second borrow occurs here LL | f.use_ref(); | - first borrow later used here @@ -138,7 +138,7 @@ LL | let f = || *x = 0; | | | closure construction occurs here LL | let y = &mut x; //~ ERROR - | ^^^^^^ borrow occurs here + | ^^^^^^ second borrow occurs here LL | f.use_ref(); | - first borrow later used here diff --git a/src/test/ui/nll/issue-21232-partial-init-and-use.rs b/src/test/ui/nll/issue-21232-partial-init-and-use.rs index 186ecc54827..633cbdba2d4 100644 --- a/src/test/ui/nll/issue-21232-partial-init-and-use.rs +++ b/src/test/ui/nll/issue-21232-partial-init-and-use.rs @@ -61,7 +61,7 @@ impl R { fn new(f: F) -> Self { R { w: 0, f } } } // As a shorthand for the cases above, adding a numeric summary to // each test's fn name to denote each point on each axis. // -// E.g. 1000 = field fully init struct; 0211 = local void reinit tuple +// e.g., 1000 = field fully init struct; 0211 = local void reinit tuple // It got pretty monotonous writing the same code over and over, and I // feared I would forget details. So I abstracted some desiderata into diff --git a/src/test/ui/nll/issue-46589.rs b/src/test/ui/nll/issue-46589.rs new file mode 100644 index 00000000000..82e73651f43 --- /dev/null +++ b/src/test/ui/nll/issue-46589.rs @@ -0,0 +1,37 @@ +// 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. + +#![feature(nll)] + +struct Foo; + +impl Foo { + fn get_self(&mut self) -> Option<&mut Self> { + Some(self) + } + + fn new_self(&mut self) -> &mut Self { + self + } + + fn trigger_bug(&mut self) { + let other = &mut (&mut *self); + + *other = match (*other).get_self() { + Some(s) => s, + None => (*other).new_self() + //~^ ERROR cannot borrow `**other` as mutable more than once at a time [E0499] + }; + + let c = other; + } +} + +fn main() {} diff --git a/src/test/ui/nll/issue-46589.stderr b/src/test/ui/nll/issue-46589.stderr new file mode 100644 index 00000000000..6df2983f465 --- /dev/null +++ b/src/test/ui/nll/issue-46589.stderr @@ -0,0 +1,15 @@ +error[E0499]: cannot borrow `**other` as mutable more than once at a time + --> $DIR/issue-46589.rs:29:21 + | +LL | *other = match (*other).get_self() { + | -------- first mutable borrow occurs here +LL | Some(s) => s, +LL | None => (*other).new_self() + | ^^^^^^^^ + | | + | second mutable borrow occurs here + | first borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/src/test/ui/nll/issue-55850.nll.stderr b/src/test/ui/nll/issue-55850.nll.stderr new file mode 100644 index 00000000000..08e5217670e --- /dev/null +++ b/src/test/ui/nll/issue-55850.nll.stderr @@ -0,0 +1,18 @@ +error[E0597]: `s` does not live long enough + --> $DIR/issue-55850.rs:38:16 + | +LL | yield &s[..] //~ ERROR `s` does not live long enough [E0597] + | ^ borrowed value does not live long enough +LL | }) + | - `s` dropped here while still borrowed + +error[E0626]: borrow may still be in use when generator yields + --> $DIR/issue-55850.rs:38:16 + | +LL | yield &s[..] //~ ERROR `s` does not live long enough [E0597] + | -------^---- possible yield occurs here + +error: aborting due to 2 previous errors + +Some errors occurred: E0597, E0626. +For more information about an error, try `rustc --explain E0597`. diff --git a/src/test/ui/nll/issue-55850.rs b/src/test/ui/nll/issue-55850.rs new file mode 100644 index 00000000000..4140815c91b --- /dev/null +++ b/src/test/ui/nll/issue-55850.rs @@ -0,0 +1,44 @@ +// 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. + +#![allow(unused_mut)] +#![feature(generators, generator_trait)] + +use std::ops::Generator; +use std::ops::GeneratorState::Yielded; + +pub struct GenIter(G); + +impl Iterator for GenIter +where + G: Generator, +{ + type Item = G::Yield; + + fn next(&mut self) -> Option { + unsafe { + match self.0.resume() { + Yielded(y) => Some(y), + _ => None + } + } + } +} + +fn bug<'a>() -> impl Iterator { + GenIter(move || { + let mut s = String::new(); + yield &s[..] //~ ERROR `s` does not live long enough [E0597] + }) +} + +fn main() { + bug(); +} diff --git a/src/test/ui/nll/issue-55850.stderr b/src/test/ui/nll/issue-55850.stderr new file mode 100644 index 00000000000..26b4c82076c --- /dev/null +++ b/src/test/ui/nll/issue-55850.stderr @@ -0,0 +1,17 @@ +error[E0597]: `s` does not live long enough + --> $DIR/issue-55850.rs:38:16 + | +LL | yield &s[..] //~ ERROR `s` does not live long enough [E0597] + | ^ borrowed value does not live long enough +LL | }) + | - borrowed value only lives until here + | +note: borrowed value must be valid for the lifetime 'a as defined on the function body at 35:8... + --> $DIR/issue-55850.rs:35:8 + | +LL | fn bug<'a>() -> impl Iterator { + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/nll/loan_ends_mid_block_pair.rs b/src/test/ui/nll/loan_ends_mid_block_pair.rs index 97126e98cbf..320d80438b0 100644 --- a/src/test/ui/nll/loan_ends_mid_block_pair.rs +++ b/src/test/ui/nll/loan_ends_mid_block_pair.rs @@ -27,10 +27,8 @@ fn nll_fail() { //~| ERROR (Mir) [E0506] data.0 = 'f'; //~^ ERROR (Ast) [E0506] - //~| ERROR (Mir) [E0506] data.0 = 'g'; //~^ ERROR (Ast) [E0506] - //~| ERROR (Mir) [E0506] capitalize(c); } diff --git a/src/test/ui/nll/loan_ends_mid_block_pair.stderr b/src/test/ui/nll/loan_ends_mid_block_pair.stderr index 9afae71edbe..3ba3fa15a53 100644 --- a/src/test/ui/nll/loan_ends_mid_block_pair.stderr +++ b/src/test/ui/nll/loan_ends_mid_block_pair.stderr @@ -17,7 +17,7 @@ LL | data.0 = 'f'; | ^^^^^^^^^^^^ assignment to borrowed `data.0` occurs here error[E0506]: cannot assign to `data.0` because it is borrowed (Ast) - --> $DIR/loan_ends_mid_block_pair.rs:31:5 + --> $DIR/loan_ends_mid_block_pair.rs:30:5 | LL | let c = &mut data.0; | ------ borrow of `data.0` occurs here @@ -26,7 +26,7 @@ LL | data.0 = 'g'; | ^^^^^^^^^^^^ assignment to borrowed `data.0` occurs here error[E0506]: cannot assign to `data.0` because it is borrowed (Ast) - --> $DIR/loan_ends_mid_block_pair.rs:41:5 + --> $DIR/loan_ends_mid_block_pair.rs:39:5 | LL | let c = &mut data.0; | ------ borrow of `data.0` occurs here @@ -34,21 +34,21 @@ LL | capitalize(c); LL | data.0 = 'e'; | ^^^^^^^^^^^^ assignment to borrowed `data.0` occurs here +error[E0506]: cannot assign to `data.0` because it is borrowed (Ast) + --> $DIR/loan_ends_mid_block_pair.rs:41:5 + | +LL | let c = &mut data.0; + | ------ borrow of `data.0` occurs here +... +LL | data.0 = 'f'; + | ^^^^^^^^^^^^ assignment to borrowed `data.0` occurs here + error[E0506]: cannot assign to `data.0` because it is borrowed (Ast) --> $DIR/loan_ends_mid_block_pair.rs:43:5 | LL | let c = &mut data.0; | ------ borrow of `data.0` occurs here ... -LL | data.0 = 'f'; - | ^^^^^^^^^^^^ assignment to borrowed `data.0` occurs here - -error[E0506]: cannot assign to `data.0` because it is borrowed (Ast) - --> $DIR/loan_ends_mid_block_pair.rs:45:5 - | -LL | let c = &mut data.0; - | ------ borrow of `data.0` occurs here -... LL | data.0 = 'g'; | ^^^^^^^^^^^^ assignment to borrowed `data.0` occurs here @@ -64,30 +64,6 @@ LL | data.0 = 'e'; LL | capitalize(c); | - borrow later used here -error[E0506]: cannot assign to `data.0` because it is borrowed (Mir) - --> $DIR/loan_ends_mid_block_pair.rs:28:5 - | -LL | let c = &mut data.0; - | ----------- borrow of `data.0` occurs here -... -LL | data.0 = 'f'; - | ^^^^^^^^^^^^ assignment to borrowed `data.0` occurs here -... -LL | capitalize(c); - | - borrow later used here - -error[E0506]: cannot assign to `data.0` because it is borrowed (Mir) - --> $DIR/loan_ends_mid_block_pair.rs:31:5 - | -LL | let c = &mut data.0; - | ----------- borrow of `data.0` occurs here -... -LL | data.0 = 'g'; - | ^^^^^^^^^^^^ assignment to borrowed `data.0` occurs here -... -LL | capitalize(c); - | - borrow later used here - -error: aborting due to 9 previous errors +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/nll/match-guards-always-borrow.ast.nll.stderr b/src/test/ui/nll/match-guards-always-borrow.ast.nll.stderr index afb85c69990..46c26d2fd2d 100644 --- a/src/test/ui/nll/match-guards-always-borrow.ast.nll.stderr +++ b/src/test/ui/nll/match-guards-always-borrow.ast.nll.stderr @@ -4,9 +4,8 @@ warning[E0507]: cannot move out of borrowed content LL | (|| { let bar = foo; bar.take() })(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content | - = warning: This error has been downgraded to a warning for backwards compatibility with previous releases. - It represents potential unsoundness in your code. - This warning will become a hard error in the future. + = warning: this error has been downgraded to a warning for backwards compatibility with previous releases + = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future error: compilation successful --> $DIR/match-guards-always-borrow.rs:57:1 diff --git a/src/test/ui/nll/match-on-borrowed.rs b/src/test/ui/nll/match-on-borrowed.rs index 6a8ce03e8fd..edce2b185df 100644 --- a/src/test/ui/nll/match-on-borrowed.rs +++ b/src/test/ui/nll/match-on-borrowed.rs @@ -46,9 +46,9 @@ fn enum_example(mut e: E) { E::V(ref mut x, _) => x, E::W => panic!(), }; - match e { // OK, no access of borrowed data + match e { // Don't know that E uses a tag for its discriminant _ if false => (), - E::V(_, r) => (), + E::V(_, r) => (), //~ ERROR E::W => (), } x; @@ -59,9 +59,9 @@ fn indirect_enum_example(mut f: &mut E) { E::V(ref mut x, _) => x, E::W => panic!(), }; - match f { // OK, no access of borrowed data + match f { // Don't know that E uses a tag for its discriminant _ if false => (), - E::V(_, r) => (), + E::V(_, r) => (), //~ ERROR E::W => (), } x; diff --git a/src/test/ui/nll/match-on-borrowed.stderr b/src/test/ui/nll/match-on-borrowed.stderr index cdff29d44b8..2d34dd7805d 100644 --- a/src/test/ui/nll/match-on-borrowed.stderr +++ b/src/test/ui/nll/match-on-borrowed.stderr @@ -1,3 +1,27 @@ +error[E0503]: cannot use `e` because it was mutably borrowed + --> $DIR/match-on-borrowed.rs:51:9 + | +LL | E::V(ref mut x, _) => x, + | --------- borrow of `e.0` occurs here +... +LL | E::V(_, r) => (), //~ ERROR + | ^^^^^^^^^^ use of borrowed `e.0` +... +LL | x; + | - borrow later used here + +error[E0503]: cannot use `*f` because it was mutably borrowed + --> $DIR/match-on-borrowed.rs:64:9 + | +LL | E::V(ref mut x, _) => x, + | --------- borrow of `f.0` occurs here +... +LL | E::V(_, r) => (), //~ ERROR + | ^^^^^^^^^^ use of borrowed `f.0` +... +LL | x; + | - borrow later used here + error[E0503]: cannot use `t` because it was mutably borrowed --> $DIR/match-on-borrowed.rs:82:9 | @@ -16,7 +40,7 @@ error[E0381]: use of possibly uninitialized variable: `n` LL | match n {} //~ ERROR | ^ use of possibly uninitialized `n` -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors Some errors occurred: E0381, E0503. For more information about an error, try `rustc --explain E0381`. diff --git a/src/test/ui/no-implicit-prelude-nested.rs b/src/test/ui/no-implicit-prelude-nested.rs index c64839ad0de..0250cf529ee 100644 --- a/src/test/ui/no-implicit-prelude-nested.rs +++ b/src/test/ui/no-implicit-prelude-nested.rs @@ -10,7 +10,7 @@ // Test that things from the prelude aren't in scope. Use many of them // so that renaming some things won't magically make this test fail -// for the wrong reason (e.g. if `Add` changes to `Addition`, and +// for the wrong reason (e.g., if `Add` changes to `Addition`, and // `no_implicit_prelude` stops working, then the `impl Add` will still // fail with the same error message). diff --git a/src/test/ui/no-implicit-prelude.rs b/src/test/ui/no-implicit-prelude.rs index 0e39d9ebdc1..8a4a0aef069 100644 --- a/src/test/ui/no-implicit-prelude.rs +++ b/src/test/ui/no-implicit-prelude.rs @@ -12,7 +12,7 @@ // Test that things from the prelude aren't in scope. Use many of them // so that renaming some things won't magically make this test fail -// for the wrong reason (e.g. if `Add` changes to `Addition`, and +// for the wrong reason (e.g., if `Add` changes to `Addition`, and // `no_implicit_prelude` stops working, then the `impl Add` will still // fail with the same error message). diff --git a/src/test/compile-fail-fulldeps/no-link-unknown-crate.rs b/src/test/ui/no-link-unknown-crate.rs similarity index 100% rename from src/test/compile-fail-fulldeps/no-link-unknown-crate.rs rename to src/test/ui/no-link-unknown-crate.rs diff --git a/src/test/ui/no-link-unknown-crate.stderr b/src/test/ui/no-link-unknown-crate.stderr new file mode 100644 index 00000000000..182b484f80b --- /dev/null +++ b/src/test/ui/no-link-unknown-crate.stderr @@ -0,0 +1,9 @@ +error[E0463]: can't find crate for `doesnt_exist` + --> $DIR/no-link-unknown-crate.rs:12:1 + | +LL | extern crate doesnt_exist; //~ ERROR can't find crate + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ 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/non-copyable-void.rs b/src/test/ui/non-copyable-void.rs index 63e5f963754..35991901e93 100644 --- a/src/test/ui/non-copyable-void.rs +++ b/src/test/ui/non-copyable-void.rs @@ -10,7 +10,7 @@ // ignore-wasm32-bare no libc to test ffi with -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; diff --git a/src/test/ui/non-exhaustive/non-exhaustive-float-range-match.rs b/src/test/ui/non-exhaustive/non-exhaustive-float-range-match.rs new file mode 100644 index 00000000000..588fecbf10d --- /dev/null +++ b/src/test/ui/non-exhaustive/non-exhaustive-float-range-match.rs @@ -0,0 +1,13 @@ +#![allow(illegal_floating_point_literal_pattern)] +#![deny(unreachable_patterns)] + +fn main() { + match 0.0 { + 0.0..=1.0 => {} + _ => {} // ok + } + + match 0.0 { //~ ERROR non-exhaustive patterns + 0.0..=1.0 => {} + } +} diff --git a/src/test/ui/non-exhaustive/non-exhaustive-float-range-match.stderr b/src/test/ui/non-exhaustive/non-exhaustive-float-range-match.stderr new file mode 100644 index 00000000000..2e285afb380 --- /dev/null +++ b/src/test/ui/non-exhaustive/non-exhaustive-float-range-match.stderr @@ -0,0 +1,9 @@ +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/non-exhaustive-float-range-match.rs:10:11 + | +LL | match 0.0 { //~ ERROR non-exhaustive patterns + | ^^^ pattern `_` not covered + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/non-exhaustive/non-exhaustive-match.rs b/src/test/ui/non-exhaustive/non-exhaustive-match.rs index 13b62429f46..99a0c5d6626 100644 --- a/src/test/ui/non-exhaustive/non-exhaustive-match.rs +++ b/src/test/ui/non-exhaustive/non-exhaustive-match.rs @@ -22,7 +22,8 @@ fn main() { match Some(10) { //~ ERROR non-exhaustive patterns: `Some(_)` not covered None => {} } - match (2, 3, 4) { //~ ERROR non-exhaustive patterns: `(_, _, _)` not covered + match (2, 3, 4) { //~ ERROR non-exhaustive patterns: `(_, _, -2147483648i32..=3i32)` + // and `(_, _, 5i32..=2147483647i32)` not covered (_, _, 4) => {} } match (t::a, t::a) { //~ ERROR non-exhaustive patterns: `(a, a)` not covered diff --git a/src/test/ui/non-exhaustive/non-exhaustive-match.stderr b/src/test/ui/non-exhaustive/non-exhaustive-match.stderr index f48a0bc15eb..d3703a44454 100644 --- a/src/test/ui/non-exhaustive/non-exhaustive-match.stderr +++ b/src/test/ui/non-exhaustive/non-exhaustive-match.stderr @@ -16,32 +16,32 @@ error[E0004]: non-exhaustive patterns: `Some(_)` not covered LL | match Some(10) { //~ ERROR non-exhaustive patterns: `Some(_)` not covered | ^^^^^^^^ pattern `Some(_)` not covered -error[E0004]: non-exhaustive patterns: `(_, _, _)` not covered +error[E0004]: non-exhaustive patterns: `(_, _, -2147483648i32..=3i32)` and `(_, _, 5i32..=2147483647i32)` not covered --> $DIR/non-exhaustive-match.rs:25:11 | -LL | match (2, 3, 4) { //~ ERROR non-exhaustive patterns: `(_, _, _)` not covered - | ^^^^^^^^^ pattern `(_, _, _)` not covered +LL | match (2, 3, 4) { //~ ERROR non-exhaustive patterns: `(_, _, -2147483648i32..=3i32)` + | ^^^^^^^^^ patterns `(_, _, -2147483648i32..=3i32)` and `(_, _, 5i32..=2147483647i32)` not covered error[E0004]: non-exhaustive patterns: `(a, a)` not covered - --> $DIR/non-exhaustive-match.rs:28:11 + --> $DIR/non-exhaustive-match.rs:29:11 | LL | match (t::a, t::a) { //~ ERROR non-exhaustive patterns: `(a, a)` not covered | ^^^^^^^^^^^^ pattern `(a, a)` not covered error[E0004]: non-exhaustive patterns: `b` not covered - --> $DIR/non-exhaustive-match.rs:32:11 + --> $DIR/non-exhaustive-match.rs:33:11 | LL | match t::a { //~ ERROR non-exhaustive patterns: `b` not covered | ^^^^ pattern `b` not covered error[E0004]: non-exhaustive patterns: `[]` not covered - --> $DIR/non-exhaustive-match.rs:43:11 + --> $DIR/non-exhaustive-match.rs:44:11 | LL | match *vec { //~ ERROR non-exhaustive patterns: `[]` not covered | ^^^^ pattern `[]` not covered error[E0004]: non-exhaustive patterns: `[_, _, _, _]` not covered - --> $DIR/non-exhaustive-match.rs:56:11 + --> $DIR/non-exhaustive-match.rs:57:11 | LL | match *vec { //~ ERROR non-exhaustive patterns: `[_, _, _, _]` not covered | ^^^^ pattern `[_, _, _, _]` not covered diff --git a/src/test/ui/orphan-check-diagnostics.stderr b/src/test/ui/orphan-check-diagnostics.stderr index dc134dd8d6f..22422f15404 100644 --- a/src/test/ui/orphan-check-diagnostics.stderr +++ b/src/test/ui/orphan-check-diagnostics.stderr @@ -1,4 +1,4 @@ -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g. `MyStruct`) +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) --> $DIR/orphan-check-diagnostics.rs:20:1 | LL | impl RemoteTrait for T where T: LocalTrait {} diff --git a/src/test/ui/parser/assoc-oddities-1.rs b/src/test/ui/parser/assoc-oddities-1.rs index 63408b76b15..866d7423f14 100644 --- a/src/test/ui/parser/assoc-oddities-1.rs +++ b/src/test/ui/parser/assoc-oddities-1.rs @@ -15,7 +15,7 @@ fn that_odd_parse() { x = if c { a } else { b }(); x = if true { 1 } else { 0 } as *mut _; // however this does not parse and probably should fail to retain compat? - // NB: `..` here is arbitrary, failure happens/should happen ∀ops that aren’t `=` + // N.B., `..` here is arbitrary, failure happens/should happen ∀ops that aren’t `=` // see assoc-oddities-2 and assoc-oddities-3 ..if c { a } else { b }[n]; //~ ERROR expected one of } diff --git a/src/test/ui/parser/underscore_static.rs b/src/test/ui/parser/underscore_static.rs new file mode 100644 index 00000000000..e1a9a02f9aa --- /dev/null +++ b/src/test/ui/parser/underscore_static.rs @@ -0,0 +1,3 @@ +// compile-flags: -Z parse-only + +static _: () = (); //~ ERROR expected identifier, found reserved identifier `_` diff --git a/src/test/ui/parser/underscore_static.stderr b/src/test/ui/parser/underscore_static.stderr new file mode 100644 index 00000000000..1b766f785a5 --- /dev/null +++ b/src/test/ui/parser/underscore_static.stderr @@ -0,0 +1,8 @@ +error: expected identifier, found reserved identifier `_` + --> $DIR/underscore_static.rs:3:8 + | +LL | static _: () = (); //~ ERROR expected identifier, found reserved identifier `_` + | ^ expected identifier, found reserved identifier + +error: aborting due to previous error + diff --git a/src/test/ui/parser/unmatched-delimiter-at-end-of-file.rs b/src/test/ui/parser/unmatched-delimiter-at-end-of-file.rs new file mode 100644 index 00000000000..3eef75bafd3 --- /dev/null +++ b/src/test/ui/parser/unmatched-delimiter-at-end-of-file.rs @@ -0,0 +1,11 @@ +struct S { + x: usize, + y: usize, +} + +fn main() { + S { x: 4, + y: 5 }; +} + +fn foo() { //~ ERROR this file contains an un-closed delimiter diff --git a/src/test/ui/parser/unmatched-delimiter-at-end-of-file.stderr b/src/test/ui/parser/unmatched-delimiter-at-end-of-file.stderr new file mode 100644 index 00000000000..442837e5808 --- /dev/null +++ b/src/test/ui/parser/unmatched-delimiter-at-end-of-file.stderr @@ -0,0 +1,8 @@ +error: this file contains an un-closed delimiter + --> $DIR/unmatched-delimiter-at-end-of-file.rs:11:64 + | +LL | fn foo() { //~ ERROR this file contains an un-closed delimiter + | - un-closed delimiter ^ + +error: aborting due to previous error + diff --git a/src/test/ui/pattern/const-pat-ice.rs b/src/test/ui/pattern/const-pat-ice.rs new file mode 100644 index 00000000000..6496a2ab69f --- /dev/null +++ b/src/test/ui/pattern/const-pat-ice.rs @@ -0,0 +1,13 @@ +// failure-status: 101 + +// This is a repro test for an ICE in our pattern handling of constants. + +const FOO: &&&u32 = &&&42; + +fn main() { + match unimplemented!() { + &&&42 => {}, + FOO => {}, + _ => {}, + } +} diff --git a/src/test/ui/pattern/irrefutable-exhaustive-integer-binding.rs b/src/test/ui/pattern/irrefutable-exhaustive-integer-binding.rs new file mode 100644 index 00000000000..ff065882d96 --- /dev/null +++ b/src/test/ui/pattern/irrefutable-exhaustive-integer-binding.rs @@ -0,0 +1,8 @@ +// run-pass + +fn main() { + let -2147483648..=2147483647 = 1; + let 0..=255 = 0u8; + let -128..=127 = 0i8; + let '\u{0000}'..='\u{10FFFF}' = 'v'; +} diff --git a/src/test/ui/pattern/slice-pattern-const-2.rs b/src/test/ui/pattern/slice-pattern-const-2.rs index 6f9501d025c..6cfef115d08 100644 --- a/src/test/ui/pattern/slice-pattern-const-2.rs +++ b/src/test/ui/pattern/slice-pattern-const-2.rs @@ -1,4 +1,4 @@ -// compile-pass +#![deny(unreachable_patterns)] fn main() { let s = &[0x00; 4][..]; //Slice of any value @@ -6,19 +6,26 @@ fn main() { match s { MAGIC_TEST => (), [0x00, 0x00, 0x00, 0x00] => (), - [4, 5, 6, 7] => (), // this should warn + [4, 5, 6, 7] => (), //~ ERROR unreachable pattern _ => (), } match s { [0x00, 0x00, 0x00, 0x00] => (), MAGIC_TEST => (), - [4, 5, 6, 7] => (), // this should warn + [4, 5, 6, 7] => (), //~ ERROR unreachable pattern _ => (), } match s { [0x00, 0x00, 0x00, 0x00] => (), [4, 5, 6, 7] => (), - MAGIC_TEST => (), // this should warn + MAGIC_TEST => (), // FIXME(oli-obk): this should warn, but currently does not + _ => (), + } + const FOO: [u32; 1] = [4]; + match [99] { + [0x00] => (), + [4] => (), + FOO => (), //~ ERROR unreachable pattern _ => (), } } diff --git a/src/test/ui/pattern/slice-pattern-const-2.stderr b/src/test/ui/pattern/slice-pattern-const-2.stderr new file mode 100644 index 00000000000..95651ccc401 --- /dev/null +++ b/src/test/ui/pattern/slice-pattern-const-2.stderr @@ -0,0 +1,26 @@ +error: unreachable pattern + --> $DIR/slice-pattern-const-2.rs:9:9 + | +LL | [4, 5, 6, 7] => (), //~ ERROR unreachable pattern + | ^^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/slice-pattern-const-2.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const-2.rs:15:9 + | +LL | [4, 5, 6, 7] => (), //~ ERROR unreachable pattern + | ^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const-2.rs:28:9 + | +LL | FOO => (), //~ ERROR unreachable pattern + | ^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/pattern/slice-pattern-const-3.rs b/src/test/ui/pattern/slice-pattern-const-3.rs index e7a30cef57a..8805c43ba02 100644 --- a/src/test/ui/pattern/slice-pattern-const-3.rs +++ b/src/test/ui/pattern/slice-pattern-const-3.rs @@ -1,4 +1,4 @@ -// compile-pass +#![deny(unreachable_patterns)] fn main() { let s = &["0x00"; 4][..]; //Slice of any value @@ -6,19 +6,26 @@ fn main() { match s { MAGIC_TEST => (), ["0x00", "0x00", "0x00", "0x00"] => (), - ["4", "5", "6", "7"] => (), // this should warn + ["4", "5", "6", "7"] => (), // FIXME(oli-obk): this should warn, but currently does not _ => (), } match s { ["0x00", "0x00", "0x00", "0x00"] => (), MAGIC_TEST => (), - ["4", "5", "6", "7"] => (), // this should warn + ["4", "5", "6", "7"] => (), // FIXME(oli-obk): this should warn, but currently does not _ => (), } match s { ["0x00", "0x00", "0x00", "0x00"] => (), ["4", "5", "6", "7"] => (), - MAGIC_TEST => (), // this should warn + MAGIC_TEST => (), // FIXME(oli-obk): this should warn, but currently does not + _ => (), + } + const FOO: [&str; 1] = ["boo"]; + match ["baa"] { + ["0x00"] => (), + ["boo"] => (), + FOO => (), //~ ERROR unreachable pattern _ => (), } } diff --git a/src/test/ui/pattern/slice-pattern-const-3.stderr b/src/test/ui/pattern/slice-pattern-const-3.stderr new file mode 100644 index 00000000000..531bbbc84d0 --- /dev/null +++ b/src/test/ui/pattern/slice-pattern-const-3.stderr @@ -0,0 +1,14 @@ +error: unreachable pattern + --> $DIR/slice-pattern-const-3.rs:28:9 + | +LL | FOO => (), //~ ERROR unreachable pattern + | ^^^ + | +note: lint level defined here + --> $DIR/slice-pattern-const-3.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/pattern/slice-pattern-const.rs b/src/test/ui/pattern/slice-pattern-const.rs index d353f6cddbd..f0a04513f91 100644 --- a/src/test/ui/pattern/slice-pattern-const.rs +++ b/src/test/ui/pattern/slice-pattern-const.rs @@ -1,4 +1,4 @@ -//compile-pass +#![deny(unreachable_patterns)] fn main() { let s = &[0x00; 4][..]; //Slice of any value @@ -6,19 +6,42 @@ fn main() { match s { MAGIC_TEST => (), [0x00, 0x00, 0x00, 0x00] => (), - [84, 69, 83, 84] => (), // this should warn + [84, 69, 83, 84] => (), //~ ERROR unreachable pattern _ => (), } match s { [0x00, 0x00, 0x00, 0x00] => (), MAGIC_TEST => (), - [84, 69, 83, 84] => (), // this should warn + [84, 69, 83, 84] => (), //~ ERROR unreachable pattern _ => (), } match s { [0x00, 0x00, 0x00, 0x00] => (), [84, 69, 83, 84] => (), - MAGIC_TEST => (), // this should warn + MAGIC_TEST => (), //~ ERROR unreachable pattern _ => (), } + const FOO: [u8; 1] = [4]; + match [99] { + [0x00] => (), + [4] => (), + FOO => (), //~ ERROR unreachable pattern + _ => (), + } + const BAR: &[u8; 1] = &[4]; + match &[99] { + [0x00] => (), + [4] => (), + BAR => (), //~ ERROR unreachable pattern + b"a" => (), + _ => (), + } + + const BOO: &[u8; 0] = &[]; + match &[] { + [] => (), + BOO => (), //~ ERROR unreachable pattern + b"" => (), //~ ERROR unreachable pattern + _ => (), //~ ERROR unreachable pattern + } } diff --git a/src/test/ui/pattern/slice-pattern-const.stderr b/src/test/ui/pattern/slice-pattern-const.stderr new file mode 100644 index 00000000000..412e0158c01 --- /dev/null +++ b/src/test/ui/pattern/slice-pattern-const.stderr @@ -0,0 +1,56 @@ +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:9:9 + | +LL | [84, 69, 83, 84] => (), //~ ERROR unreachable pattern + | ^^^^^^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/slice-pattern-const.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:15:9 + | +LL | [84, 69, 83, 84] => (), //~ ERROR unreachable pattern + | ^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:21:9 + | +LL | MAGIC_TEST => (), //~ ERROR unreachable pattern + | ^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:28:9 + | +LL | FOO => (), //~ ERROR unreachable pattern + | ^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:35:9 + | +LL | BAR => (), //~ ERROR unreachable pattern + | ^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:43:9 + | +LL | BOO => (), //~ ERROR unreachable pattern + | ^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:44:9 + | +LL | b"" => (), //~ ERROR unreachable pattern + | ^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:45:9 + | +LL | _ => (), //~ ERROR unreachable pattern + | ^ + +error: aborting due to 8 previous errors + diff --git a/src/test/ui/precise_pointer_size_matching.rs b/src/test/ui/precise_pointer_size_matching.rs new file mode 100644 index 00000000000..759b63b188b --- /dev/null +++ b/src/test/ui/precise_pointer_size_matching.rs @@ -0,0 +1,33 @@ +// normalize-stderr-32bit: "-2147483648isize" -> "$$ISIZE_MIN" +// normalize-stderr-64bit: "-9223372036854775808isize" -> "$$ISIZE_MIN" +// normalize-stderr-32bit: "2147483647isize" -> "$$ISIZE_MAX" +// normalize-stderr-64bit: "9223372036854775807isize" -> "$$ISIZE_MAX" +// normalize-stderr-32bit: "4294967295usize" -> "$$USIZE_MAX" +// normalize-stderr-64bit: "18446744073709551615usize" -> "$$USIZE_MAX" + +#![feature(precise_pointer_size_matching)] +#![feature(exclusive_range_pattern)] + +#![deny(unreachable_patterns)] + +use std::{usize, isize}; + +fn main() { + match 0isize { + isize::MIN ..= isize::MAX => {} // ok + } + + match 0usize { + 0 ..= usize::MAX => {} // ok + } + + match 0isize { //~ ERROR non-exhaustive patterns + 1 ..= 8 => {} + -5 ..= 20 => {} + } + + match 0usize { //~ ERROR non-exhaustive patterns + 1 ..= 8 => {} + 5 ..= 20 => {} + } +} diff --git a/src/test/ui/precise_pointer_size_matching.stderr b/src/test/ui/precise_pointer_size_matching.stderr new file mode 100644 index 00000000000..4acbec6c7ff --- /dev/null +++ b/src/test/ui/precise_pointer_size_matching.stderr @@ -0,0 +1,15 @@ +error[E0004]: non-exhaustive patterns: `$ISIZE_MIN..=-6isize` and `21isize..=$ISIZE_MAX` not covered + --> $DIR/precise_pointer_size_matching.rs:24:11 + | +LL | match 0isize { //~ ERROR non-exhaustive patterns + | ^^^^^^ patterns `$ISIZE_MIN..=-6isize` and `21isize..=$ISIZE_MAX` not covered + +error[E0004]: non-exhaustive patterns: `0usize` and `21usize..=$USIZE_MAX` not covered + --> $DIR/precise_pointer_size_matching.rs:29:11 + | +LL | match 0usize { //~ ERROR non-exhaustive patterns + | ^^^^^^ patterns `0usize` and `21usize..=$USIZE_MAX` not covered + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/print_type_sizes/generics.rs b/src/test/ui/print_type_sizes/generics.rs index fa5921cfb13..5b6918d41b5 100644 --- a/src/test/ui/print_type_sizes/generics.rs +++ b/src/test/ui/print_type_sizes/generics.rs @@ -30,7 +30,7 @@ // Copy. // // (I suspect this reflect some naivety within the rust compiler -// itself; it should be checking for drop glue, i.e. a destructor +// itself; it should be checking for drop glue, i.e., a destructor // somewhere in the monomorphized types. It should not matter whether // the type is Copy.) #[derive(Copy, Clone)] diff --git a/src/test/ui/print_type_sizes/packed.rs b/src/test/ui/print_type_sizes/packed.rs index bc11146aa85..9ff794178fc 100644 --- a/src/test/ui/print_type_sizes/packed.rs +++ b/src/test/ui/print_type_sizes/packed.rs @@ -21,7 +21,6 @@ #![allow(dead_code)] #![feature(start)] -#![feature(repr_packed)] #[derive(Default)] #[repr(packed)] diff --git a/src/test/ui/privacy/privacy1.rs b/src/test/ui/privacy/privacy1.rs index 9aff4bbc41c..c336cc6299e 100644 --- a/src/test/ui/privacy/privacy1.rs +++ b/src/test/ui/privacy/privacy1.rs @@ -17,6 +17,20 @@ pub trait Sized {} #[lang="copy"] pub trait Copy {} +#[lang="deref"] +pub trait Deref { + type Target; +} + +#[lang="receiver"] +pub trait Receiver: Deref {} + +impl<'a, T> Deref for &'a T { + type Target = T; +} + +impl<'a, T> Receiver for &'a T {} + mod bar { // shouldn't bring in too much pub use self::glob::*; diff --git a/src/test/ui/privacy/privacy1.stderr b/src/test/ui/privacy/privacy1.stderr index d6197575447..54e01cca6c4 100644 --- a/src/test/ui/privacy/privacy1.stderr +++ b/src/test/ui/privacy/privacy1.stderr @@ -1,101 +1,101 @@ error[E0603]: module `baz` is private - --> $DIR/privacy1.rs:128:18 + --> $DIR/privacy1.rs:142:18 | LL | use bar::baz::{foo, bar}; | ^^^ error[E0603]: module `baz` is private - --> $DIR/privacy1.rs:136:18 + --> $DIR/privacy1.rs:150:18 | LL | use bar::baz; | ^^^ error[E0603]: module `i` is private - --> $DIR/privacy1.rs:160:20 + --> $DIR/privacy1.rs:174:20 | LL | use self::foo::i::A; //~ ERROR: module `i` is private | ^ error[E0603]: module `baz` is private - --> $DIR/privacy1.rs:100:16 + --> $DIR/privacy1.rs:114:16 | LL | ::bar::baz::A::foo(); //~ ERROR: module `baz` is private | ^^^ error[E0603]: module `baz` is private - --> $DIR/privacy1.rs:101:16 + --> $DIR/privacy1.rs:115:16 | LL | ::bar::baz::A::bar(); //~ ERROR: module `baz` is private | ^^^ error[E0603]: module `baz` is private - --> $DIR/privacy1.rs:103:16 + --> $DIR/privacy1.rs:117:16 | LL | ::bar::baz::A.foo2(); //~ ERROR: module `baz` is private | ^^^ error[E0603]: module `baz` is private - --> $DIR/privacy1.rs:104:16 + --> $DIR/privacy1.rs:118:16 | LL | ::bar::baz::A.bar2(); //~ ERROR: module `baz` is private | ^^^ error[E0603]: trait `B` is private - --> $DIR/privacy1.rs:108:16 + --> $DIR/privacy1.rs:122:16 | LL | ::bar::B::foo(); //~ ERROR: trait `B` is private | ^ error[E0603]: function `epriv` is private - --> $DIR/privacy1.rs:114:20 + --> $DIR/privacy1.rs:128:20 | LL | ::bar::epriv(); //~ ERROR: function `epriv` is private | ^^^^^ error[E0603]: module `baz` is private - --> $DIR/privacy1.rs:123:16 + --> $DIR/privacy1.rs:137:16 | LL | ::bar::baz::foo(); //~ ERROR: module `baz` is private | ^^^ error[E0603]: module `baz` is private - --> $DIR/privacy1.rs:124:16 + --> $DIR/privacy1.rs:138:16 | LL | ::bar::baz::bar(); //~ ERROR: module `baz` is private | ^^^ error[E0603]: trait `B` is private - --> $DIR/privacy1.rs:152:17 + --> $DIR/privacy1.rs:166:17 | LL | impl ::bar::B for f32 { fn foo() -> f32 { 1.0 } } | ^ error[E0624]: method `bar` is private - --> $DIR/privacy1.rs:73:9 + --> $DIR/privacy1.rs:87:9 | LL | self::baz::A::bar(); //~ ERROR: method `bar` is private | ^^^^^^^^^^^^^^^^^ error[E0624]: method `bar` is private - --> $DIR/privacy1.rs:91:5 + --> $DIR/privacy1.rs:105:5 | LL | bar::A::bar(); //~ ERROR: method `bar` is private | ^^^^^^^^^^^ error[E0624]: method `bar` is private - --> $DIR/privacy1.rs:98:9 + --> $DIR/privacy1.rs:112:9 | LL | ::bar::A::bar(); //~ ERROR: method `bar` is private | ^^^^^^^^^^^^^ error[E0624]: method `bar` is private - --> $DIR/privacy1.rs:101:9 + --> $DIR/privacy1.rs:115:9 | LL | ::bar::baz::A::bar(); //~ ERROR: module `baz` is private | ^^^^^^^^^^^^^^^^^^ error[E0624]: method `bar2` is private - --> $DIR/privacy1.rs:104:23 + --> $DIR/privacy1.rs:118:23 | LL | ::bar::baz::A.bar2(); //~ ERROR: module `baz` is private | ^^^^ diff --git a/src/test/compile-fail/proc-macro/attr-invalid-exprs.rs b/src/test/ui/proc-macro/attr-invalid-exprs.rs similarity index 100% rename from src/test/compile-fail/proc-macro/attr-invalid-exprs.rs rename to src/test/ui/proc-macro/attr-invalid-exprs.rs diff --git a/src/test/ui/proc-macro/attr-invalid-exprs.stderr b/src/test/ui/proc-macro/attr-invalid-exprs.stderr new file mode 100644 index 00000000000..c28def63e3e --- /dev/null +++ b/src/test/ui/proc-macro/attr-invalid-exprs.stderr @@ -0,0 +1,28 @@ +error: expected expression, found `` + --> $DIR/attr-invalid-exprs.rs:21:13 + | +LL | let _ = #[no_output] "Hello, world!"; + | ^^^^^^^^^^^^ + +error: macro expansion ignores token `,` and any following + --> $DIR/attr-invalid-exprs.rs:24:13 + | +LL | let _ = #[duplicate] "Hello, world!"; + | ^^^^^^^^^^^^- help: you might be missing a semicolon here: `;` + | | + | caused by the macro expansion here + | + = note: the usage of `duplicate!` is likely invalid in expression context + +error: macro expansion ignores token `,` and any following + --> $DIR/attr-invalid-exprs.rs:33:9 + | +LL | #[duplicate] + | ^^^^^^^^^^^^- help: you might be missing a semicolon here: `;` + | | + | caused by the macro expansion here + | + = note: the usage of `duplicate!` is likely invalid in expression context + +error: aborting due to 3 previous errors + diff --git a/src/test/compile-fail/proc-macro/attr-stmt-expr.rs b/src/test/ui/proc-macro/attr-stmt-expr.rs similarity index 100% rename from src/test/compile-fail/proc-macro/attr-stmt-expr.rs rename to src/test/ui/proc-macro/attr-stmt-expr.rs diff --git a/src/test/ui/proc-macro/attr-stmt-expr.stderr b/src/test/ui/proc-macro/attr-stmt-expr.stderr new file mode 100644 index 00000000000..ee9bc771782 --- /dev/null +++ b/src/test/ui/proc-macro/attr-stmt-expr.stderr @@ -0,0 +1,19 @@ +error[E0658]: attributes on expressions are experimental. (see issue #15701) + --> $DIR/attr-stmt-expr.rs:20:5 + | +LL | #[expect_print_expr] + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(stmt_expr_attributes)] to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental. (see issue #15701) + --> $DIR/attr-stmt-expr.rs:33:5 + | +LL | #[expect_expr] + | ^^^^^^^^^^^^^^ + | + = help: add #![feature(stmt_expr_attributes)] to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/compile-fail/proc-macro/attribute-with-error.rs b/src/test/ui/proc-macro/attribute-with-error.rs similarity index 100% rename from src/test/compile-fail/proc-macro/attribute-with-error.rs rename to src/test/ui/proc-macro/attribute-with-error.rs diff --git a/src/test/ui/proc-macro/attribute-with-error.stderr b/src/test/ui/proc-macro/attribute-with-error.stderr new file mode 100644 index 00000000000..d2b4ac63992 --- /dev/null +++ b/src/test/ui/proc-macro/attribute-with-error.stderr @@ -0,0 +1,39 @@ +error[E0308]: mismatched types + --> $DIR/attribute-with-error.rs:21:18 + | +LL | let a: i32 = "foo"; + | ^^^^^ expected i32, found reference + | + = note: expected type `i32` + found type `&'static str` + +error[E0308]: mismatched types + --> $DIR/attribute-with-error.rs:23:18 + | +LL | let b: i32 = "f'oo"; + | ^^^^^^ expected i32, found reference + | + = note: expected type `i32` + found type `&'static str` + +error[E0308]: mismatched types + --> $DIR/attribute-with-error.rs:36:22 + | +LL | let a: i32 = "foo"; + | ^^^^^ expected i32, found reference + | + = note: expected type `i32` + found type `&'static str` + +error[E0308]: mismatched types + --> $DIR/attribute-with-error.rs:46:22 + | +LL | let a: i32 = "foo"; + | ^^^^^ expected i32, found reference + | + = note: expected type `i32` + found type `&'static str` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/compile-fail/proc-macro/attribute.rs b/src/test/ui/proc-macro/attribute.rs similarity index 100% rename from src/test/compile-fail/proc-macro/attribute.rs rename to src/test/ui/proc-macro/attribute.rs diff --git a/src/test/ui/proc-macro/attribute.stderr b/src/test/ui/proc-macro/attribute.stderr new file mode 100644 index 00000000000..c752c5364f4 --- /dev/null +++ b/src/test/ui/proc-macro/attribute.stderr @@ -0,0 +1,50 @@ +error: attribute must be of form: #[proc_macro_derive(TraitName)] + --> $DIR/attribute.rs:18:1 + | +LL | #[proc_macro_derive] + | ^^^^^^^^^^^^^^^^^^^^ + +error: attribute must be of form: #[proc_macro_derive(TraitName)] + --> $DIR/attribute.rs:24:1 + | +LL | #[proc_macro_derive = "foo"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: must only be one word + --> $DIR/attribute.rs:31:5 + | +LL | a = "b" + | ^^^^^^^ + +error: attribute must have either one or two arguments + --> $DIR/attribute.rs:38:1 + | +LL | #[proc_macro_derive(b, c, d)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: must only be one word + --> $DIR/attribute.rs:44:21 + | +LL | #[proc_macro_derive(d(e))] + | ^^^^ + +error: must only be one word + --> $DIR/attribute.rs:50:35 + | +LL | #[proc_macro_derive(f, attributes(g = "h"))] + | ^^^^^^^ + +error: must only be one word + --> $DIR/attribute.rs:56:35 + | +LL | #[proc_macro_derive(i, attributes(j(k)))] + | ^^^^ + +error: attribute must have either one or two arguments + --> $DIR/attribute.rs:62:1 + | +LL | #[proc_macro_derive(l, attributes(m), n)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 8 previous errors + diff --git a/src/test/compile-fail/proc-macro/attributes-included.rs b/src/test/ui/proc-macro/attributes-included.rs similarity index 100% rename from src/test/compile-fail/proc-macro/attributes-included.rs rename to src/test/ui/proc-macro/attributes-included.rs diff --git a/src/test/ui/proc-macro/attributes-included.stderr b/src/test/ui/proc-macro/attributes-included.stderr new file mode 100644 index 00000000000..e7eeccc01f2 --- /dev/null +++ b/src/test/ui/proc-macro/attributes-included.stderr @@ -0,0 +1,13 @@ +warning: unused variable: `a` + --> $DIR/attributes-included.rs:27:9 + | +LL | let a: i32 = "foo"; //~ WARN: unused variable + | ^ help: consider using `_a` instead + | +note: lint level defined here + --> $DIR/attributes-included.rs:14:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: #[warn(unused_variables)] implied by #[warn(unused)] + diff --git a/src/test/compile-fail/proc-macro/auxiliary/attr-stmt-expr.rs b/src/test/ui/proc-macro/auxiliary/attr-stmt-expr.rs similarity index 100% rename from src/test/compile-fail/proc-macro/auxiliary/attr-stmt-expr.rs rename to src/test/ui/proc-macro/auxiliary/attr-stmt-expr.rs diff --git a/src/test/compile-fail/proc-macro/auxiliary/attribute-with-error.rs b/src/test/ui/proc-macro/auxiliary/attribute-with-error.rs similarity index 100% rename from src/test/compile-fail/proc-macro/auxiliary/attribute-with-error.rs rename to src/test/ui/proc-macro/auxiliary/attribute-with-error.rs diff --git a/src/test/compile-fail/proc-macro/auxiliary/attributes-included.rs b/src/test/ui/proc-macro/auxiliary/attributes-included.rs similarity index 100% rename from src/test/compile-fail/proc-macro/auxiliary/attributes-included.rs rename to src/test/ui/proc-macro/auxiliary/attributes-included.rs diff --git a/src/test/compile-fail/proc-macro/auxiliary/bang_proc_macro2.rs b/src/test/ui/proc-macro/auxiliary/bang_proc_macro2.rs similarity index 100% rename from src/test/compile-fail/proc-macro/auxiliary/bang_proc_macro2.rs rename to src/test/ui/proc-macro/auxiliary/bang_proc_macro2.rs diff --git a/src/test/compile-fail/proc-macro/auxiliary/derive-a-b.rs b/src/test/ui/proc-macro/auxiliary/derive-a-b.rs similarity index 100% rename from src/test/compile-fail/proc-macro/auxiliary/derive-a-b.rs rename to src/test/ui/proc-macro/auxiliary/derive-a-b.rs diff --git a/src/test/compile-fail/proc-macro/auxiliary/derive-a.rs b/src/test/ui/proc-macro/auxiliary/derive-a.rs similarity index 100% rename from src/test/compile-fail/proc-macro/auxiliary/derive-a.rs rename to src/test/ui/proc-macro/auxiliary/derive-a.rs diff --git a/src/test/compile-fail/proc-macro/auxiliary/derive-b.rs b/src/test/ui/proc-macro/auxiliary/derive-b.rs similarity index 100% rename from src/test/compile-fail/proc-macro/auxiliary/derive-b.rs rename to src/test/ui/proc-macro/auxiliary/derive-b.rs diff --git a/src/test/compile-fail/proc-macro/auxiliary/derive-bad.rs b/src/test/ui/proc-macro/auxiliary/derive-bad.rs similarity index 100% rename from src/test/compile-fail/proc-macro/auxiliary/derive-bad.rs rename to src/test/ui/proc-macro/auxiliary/derive-bad.rs diff --git a/src/test/compile-fail/proc-macro/auxiliary/derive-unstable-2.rs b/src/test/ui/proc-macro/auxiliary/derive-unstable-2.rs similarity index 100% rename from src/test/compile-fail/proc-macro/auxiliary/derive-unstable-2.rs rename to src/test/ui/proc-macro/auxiliary/derive-unstable-2.rs diff --git a/src/test/compile-fail/proc-macro/auxiliary/derive-unstable.rs b/src/test/ui/proc-macro/auxiliary/derive-unstable.rs similarity index 100% rename from src/test/compile-fail/proc-macro/auxiliary/derive-unstable.rs rename to src/test/ui/proc-macro/auxiliary/derive-unstable.rs diff --git a/src/test/ui/proc-macro/auxiliary/dollar-crate-external.rs b/src/test/ui/proc-macro/auxiliary/dollar-crate-external.rs new file mode 100644 index 00000000000..8f15a2b975b --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/dollar-crate-external.rs @@ -0,0 +1,16 @@ +pub type S = u8; + +#[macro_export] +macro_rules! external { + () => { + dollar_crate::m! { + struct M($crate::S); + } + + #[dollar_crate::a] + struct A($crate::S); + + #[derive(dollar_crate::d)] + struct D($crate::S); + }; +} diff --git a/src/test/ui/proc-macro/auxiliary/dollar-crate.rs b/src/test/ui/proc-macro/auxiliary/dollar-crate.rs new file mode 100644 index 00000000000..d0ea850d4e3 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/dollar-crate.rs @@ -0,0 +1,28 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro] +pub fn m(input: TokenStream) -> TokenStream { + println!("PROC MACRO INPUT (PRETTY-PRINTED): {}", input); + println!("PROC MACRO INPUT: {:#?}", input); + input.into_iter().collect() +} + +#[proc_macro_attribute] +pub fn a(_args: TokenStream, input: TokenStream) -> TokenStream { + println!("ATTRIBUTE INPUT (PRETTY-PRINTED): {}", input); + println!("ATTRIBUTE INPUT: {:#?}", input); + input.into_iter().collect() +} + +#[proc_macro_derive(d)] +pub fn d(input: TokenStream) -> TokenStream { + println!("DERIVE INPUT (PRETTY-PRINTED): {}", input); + println!("DERIVE INPUT: {:#?}", input); + input.into_iter().collect() +} diff --git a/src/test/ui-fulldeps/proc-macro/auxiliary/edition-imports-2015.rs b/src/test/ui/proc-macro/auxiliary/edition-imports-2015.rs similarity index 95% rename from src/test/ui-fulldeps/proc-macro/auxiliary/edition-imports-2015.rs rename to src/test/ui/proc-macro/auxiliary/edition-imports-2015.rs index 5bb818f7d23..27c59b805e2 100644 --- a/src/test/ui-fulldeps/proc-macro/auxiliary/edition-imports-2015.rs +++ b/src/test/ui/proc-macro/auxiliary/edition-imports-2015.rs @@ -1,4 +1,5 @@ // edition:2015 +// force-host // no-prefer-dynamic #![crate_type = "proc-macro"] diff --git a/src/test/compile-fail/proc-macro/auxiliary/issue-41211.rs b/src/test/ui/proc-macro/auxiliary/issue-41211.rs similarity index 100% rename from src/test/compile-fail/proc-macro/auxiliary/issue-41211.rs rename to src/test/ui/proc-macro/auxiliary/issue-41211.rs diff --git a/src/test/compile-fail/proc-macro/auxiliary/issue_38586.rs b/src/test/ui/proc-macro/auxiliary/issue_38586.rs similarity index 100% rename from src/test/compile-fail/proc-macro/auxiliary/issue_38586.rs rename to src/test/ui/proc-macro/auxiliary/issue_38586.rs diff --git a/src/test/compile-fail/proc-macro/auxiliary/issue_50493.rs b/src/test/ui/proc-macro/auxiliary/issue_50493.rs similarity index 100% rename from src/test/compile-fail/proc-macro/auxiliary/issue_50493.rs rename to src/test/ui/proc-macro/auxiliary/issue_50493.rs diff --git a/src/test/compile-fail/proc-macro/auxiliary/more-gates.rs b/src/test/ui/proc-macro/auxiliary/more-gates.rs similarity index 100% rename from src/test/compile-fail/proc-macro/auxiliary/more-gates.rs rename to src/test/ui/proc-macro/auxiliary/more-gates.rs diff --git a/src/test/compile-fail/proc-macro/auxiliary/proc-macro-gates.rs b/src/test/ui/proc-macro/auxiliary/proc-macro-gates.rs similarity index 100% rename from src/test/compile-fail/proc-macro/auxiliary/proc-macro-gates.rs rename to src/test/ui/proc-macro/auxiliary/proc-macro-gates.rs diff --git a/src/test/compile-fail/proc-macro/auxiliary/test-macros.rs b/src/test/ui/proc-macro/auxiliary/test-macros.rs similarity index 100% rename from src/test/compile-fail/proc-macro/auxiliary/test-macros.rs rename to src/test/ui/proc-macro/auxiliary/test-macros.rs diff --git a/src/test/compile-fail/proc-macro/define-two.rs b/src/test/ui/proc-macro/define-two.rs similarity index 100% rename from src/test/compile-fail/proc-macro/define-two.rs rename to src/test/ui/proc-macro/define-two.rs diff --git a/src/test/ui/proc-macro/define-two.stderr b/src/test/ui/proc-macro/define-two.stderr new file mode 100644 index 00000000000..1ca2e0a3e3c --- /dev/null +++ b/src/test/ui/proc-macro/define-two.stderr @@ -0,0 +1,14 @@ +error[E0428]: the name `A` is defined multiple times + --> $DIR/define-two.rs:25:21 + | +LL | #[proc_macro_derive(A)] + | - previous definition of the macro `A` here +... +LL | #[proc_macro_derive(A)] //~ ERROR the name `A` is defined multiple times + | ^ `A` redefined here + | + = note: `A` must be defined only once in the macro namespace of this module + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0428`. diff --git a/src/test/compile-fail/proc-macro/derive-bad.rs b/src/test/ui/proc-macro/derive-bad.rs similarity index 100% rename from src/test/compile-fail/proc-macro/derive-bad.rs rename to src/test/ui/proc-macro/derive-bad.rs diff --git a/src/test/ui/proc-macro/derive-bad.stderr b/src/test/ui/proc-macro/derive-bad.stderr new file mode 100644 index 00000000000..57e72a07ee1 --- /dev/null +++ b/src/test/ui/proc-macro/derive-bad.stderr @@ -0,0 +1,14 @@ +error: expected `:`, found `}` + --> $DIR/derive-bad.rs:17:5 + | +LL | A + | ^ expected `:` + +error: proc-macro derive produced unparseable tokens + --> $DIR/derive-bad.rs:17:5 + | +LL | A + | ^ + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/proc-macro/derive-still-gated.rs b/src/test/ui/proc-macro/derive-still-gated.rs similarity index 86% rename from src/test/compile-fail/proc-macro/derive-still-gated.rs rename to src/test/ui/proc-macro/derive-still-gated.rs index f36236c5356..edf5cc7e9ae 100644 --- a/src/test/compile-fail/proc-macro/derive-still-gated.rs +++ b/src/test/ui/proc-macro/derive-still-gated.rs @@ -15,7 +15,7 @@ #[macro_use] extern crate derive_a; -#[derive_A] //~ ERROR: attributes of the form `#[derive_*]` are reserved for the compiler +#[derive_A] //~ ERROR attribute `derive_A` is currently unknown struct A; fn main() {} diff --git a/src/test/ui/proc-macro/derive-still-gated.stderr b/src/test/ui/proc-macro/derive-still-gated.stderr new file mode 100644 index 00000000000..4e5dd34b004 --- /dev/null +++ b/src/test/ui/proc-macro/derive-still-gated.stderr @@ -0,0 +1,11 @@ +error[E0658]: The attribute `derive_A` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/derive-still-gated.rs:18:3 + | +LL | #[derive_A] //~ ERROR attribute `derive_A` is currently unknown + | ^^^^^^^^ + | + = help: add #![feature(custom_attribute)] 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/proc-macro/dollar-crate.rs b/src/test/ui/proc-macro/dollar-crate.rs new file mode 100644 index 00000000000..1460e9a3b2d --- /dev/null +++ b/src/test/ui/proc-macro/dollar-crate.rs @@ -0,0 +1,40 @@ +// edition:2018 +// aux-build:dollar-crate.rs +// aux-build:dollar-crate-external.rs + +// Anonymize unstable non-dummy spans while still showing dummy spans `0..0`. +// normalize-stdout-test "bytes\([^0]\w*\.\.(\w+)\)" -> "bytes(LO..$1)" +// normalize-stdout-test "bytes\((\w+)\.\.[^0]\w*\)" -> "bytes($1..HI)" + +extern crate dollar_crate; +extern crate dollar_crate_external; + +type S = u8; + +mod local { + use crate::dollar_crate; + + macro_rules! local { + () => { + dollar_crate::m! { + struct M($crate::S); + } + + #[dollar_crate::a] + struct A($crate::S); + + #[derive(dollar_crate::d)] + struct D($crate::S); //~ ERROR the name `D` is defined multiple times + }; + } + + local!(); +} + +mod external { + use crate::dollar_crate_external; + + dollar_crate_external::external!(); //~ ERROR the name `D` is defined multiple times +} + +fn main() {} diff --git a/src/test/ui/proc-macro/dollar-crate.stderr b/src/test/ui/proc-macro/dollar-crate.stderr new file mode 100644 index 00000000000..08de3c7d1a6 --- /dev/null +++ b/src/test/ui/proc-macro/dollar-crate.stderr @@ -0,0 +1,29 @@ +error[E0428]: the name `D` is defined multiple times + --> $DIR/dollar-crate.rs:27:13 + | +LL | struct D($crate::S); //~ ERROR the name `D` is defined multiple times + | ^^^^^^^^^^^^^^^^^^^^ + | | + | `D` redefined here + | previous definition of the type `D` here +... +LL | local!(); + | --------- in this macro invocation + | + = note: `D` must be defined only once in the type namespace of this module + +error[E0428]: the name `D` is defined multiple times + --> $DIR/dollar-crate.rs:37:5 + | +LL | dollar_crate_external::external!(); //~ ERROR the name `D` is defined multiple times + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `D` redefined here + | previous definition of the type `D` here + | + = note: `D` must be defined only once in the type namespace of this module + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0428`. diff --git a/src/test/ui/proc-macro/dollar-crate.stdout b/src/test/ui/proc-macro/dollar-crate.stdout new file mode 100644 index 00000000000..c47b3603f41 --- /dev/null +++ b/src/test/ui/proc-macro/dollar-crate.stdout @@ -0,0 +1,240 @@ +PROC MACRO INPUT (PRETTY-PRINTED): struct M ( $crate :: S ) ; +PROC MACRO INPUT: TokenStream [ + Ident { + ident: "struct", + span: #2 bytes(LO..HI) + }, + Ident { + ident: "M", + span: #2 bytes(LO..HI) + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "$crate", + span: #2 bytes(LO..HI) + }, + Punct { + ch: ':', + spacing: Joint, + span: #2 bytes(LO..HI) + }, + Punct { + ch: ':', + spacing: Alone, + span: #2 bytes(LO..HI) + }, + Ident { + ident: "S", + span: #2 bytes(LO..HI) + } + ], + span: #2 bytes(LO..HI) + }, + Punct { + ch: ';', + spacing: Alone, + span: #2 bytes(LO..HI) + } +] +ATTRIBUTE INPUT (PRETTY-PRINTED): struct A(crate::S); +ATTRIBUTE INPUT: TokenStream [ + Ident { + ident: "struct", + span: #2 bytes(LO..HI) + }, + Ident { + ident: "A", + span: #2 bytes(LO..HI) + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "$crate", + span: #2 bytes(LO..HI) + }, + Punct { + ch: ':', + spacing: Joint, + span: #2 bytes(LO..HI) + }, + Punct { + ch: ':', + spacing: Alone, + span: #2 bytes(LO..HI) + }, + Ident { + ident: "S", + span: #2 bytes(LO..HI) + } + ], + span: #2 bytes(LO..HI) + }, + Punct { + ch: ';', + spacing: Alone, + span: #2 bytes(LO..HI) + } +] +DERIVE INPUT (PRETTY-PRINTED): struct D(crate::S); +DERIVE INPUT: TokenStream [ + Ident { + ident: "struct", + span: #2 bytes(LO..HI) + }, + Ident { + ident: "D", + span: #2 bytes(LO..HI) + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "$crate", + span: #2 bytes(LO..HI) + }, + Punct { + ch: ':', + spacing: Joint, + span: #2 bytes(LO..HI) + }, + Punct { + ch: ':', + spacing: Alone, + span: #2 bytes(LO..HI) + }, + Ident { + ident: "S", + span: #2 bytes(LO..HI) + } + ], + span: #2 bytes(LO..HI) + }, + Punct { + ch: ';', + spacing: Alone, + span: #2 bytes(LO..HI) + } +] +PROC MACRO INPUT (PRETTY-PRINTED): struct M ( $crate :: S ) ; +PROC MACRO INPUT: TokenStream [ + Ident { + ident: "struct", + span: #10 bytes(LO..HI) + }, + Ident { + ident: "M", + span: #10 bytes(LO..HI) + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "$crate", + span: #10 bytes(LO..HI) + }, + Punct { + ch: ':', + spacing: Joint, + span: #10 bytes(LO..HI) + }, + Punct { + ch: ':', + spacing: Alone, + span: #10 bytes(LO..HI) + }, + Ident { + ident: "S", + span: #10 bytes(LO..HI) + } + ], + span: #10 bytes(LO..HI) + }, + Punct { + ch: ';', + spacing: Alone, + span: #10 bytes(LO..HI) + } +] +ATTRIBUTE INPUT (PRETTY-PRINTED): struct A(::dollar_crate_external::S); +ATTRIBUTE INPUT: TokenStream [ + Ident { + ident: "struct", + span: #10 bytes(LO..HI) + }, + Ident { + ident: "A", + span: #10 bytes(LO..HI) + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "$crate", + span: #10 bytes(LO..HI) + }, + Punct { + ch: ':', + spacing: Joint, + span: #10 bytes(LO..HI) + }, + Punct { + ch: ':', + spacing: Alone, + span: #10 bytes(LO..HI) + }, + Ident { + ident: "S", + span: #10 bytes(LO..HI) + } + ], + span: #10 bytes(LO..HI) + }, + Punct { + ch: ';', + spacing: Alone, + span: #10 bytes(LO..HI) + } +] +DERIVE INPUT (PRETTY-PRINTED): struct D(::dollar_crate_external::S); +DERIVE INPUT: TokenStream [ + Ident { + ident: "struct", + span: #10 bytes(LO..HI) + }, + Ident { + ident: "D", + span: #10 bytes(LO..HI) + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "$crate", + span: #10 bytes(LO..HI) + }, + Punct { + ch: ':', + spacing: Joint, + span: #10 bytes(LO..HI) + }, + Punct { + ch: ':', + spacing: Alone, + span: #10 bytes(LO..HI) + }, + Ident { + ident: "S", + span: #10 bytes(LO..HI) + } + ], + span: #10 bytes(LO..HI) + }, + Punct { + ch: ';', + spacing: Alone, + span: #10 bytes(LO..HI) + } +] diff --git a/src/test/ui-fulldeps/proc-macro/edition-imports-2018.rs b/src/test/ui/proc-macro/edition-imports-2018.rs similarity index 100% rename from src/test/ui-fulldeps/proc-macro/edition-imports-2018.rs rename to src/test/ui/proc-macro/edition-imports-2018.rs diff --git a/src/test/compile-fail/proc-macro/expand-to-unstable-2.rs b/src/test/ui/proc-macro/expand-to-unstable-2.rs similarity index 100% rename from src/test/compile-fail/proc-macro/expand-to-unstable-2.rs rename to src/test/ui/proc-macro/expand-to-unstable-2.rs diff --git a/src/test/ui/proc-macro/expand-to-unstable-2.stderr b/src/test/ui/proc-macro/expand-to-unstable-2.stderr new file mode 100644 index 00000000000..855e9051974 --- /dev/null +++ b/src/test/ui/proc-macro/expand-to-unstable-2.stderr @@ -0,0 +1,11 @@ +error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics (see issue #29642) + --> $DIR/expand-to-unstable-2.rs:18:10 + | +LL | #[derive(Unstable)] + | ^^^^^^^^ + | + = help: add #![feature(rustc_attrs)] 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/compile-fail/proc-macro/expand-to-unstable.rs b/src/test/ui/proc-macro/expand-to-unstable.rs similarity index 100% rename from src/test/compile-fail/proc-macro/expand-to-unstable.rs rename to src/test/ui/proc-macro/expand-to-unstable.rs diff --git a/src/test/ui/proc-macro/expand-to-unstable.stderr b/src/test/ui/proc-macro/expand-to-unstable.stderr new file mode 100644 index 00000000000..e851b0e2bc3 --- /dev/null +++ b/src/test/ui/proc-macro/expand-to-unstable.stderr @@ -0,0 +1,11 @@ +error[E0658]: use of unstable library feature 'core_intrinsics': intrinsics are unlikely to ever be stabilized, instead they should be used through stabilized interfaces in the rest of the standard library + --> $DIR/expand-to-unstable.rs:18:10 + | +LL | #[derive(Unstable)] + | ^^^^^^^^ + | + = help: add #![feature(core_intrinsics)] 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/compile-fail/proc-macro/export-macro.rs b/src/test/ui/proc-macro/export-macro.rs similarity index 100% rename from src/test/compile-fail/proc-macro/export-macro.rs rename to src/test/ui/proc-macro/export-macro.rs diff --git a/src/test/ui/proc-macro/export-macro.stderr b/src/test/ui/proc-macro/export-macro.stderr new file mode 100644 index 00000000000..f82d5ab5f1c --- /dev/null +++ b/src/test/ui/proc-macro/export-macro.stderr @@ -0,0 +1,10 @@ +error: cannot export macro_rules! macros from a `proc-macro` crate type currently + --> $DIR/export-macro.rs:19:1 + | +LL | / macro_rules! foo { +LL | | ($e:expr) => ($e) +LL | | } + | |_^ + +error: aborting due to previous error + diff --git a/src/test/compile-fail/proc-macro/exports.rs b/src/test/ui/proc-macro/exports.rs similarity index 100% rename from src/test/compile-fail/proc-macro/exports.rs rename to src/test/ui/proc-macro/exports.rs diff --git a/src/test/ui/proc-macro/exports.stderr b/src/test/ui/proc-macro/exports.stderr new file mode 100644 index 00000000000..3637d0fbd83 --- /dev/null +++ b/src/test/ui/proc-macro/exports.stderr @@ -0,0 +1,26 @@ +error: `proc-macro` crate types cannot export any items other than functions tagged with `#[proc_macro_derive]` currently + --> $DIR/exports.rs:17:1 + | +LL | pub fn a() {} //~ ERROR: cannot export any items + | ^^^^^^^^^^^^^ + +error: `proc-macro` crate types cannot export any items other than functions tagged with `#[proc_macro_derive]` currently + --> $DIR/exports.rs:18:1 + | +LL | pub struct B; //~ ERROR: cannot export any items + | ^^^^^^^^^^^^^ + +error: `proc-macro` crate types cannot export any items other than functions tagged with `#[proc_macro_derive]` currently + --> $DIR/exports.rs:19:1 + | +LL | pub enum C {} //~ ERROR: cannot export any items + | ^^^^^^^^^^^^^ + +error: `proc-macro` crate types cannot export any items other than functions tagged with `#[proc_macro_derive]` currently + --> $DIR/exports.rs:20:1 + | +LL | pub mod d {} //~ ERROR: cannot export any items + | ^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/src/test/compile-fail/proc-macro/illegal-proc-macro-derive-use.rs b/src/test/ui/proc-macro/illegal-proc-macro-derive-use.rs similarity index 100% rename from src/test/compile-fail/proc-macro/illegal-proc-macro-derive-use.rs rename to src/test/ui/proc-macro/illegal-proc-macro-derive-use.rs diff --git a/src/test/ui/proc-macro/illegal-proc-macro-derive-use.stderr b/src/test/ui/proc-macro/illegal-proc-macro-derive-use.stderr new file mode 100644 index 00000000000..715ff0e20a9 --- /dev/null +++ b/src/test/ui/proc-macro/illegal-proc-macro-derive-use.stderr @@ -0,0 +1,14 @@ +error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type + --> $DIR/illegal-proc-macro-derive-use.rs:13:1 + | +LL | #[proc_macro_derive(Foo)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the `#[proc_macro_derive]` attribute may only be used on bare functions + --> $DIR/illegal-proc-macro-derive-use.rs:20:1 + | +LL | #[proc_macro_derive(Foo)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/proc-macro/import.rs b/src/test/ui/proc-macro/import.rs similarity index 100% rename from src/test/compile-fail/proc-macro/import.rs rename to src/test/ui/proc-macro/import.rs diff --git a/src/test/ui/proc-macro/import.stderr b/src/test/ui/proc-macro/import.stderr new file mode 100644 index 00000000000..f3633b21583 --- /dev/null +++ b/src/test/ui/proc-macro/import.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `derive_a::derive_a` + --> $DIR/import.rs:18:5 + | +LL | use derive_a::derive_a; + | ^^^^^^^^^^^^^^^^^^ no `derive_a` in the root + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/compile-fail/proc-macro/issue-37788.rs b/src/test/ui/proc-macro/issue-37788.rs similarity index 100% rename from src/test/compile-fail/proc-macro/issue-37788.rs rename to src/test/ui/proc-macro/issue-37788.rs diff --git a/src/test/ui/proc-macro/issue-37788.stderr b/src/test/ui/proc-macro/issue-37788.stderr new file mode 100644 index 00000000000..f5ddf9ba6b8 --- /dev/null +++ b/src/test/ui/proc-macro/issue-37788.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/issue-37788.rs:18:5 + | +LL | fn main() { + | - expected `()` because of default return type +LL | // Test that constructing the `visible_parent_map` (in `cstore_impl.rs`) does not ICE. +LL | std::cell::Cell::new(0) //~ ERROR mismatched types + | ^^^^^^^^^^^^^^^^^^^^^^^- help: try adding a semicolon: `;` + | | + | expected (), found struct `std::cell::Cell` + | + = note: expected type `()` + found type `std::cell::Cell<{integer}>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/compile-fail/proc-macro/issue-38586.rs b/src/test/ui/proc-macro/issue-38586.rs similarity index 100% rename from src/test/compile-fail/proc-macro/issue-38586.rs rename to src/test/ui/proc-macro/issue-38586.rs diff --git a/src/test/ui/proc-macro/issue-38586.stderr b/src/test/ui/proc-macro/issue-38586.stderr new file mode 100644 index 00000000000..6ba2c0b269f --- /dev/null +++ b/src/test/ui/proc-macro/issue-38586.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `foo` in this scope + --> $DIR/issue-38586.rs:16:10 + | +LL | #[derive(A)] //~ ERROR `foo` + | ^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/compile-fail/proc-macro/issue-41211.rs b/src/test/ui/proc-macro/issue-41211.rs similarity index 100% rename from src/test/compile-fail/proc-macro/issue-41211.rs rename to src/test/ui/proc-macro/issue-41211.rs diff --git a/src/test/ui/proc-macro/issue-41211.stderr b/src/test/ui/proc-macro/issue-41211.stderr new file mode 100644 index 00000000000..ba5fad432b7 --- /dev/null +++ b/src/test/ui/proc-macro/issue-41211.stderr @@ -0,0 +1,11 @@ +error[E0658]: The attribute `emit_unchanged` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/issue-41211.rs:18:4 + | +LL | #![emit_unchanged] + | ^^^^^^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] 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/compile-fail/proc-macro/issue-50493.rs b/src/test/ui/proc-macro/issue-50493.rs similarity index 100% rename from src/test/compile-fail/proc-macro/issue-50493.rs rename to src/test/ui/proc-macro/issue-50493.rs diff --git a/src/test/ui/proc-macro/issue-50493.stderr b/src/test/ui/proc-macro/issue-50493.stderr new file mode 100644 index 00000000000..3dcb5265535 --- /dev/null +++ b/src/test/ui/proc-macro/issue-50493.stderr @@ -0,0 +1,15 @@ +error: visibilities can only be restricted to ancestor modules + --> $DIR/issue-50493.rs:18:12 + | +LL | pub(in restricted) field: usize, //~ visibilities can only be restricted to ancestor modules + | ^^^^^^^^^^ + +error[E0616]: field `field` of struct `Restricted` is private + --> $DIR/issue-50493.rs:16:10 + | +LL | #[derive(Derive)] //~ ERROR field `field` of struct `Restricted` is private + | ^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0616`. diff --git a/src/test/compile-fail/proc-macro/item-error.rs b/src/test/ui/proc-macro/item-error.rs similarity index 100% rename from src/test/compile-fail/proc-macro/item-error.rs rename to src/test/ui/proc-macro/item-error.rs diff --git a/src/test/ui/proc-macro/item-error.stderr b/src/test/ui/proc-macro/item-error.stderr new file mode 100644 index 00000000000..d1932868797 --- /dev/null +++ b/src/test/ui/proc-macro/item-error.stderr @@ -0,0 +1,9 @@ +error[E0106]: missing lifetime specifier + --> $DIR/item-error.rs:20:8 + | +LL | a: &u64 + | ^ expected lifetime parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/compile-fail/proc-macro/lints_in_proc_macros.rs b/src/test/ui/proc-macro/lints_in_proc_macros.rs similarity index 100% rename from src/test/compile-fail/proc-macro/lints_in_proc_macros.rs rename to src/test/ui/proc-macro/lints_in_proc_macros.rs diff --git a/src/test/ui/proc-macro/lints_in_proc_macros.stderr b/src/test/ui/proc-macro/lints_in_proc_macros.stderr new file mode 100644 index 00000000000..42d9a307226 --- /dev/null +++ b/src/test/ui/proc-macro/lints_in_proc_macros.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `foobar2` in this scope + --> $DIR/lints_in_proc_macros.rs:22:5 + | +LL | bang_proc_macro2!(); + | ^^^^^^^^^^^^^^^^^^^^ did you mean `foobar`? + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/compile-fail/proc-macro/macros-in-extern.rs b/src/test/ui/proc-macro/macros-in-extern.rs similarity index 100% rename from src/test/compile-fail/proc-macro/macros-in-extern.rs rename to src/test/ui/proc-macro/macros-in-extern.rs diff --git a/src/test/ui/proc-macro/macros-in-extern.stderr b/src/test/ui/proc-macro/macros-in-extern.stderr new file mode 100644 index 00000000000..5c51de45801 --- /dev/null +++ b/src/test/ui/proc-macro/macros-in-extern.stderr @@ -0,0 +1,27 @@ +error[E0658]: macro invocations in `extern {}` blocks are experimental (see issue #49476) + --> $DIR/macros-in-extern.rs:25:5 + | +LL | #[no_output] + | ^^^^^^^^^^^^ + | + = help: add #![feature(macros_in_extern)] to the crate attributes to enable + +error[E0658]: macro invocations in `extern {}` blocks are experimental (see issue #49476) + --> $DIR/macros-in-extern.rs:29:5 + | +LL | #[nop_attr] + | ^^^^^^^^^^^ + | + = help: add #![feature(macros_in_extern)] to the crate attributes to enable + +error[E0658]: macro invocations in `extern {}` blocks are experimental (see issue #49476) + --> $DIR/macros-in-extern.rs:33:5 + | +LL | emit_input!(fn rust_dbg_extern_identity_u32(arg: u32) -> u32;); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(macros_in_extern)] to the crate attributes to enable + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/compile-fail/proc-macro/more-gates.rs b/src/test/ui/proc-macro/more-gates.rs similarity index 100% rename from src/test/compile-fail/proc-macro/more-gates.rs rename to src/test/ui/proc-macro/more-gates.rs diff --git a/src/test/ui/proc-macro/more-gates.stderr b/src/test/ui/proc-macro/more-gates.stderr new file mode 100644 index 00000000000..d5f30d5817c --- /dev/null +++ b/src/test/ui/proc-macro/more-gates.stderr @@ -0,0 +1,43 @@ +error[E0658]: procedural macros cannot expand to macro definitions (see issue #54727) + --> $DIR/more-gates.rs:17:1 + | +LL | #[attr2mac1] + | ^^^^^^^^^^^^ + | + = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable + +error[E0658]: procedural macros cannot expand to macro definitions (see issue #54727) + --> $DIR/more-gates.rs:20:1 + | +LL | #[attr2mac2] + | ^^^^^^^^^^^^ + | + = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable + +error[E0658]: procedural macros cannot expand to macro definitions (see issue #54727) + --> $DIR/more-gates.rs:24:1 + | +LL | mac2mac1!(); //~ ERROR: cannot expand to macro definitions + | ^^^^^^^^^^^^ + | + = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable + +error[E0658]: procedural macros cannot expand to macro definitions (see issue #54727) + --> $DIR/more-gates.rs:25:1 + | +LL | mac2mac2!(); //~ ERROR: cannot expand to macro definitions + | ^^^^^^^^^^^^ + | + = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable + +error[E0658]: procedural macros cannot expand to macro definitions (see issue #54727) + --> $DIR/more-gates.rs:27:1 + | +LL | tricky!(); + | ^^^^^^^^^^ + | + = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/compile-fail/proc-macro/no-macro-use-attr.rs b/src/test/ui/proc-macro/no-macro-use-attr.rs similarity index 100% rename from src/test/compile-fail/proc-macro/no-macro-use-attr.rs rename to src/test/ui/proc-macro/no-macro-use-attr.rs diff --git a/src/test/ui/proc-macro/no-macro-use-attr.stderr b/src/test/ui/proc-macro/no-macro-use-attr.stderr new file mode 100644 index 00000000000..447cb26f056 --- /dev/null +++ b/src/test/ui/proc-macro/no-macro-use-attr.stderr @@ -0,0 +1,20 @@ +warning: unused extern crate + --> $DIR/no-macro-use-attr.rs:16:1 + | +LL | extern crate derive_a; + | ^^^^^^^^^^^^^^^^^^^^^^ help: remove it + | +note: lint level defined here + --> $DIR/no-macro-use-attr.rs:14:9 + | +LL | #![warn(unused_extern_crates)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: compilation successful + --> $DIR/no-macro-use-attr.rs:20:1 + | +LL | fn main() {} //~ ERROR compilation successful + | ^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/compile-fail/proc-macro/proc-macro-attributes.rs b/src/test/ui/proc-macro/proc-macro-attributes.rs similarity index 100% rename from src/test/compile-fail/proc-macro/proc-macro-attributes.rs rename to src/test/ui/proc-macro/proc-macro-attributes.rs diff --git a/src/test/ui/proc-macro/proc-macro-attributes.stderr b/src/test/ui/proc-macro/proc-macro-attributes.stderr new file mode 100644 index 00000000000..a1289c6356a --- /dev/null +++ b/src/test/ui/proc-macro/proc-macro-attributes.stderr @@ -0,0 +1,11 @@ +error[E0658]: The attribute `C` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/proc-macro-attributes.rs:17:3 + | +LL | #[C] //~ ERROR attribute `C` is currently unknown to the compiler + | ^ + | + = help: add #![feature(custom_attribute)] 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/compile-fail/proc-macro/proc-macro-gates.rs b/src/test/ui/proc-macro/proc-macro-gates.rs similarity index 100% rename from src/test/compile-fail/proc-macro/proc-macro-gates.rs rename to src/test/ui/proc-macro/proc-macro-gates.rs diff --git a/src/test/ui/proc-macro/proc-macro-gates.stderr b/src/test/ui/proc-macro/proc-macro-gates.stderr new file mode 100644 index 00000000000..d5c85d97b54 --- /dev/null +++ b/src/test/ui/proc-macro/proc-macro-gates.stderr @@ -0,0 +1,137 @@ +error[E0658]: non-builtin inner attributes are unstable (see issue #54726) + --> $DIR/proc-macro-gates.rs:21:5 + | +LL | #![a] //~ ERROR: non-builtin inner attributes are unstable + | ^^^^^ + | + = help: add #![feature(custom_inner_attributes)] to the crate attributes to enable + +error[E0658]: non-builtin inner attributes are unstable (see issue #54726) + --> $DIR/proc-macro-gates.rs:28:5 + | +LL | #![a] //~ ERROR: custom attributes cannot be applied to modules + | ^^^^^ + | + = help: add #![feature(custom_inner_attributes)] to the crate attributes to enable + +error[E0658]: custom attributes cannot be applied to modules (see issue #54727) + --> $DIR/proc-macro-gates.rs:24:1 + | +LL | #[a] //~ ERROR: custom attributes cannot be applied to modules + | ^^^^ + | + = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable + +error[E0658]: custom attributes cannot be applied to modules (see issue #54727) + --> $DIR/proc-macro-gates.rs:28:5 + | +LL | #![a] //~ ERROR: custom attributes cannot be applied to modules + | ^^^^^ + | + = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable + +error: custom attribute invocations must be of the form #[foo] or #[foo(..)], the macro name must only be followed by a delimiter token + --> $DIR/proc-macro-gates.rs:32:1 + | +LL | #[a = y] //~ ERROR: must only be followed by a delimiter token + | ^^^^^^^^ + +error[E0658]: custom attributes cannot be applied to statements (see issue #54727) + --> $DIR/proc-macro-gates.rs:41:5 + | +LL | #[a] //~ ERROR: custom attributes cannot be applied to statements + | ^^^^ + | + = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable + +error[E0658]: custom attributes cannot be applied to statements (see issue #54727) + --> $DIR/proc-macro-gates.rs:45:5 + | +LL | #[a] //~ ERROR: custom attributes cannot be applied to statements + | ^^^^ + | + = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable + +error[E0658]: custom attributes cannot be applied to statements (see issue #54727) + --> $DIR/proc-macro-gates.rs:49:5 + | +LL | #[a] //~ ERROR: custom attributes cannot be applied to statements + | ^^^^ + | + = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable + +error[E0658]: custom attributes cannot be applied to expressions (see issue #54727) + --> $DIR/proc-macro-gates.rs:53:14 + | +LL | let _x = #[a] 2; //~ ERROR: custom attributes cannot be applied to expressions + | ^^^^ + | + = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable + +error[E0658]: custom attributes cannot be applied to expressions (see issue #54727) + --> $DIR/proc-macro-gates.rs:56:15 + | +LL | let _x = [#[a] 2]; //~ ERROR: custom attributes cannot be applied to expressions + | ^^^^ + | + = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable + +error[E0658]: custom attributes cannot be applied to expressions (see issue #54727) + --> $DIR/proc-macro-gates.rs:59:14 + | +LL | let _x = #[a] println!(); //~ ERROR: custom attributes cannot be applied to expressions + | ^^^^ + | + = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable + +error[E0658]: procedural macros cannot be expanded to types (see issue #54727) + --> $DIR/proc-macro-gates.rs:63:13 + | +LL | let _x: m!(u32) = 3; //~ ERROR: procedural macros cannot be expanded to types + | ^^^^^^^ + | + = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable + +error[E0658]: procedural macros cannot be expanded to patterns (see issue #54727) + --> $DIR/proc-macro-gates.rs:64:12 + | +LL | if let m!(Some(_x)) = Some(3) {} //~ ERROR: procedural macros cannot be expanded to patterns + | ^^^^^^^^^^^^ + | + = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable + +error[E0658]: procedural macros cannot be expanded to statements (see issue #54727) + --> $DIR/proc-macro-gates.rs:66:5 + | +LL | m!(struct S;); //~ ERROR: procedural macros cannot be expanded to statements + | ^^^^^^^^^^^^^^ + | + = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable + +error[E0658]: procedural macros cannot be expanded to statements (see issue #54727) + --> $DIR/proc-macro-gates.rs:67:5 + | +LL | m!(let _x = 3;); //~ ERROR: procedural macros cannot be expanded to statements + | ^^^^^^^^^^^^^^^^ + | + = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable + +error[E0658]: procedural macros cannot be expanded to expressions (see issue #54727) + --> $DIR/proc-macro-gates.rs:69:14 + | +LL | let _x = m!(3); //~ ERROR: procedural macros cannot be expanded to expressions + | ^^^^^ + | + = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable + +error[E0658]: procedural macros cannot be expanded to expressions (see issue #54727) + --> $DIR/proc-macro-gates.rs:70:15 + | +LL | let _x = [m!(3)]; //~ ERROR: procedural macros cannot be expanded to expressions + | ^^^^^ + | + = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable + +error: aborting due to 17 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/compile-fail/proc-macro/proc-macro-gates2.rs b/src/test/ui/proc-macro/proc-macro-gates2.rs similarity index 100% rename from src/test/compile-fail/proc-macro/proc-macro-gates2.rs rename to src/test/ui/proc-macro/proc-macro-gates2.rs diff --git a/src/test/ui/proc-macro/proc-macro-gates2.stderr b/src/test/ui/proc-macro/proc-macro-gates2.stderr new file mode 100644 index 00000000000..2c0f2b09f06 --- /dev/null +++ b/src/test/ui/proc-macro/proc-macro-gates2.stderr @@ -0,0 +1,19 @@ +error[E0658]: The attribute `a` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/proc-macro-gates2.rs:23:11 + | +LL | fn _test6<#[a] T>() {} + | ^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error[E0658]: The attribute `a` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/proc-macro-gates2.rs:28:9 + | +LL | #[a] //~ ERROR: unknown to the compiler + | ^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/compile-fail/proc-macro/pub-at-crate-root.rs b/src/test/ui/proc-macro/pub-at-crate-root.rs similarity index 100% rename from src/test/compile-fail/proc-macro/pub-at-crate-root.rs rename to src/test/ui/proc-macro/pub-at-crate-root.rs diff --git a/src/test/ui/proc-macro/pub-at-crate-root.stderr b/src/test/ui/proc-macro/pub-at-crate-root.stderr new file mode 100644 index 00000000000..ba9a8605f1f --- /dev/null +++ b/src/test/ui/proc-macro/pub-at-crate-root.stderr @@ -0,0 +1,32 @@ +error: `proc-macro` crate types cannot export any items other than functions tagged with `#[proc_macro_derive]` currently + --> $DIR/pub-at-crate-root.rs:18:1 + | +LL | / pub mod a { //~ `proc-macro` crate types cannot export any items +LL | | use proc_macro::TokenStream; +LL | | +LL | | #[proc_macro_derive(B)] +... | +LL | | } +LL | | } + | |_^ + +error: functions tagged with `#[proc_macro_derive]` must currently reside in the root of the crate + --> $DIR/pub-at-crate-root.rs:22:5 + | +LL | / pub fn bar(a: TokenStream) -> TokenStream { +LL | | //~^ ERROR: must currently reside in the root of the crate +LL | | a +LL | | } + | |_____^ + +error: functions tagged with `#[proc_macro_derive]` must be `pub` + --> $DIR/pub-at-crate-root.rs:29:1 + | +LL | / fn bar(a: proc_macro::TokenStream) -> proc_macro::TokenStream { +LL | | //~^ ERROR: functions tagged with `#[proc_macro_derive]` must be `pub` +LL | | a +LL | | } + | |_^ + +error: aborting due to 3 previous errors + diff --git a/src/test/compile-fail/proc-macro/shadow-builtin.rs b/src/test/ui/proc-macro/shadow-builtin.rs similarity index 100% rename from src/test/compile-fail/proc-macro/shadow-builtin.rs rename to src/test/ui/proc-macro/shadow-builtin.rs diff --git a/src/test/ui/proc-macro/shadow-builtin.stderr b/src/test/ui/proc-macro/shadow-builtin.stderr new file mode 100644 index 00000000000..6d04c907386 --- /dev/null +++ b/src/test/ui/proc-macro/shadow-builtin.stderr @@ -0,0 +1,8 @@ +error: cannot override a built-in #[derive] mode + --> $DIR/shadow-builtin.rs:20:21 + | +LL | #[proc_macro_derive(PartialEq)] + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/compile-fail/proc-macro/shadow.rs b/src/test/ui/proc-macro/shadow.rs similarity index 100% rename from src/test/compile-fail/proc-macro/shadow.rs rename to src/test/ui/proc-macro/shadow.rs diff --git a/src/test/ui/proc-macro/shadow.stderr b/src/test/ui/proc-macro/shadow.stderr new file mode 100644 index 00000000000..847fc73f9e0 --- /dev/null +++ b/src/test/ui/proc-macro/shadow.stderr @@ -0,0 +1,18 @@ +error[E0259]: the name `derive_a` is defined multiple times + --> $DIR/shadow.rs:16:1 + | +LL | extern crate derive_a; + | ---------------------- previous import of the extern crate `derive_a` here +LL | #[macro_use] +LL | extern crate derive_a; //~ ERROR the name `derive_a` is defined multiple times + | ^^^^^^^^^^^^^^^^^^^^^^ `derive_a` reimported here + | + = note: `derive_a` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | extern crate derive_a as other_derive_a; //~ ERROR the name `derive_a` is defined multiple times + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0259`. diff --git a/src/test/compile-fail/proc-macro/two-crate-types-1.rs b/src/test/ui/proc-macro/two-crate-types-1.rs similarity index 100% rename from src/test/compile-fail/proc-macro/two-crate-types-1.rs rename to src/test/ui/proc-macro/two-crate-types-1.rs diff --git a/src/test/ui/proc-macro/two-crate-types-1.stderr b/src/test/ui/proc-macro/two-crate-types-1.stderr new file mode 100644 index 00000000000..deaba1cf272 --- /dev/null +++ b/src/test/ui/proc-macro/two-crate-types-1.stderr @@ -0,0 +1,4 @@ +error: cannot mix `proc-macro` crate type with others + +error: aborting due to previous error + diff --git a/src/test/compile-fail/proc-macro/two-crate-types-2.rs b/src/test/ui/proc-macro/two-crate-types-2.rs similarity index 100% rename from src/test/compile-fail/proc-macro/two-crate-types-2.rs rename to src/test/ui/proc-macro/two-crate-types-2.rs diff --git a/src/test/ui/proc-macro/two-crate-types-2.stderr b/src/test/ui/proc-macro/two-crate-types-2.stderr new file mode 100644 index 00000000000..deaba1cf272 --- /dev/null +++ b/src/test/ui/proc-macro/two-crate-types-2.stderr @@ -0,0 +1,4 @@ +error: cannot mix `proc-macro` crate type with others + +error: aborting due to previous error + diff --git a/src/test/ui/pub/pub-ident-fn-2.rs b/src/test/ui/pub/pub-ident-fn-2.rs index 44884bfcdfd..648b1067add 100644 --- a/src/test/ui/pub/pub-ident-fn-2.rs +++ b/src/test/ui/pub/pub-ident-fn-2.rs @@ -9,7 +9,7 @@ // except according to those terms. pub foo(s: usize) { bar() } -//~^ ERROR missing `fn` for method definition +//~^ ERROR missing `fn` for function definition fn main() { foo(2); diff --git a/src/test/ui/pub/pub-ident-fn-2.stderr b/src/test/ui/pub/pub-ident-fn-2.stderr index bbbb3df8769..ed7430fd394 100644 --- a/src/test/ui/pub/pub-ident-fn-2.stderr +++ b/src/test/ui/pub/pub-ident-fn-2.stderr @@ -1,9 +1,9 @@ -error: missing `fn` for method definition +error: missing `fn` for function definition --> $DIR/pub-ident-fn-2.rs:11:4 | LL | pub foo(s: usize) { bar() } | ^ -help: add `fn` here to parse `foo` as a public method +help: add `fn` here to parse `foo` as a public function | LL | pub fn foo(s: usize) { bar() } | ^^ diff --git a/src/test/ui/pub/pub-ident-fn-or-struct-2.rs b/src/test/ui/pub/pub-ident-fn-or-struct-2.rs index 1ccadc8a40b..e528e86fbc6 100644 --- a/src/test/ui/pub/pub-ident-fn-or-struct-2.rs +++ b/src/test/ui/pub/pub-ident-fn-or-struct-2.rs @@ -9,6 +9,6 @@ // except according to those terms. pub S(); -//~^ ERROR missing `fn` or `struct` for method or struct definition +//~^ ERROR missing `fn` or `struct` for function or struct definition fn main() {} diff --git a/src/test/ui/pub/pub-ident-fn-or-struct-2.stderr b/src/test/ui/pub/pub-ident-fn-or-struct-2.stderr index e492a8c4756..d423b838f05 100644 --- a/src/test/ui/pub/pub-ident-fn-or-struct-2.stderr +++ b/src/test/ui/pub/pub-ident-fn-or-struct-2.stderr @@ -1,4 +1,4 @@ -error: missing `fn` or `struct` for method or struct definition +error: missing `fn` or `struct` for function or struct definition --> $DIR/pub-ident-fn-or-struct-2.rs:11:4 | LL | pub S(); diff --git a/src/test/ui/pub/pub-ident-fn-or-struct.rs b/src/test/ui/pub/pub-ident-fn-or-struct.rs index 0664918945b..d5254bf2066 100644 --- a/src/test/ui/pub/pub-ident-fn-or-struct.rs +++ b/src/test/ui/pub/pub-ident-fn-or-struct.rs @@ -9,6 +9,6 @@ // except according to those terms. pub S (foo) bar -//~^ ERROR missing `fn` or `struct` for method or struct definition +//~^ ERROR missing `fn` or `struct` for function or struct definition fn main() {} diff --git a/src/test/ui/pub/pub-ident-fn-or-struct.stderr b/src/test/ui/pub/pub-ident-fn-or-struct.stderr index c1bff34cec3..b8b5e8a4bbf 100644 --- a/src/test/ui/pub/pub-ident-fn-or-struct.stderr +++ b/src/test/ui/pub/pub-ident-fn-or-struct.stderr @@ -1,4 +1,4 @@ -error: missing `fn` or `struct` for method or struct definition +error: missing `fn` or `struct` for function or struct definition --> $DIR/pub-ident-fn-or-struct.rs:11:4 | LL | pub S (foo) bar diff --git a/src/test/ui/pub/pub-ident-fn-with-lifetime-2.rs b/src/test/ui/pub/pub-ident-fn-with-lifetime-2.rs new file mode 100644 index 00000000000..1ee8c84f13b --- /dev/null +++ b/src/test/ui/pub/pub-ident-fn-with-lifetime-2.rs @@ -0,0 +1,6 @@ +pub bar<'a>(&self, _s: &'a usize) -> bool { true } +//~^ ERROR missing `fn` for method definition + +fn main() { + bar(2); +} diff --git a/src/test/ui/pub/pub-ident-fn-with-lifetime-2.stderr b/src/test/ui/pub/pub-ident-fn-with-lifetime-2.stderr new file mode 100644 index 00000000000..c403774df8e --- /dev/null +++ b/src/test/ui/pub/pub-ident-fn-with-lifetime-2.stderr @@ -0,0 +1,12 @@ +error: missing `fn` for method definition + --> $DIR/pub-ident-fn-with-lifetime-2.rs:1:4 + | +LL | pub bar<'a>(&self, _s: &'a usize) -> bool { true } + | ^^^ +help: add `fn` here to parse `bar` as a public method + | +LL | pub fn bar<'a>(&self, _s: &'a usize) -> bool { true } + | ^^ + +error: aborting due to previous error + diff --git a/src/test/ui/pub/pub-ident-fn-with-lifetime.rs b/src/test/ui/pub/pub-ident-fn-with-lifetime.rs new file mode 100644 index 00000000000..84f7bdc1fb1 --- /dev/null +++ b/src/test/ui/pub/pub-ident-fn-with-lifetime.rs @@ -0,0 +1,6 @@ +pub foo<'a>(_s: &'a usize) -> bool { true } +//~^ ERROR missing `fn` for function definition + +fn main() { + foo(2); +} diff --git a/src/test/ui/pub/pub-ident-fn-with-lifetime.stderr b/src/test/ui/pub/pub-ident-fn-with-lifetime.stderr new file mode 100644 index 00000000000..85823809640 --- /dev/null +++ b/src/test/ui/pub/pub-ident-fn-with-lifetime.stderr @@ -0,0 +1,12 @@ +error: missing `fn` for function definition + --> $DIR/pub-ident-fn-with-lifetime.rs:1:4 + | +LL | pub foo<'a>(_s: &'a usize) -> bool { true } + | ^^^ +help: add `fn` here to parse `foo` as a public function + | +LL | pub fn foo<'a>(_s: &'a usize) -> bool { true } + | ^^ + +error: aborting due to previous error + diff --git a/src/test/ui/pub/pub-ident-fn.fixed b/src/test/ui/pub/pub-ident-fn.fixed index f2d0c6c3e1d..667e02114a1 100644 --- a/src/test/ui/pub/pub-ident-fn.fixed +++ b/src/test/ui/pub/pub-ident-fn.fixed @@ -11,7 +11,7 @@ // run-rustfix pub fn foo(_s: usize) -> bool { true } -//~^ ERROR missing `fn` for method definition +//~^ ERROR missing `fn` for function definition fn main() { foo(2); diff --git a/src/test/ui/pub/pub-ident-fn.rs b/src/test/ui/pub/pub-ident-fn.rs index 82c32f57eea..91bbf58fe77 100644 --- a/src/test/ui/pub/pub-ident-fn.rs +++ b/src/test/ui/pub/pub-ident-fn.rs @@ -11,7 +11,7 @@ // run-rustfix pub foo(_s: usize) -> bool { true } -//~^ ERROR missing `fn` for method definition +//~^ ERROR missing `fn` for function definition fn main() { foo(2); diff --git a/src/test/ui/pub/pub-ident-fn.stderr b/src/test/ui/pub/pub-ident-fn.stderr index f7c96b8b9f4..1df6dd85ffe 100644 --- a/src/test/ui/pub/pub-ident-fn.stderr +++ b/src/test/ui/pub/pub-ident-fn.stderr @@ -1,9 +1,9 @@ -error: missing `fn` for method definition +error: missing `fn` for function definition --> $DIR/pub-ident-fn.rs:13:4 | LL | pub foo(_s: usize) -> bool { true } | ^^^ -help: add `fn` here to parse `foo` as a public method +help: add `fn` here to parse `foo` as a public function | LL | pub fn foo(_s: usize) -> bool { true } | ^^ diff --git a/src/test/ui/pub/pub-ident-struct-with-lifetime.rs b/src/test/ui/pub/pub-ident-struct-with-lifetime.rs new file mode 100644 index 00000000000..2feb0266070 --- /dev/null +++ b/src/test/ui/pub/pub-ident-struct-with-lifetime.rs @@ -0,0 +1,4 @@ +pub S<'a> { +//~^ ERROR missing `struct` for struct definition +} +fn main() {} diff --git a/src/test/ui/pub/pub-ident-struct-with-lifetime.stderr b/src/test/ui/pub/pub-ident-struct-with-lifetime.stderr new file mode 100644 index 00000000000..2bbcf5dfff0 --- /dev/null +++ b/src/test/ui/pub/pub-ident-struct-with-lifetime.stderr @@ -0,0 +1,12 @@ +error: missing `struct` for struct definition + --> $DIR/pub-ident-struct-with-lifetime.rs:1:4 + | +LL | pub S<'a> { + | ^ +help: add `struct` here to parse `S` as a public struct + | +LL | pub struct S<'a> { + | ^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/pub/pub-ident-with-lifetime-incomplete.rs b/src/test/ui/pub/pub-ident-with-lifetime-incomplete.rs new file mode 100644 index 00000000000..c86a9f2fdd6 --- /dev/null +++ b/src/test/ui/pub/pub-ident-with-lifetime-incomplete.rs @@ -0,0 +1,5 @@ +fn main() { +} + +pub foo<'a> +//~^ ERROR missing `fn` or `struct` for function or struct definition diff --git a/src/test/ui/pub/pub-ident-with-lifetime-incomplete.stderr b/src/test/ui/pub/pub-ident-with-lifetime-incomplete.stderr new file mode 100644 index 00000000000..0e0b127054d --- /dev/null +++ b/src/test/ui/pub/pub-ident-with-lifetime-incomplete.stderr @@ -0,0 +1,8 @@ +error: missing `fn` or `struct` for function or struct definition + --> $DIR/pub-ident-with-lifetime-incomplete.rs:4:4 + | +LL | pub foo<'a> + | ^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/refutable-pattern-errors.rs b/src/test/ui/refutable-pattern-errors.rs index 7b4009481ab..a140e421a57 100644 --- a/src/test/ui/refutable-pattern-errors.rs +++ b/src/test/ui/refutable-pattern-errors.rs @@ -14,5 +14,5 @@ fn func((1, (Some(1), 2..=3)): (isize, (Option, isize))) { } fn main() { let (1, (Some(1), 2..=3)) = (1, (None, 2)); - //~^ ERROR refutable pattern in local binding: `(_, _)` not covered + //~^ ERROR refutable pattern in local binding: `(-2147483648i32..=0i32, _)` not covered } diff --git a/src/test/ui/refutable-pattern-errors.stderr b/src/test/ui/refutable-pattern-errors.stderr index c2d5fe001fc..42aa5727895 100644 --- a/src/test/ui/refutable-pattern-errors.stderr +++ b/src/test/ui/refutable-pattern-errors.stderr @@ -4,11 +4,11 @@ error[E0005]: refutable pattern in function argument: `(_, _)` not covered LL | fn func((1, (Some(1), 2..=3)): (isize, (Option, isize))) { } | ^^^^^^^^^^^^^^^^^^^^^ pattern `(_, _)` not covered -error[E0005]: refutable pattern in local binding: `(_, _)` not covered +error[E0005]: refutable pattern in local binding: `(-2147483648i32..=0i32, _)` not covered --> $DIR/refutable-pattern-errors.rs:16:9 | LL | let (1, (Some(1), 2..=3)) = (1, (None, 2)); - | ^^^^^^^^^^^^^^^^^^^^^ pattern `(_, _)` not covered + | ^^^^^^^^^^^^^^^^^^^^^ pattern `(-2147483648i32..=0i32, _)` not covered error: aborting due to 2 previous errors diff --git a/src/test/ui/regions/issue-56537-closure-uses-region-from-container.rs b/src/test/ui/regions/issue-56537-closure-uses-region-from-container.rs new file mode 100644 index 00000000000..24676fe5e5b --- /dev/null +++ b/src/test/ui/regions/issue-56537-closure-uses-region-from-container.rs @@ -0,0 +1,74 @@ +// This is a collection of examples where a function's formal +// parameter has an explicit lifetime and a closure within that +// function returns that formal parameter. The closure's return type, +// to be correctly inferred, needs to include the lifetime introduced +// by the function. +// +// This works today, which precludes changing things so that closures +// follow the same lifetime-elision rules used elsehwere. See +// rust-lang/rust#56537 + +// compile-pass +// We are already testing NLL explicitly via the revision system below. +// ignore-compare-mode-nll + +// revisions: ll nll migrate +//[ll] compile-flags:-Zborrowck=ast +//[nll] compile-flags:-Zborrowck=mir -Z two-phase-borrows +//[migrate] compile-flags:-Zborrowck=migrate -Z two-phase-borrows + +fn willy_no_annot<'w>(p: &'w str, q: &str) -> &'w str { + let free_dumb = |_x| { p }; // no type annotation at all + let hello = format!("Hello"); + free_dumb(&hello) +} + +fn willy_ret_type_annot<'w>(p: &'w str, q: &str) -> &'w str { + let free_dumb = |_x| -> &str { p }; // type annotation on the return type + let hello = format!("Hello"); + free_dumb(&hello) +} + +fn willy_ret_region_annot<'w>(p: &'w str, q: &str) -> &'w str { + let free_dumb = |_x| -> &'w str { p }; // type+region annotation on return type + let hello = format!("Hello"); + free_dumb(&hello) +} + +fn willy_arg_type_ret_type_annot<'w>(p: &'w str, q: &str) -> &'w str { + let free_dumb = |_x: &str| -> &str { p }; // type annotation on arg and return types + let hello = format!("Hello"); + free_dumb(&hello) +} + +fn willy_arg_type_ret_region_annot<'w>(p: &'w str, q: &str) -> &'w str { + let free_dumb = |_x: &str| -> &'w str { p }; // fully annotated + let hello = format!("Hello"); + free_dumb(&hello) +} + +fn main() { + let world = format!("World"); + let w1: &str = { + let hello = format!("He11o"); + willy_no_annot(&world, &hello) + }; + let w2: &str = { + let hello = format!("He22o"); + willy_ret_type_annot(&world, &hello) + }; + let w3: &str = { + let hello = format!("He33o"); + willy_ret_region_annot(&world, &hello) + }; + let w4: &str = { + let hello = format!("He44o"); + willy_arg_type_ret_type_annot(&world, &hello) + }; + let w5: &str = { + let hello = format!("He55o"); + willy_arg_type_ret_region_annot(&world, &hello) + }; + assert_eq!((w1, w2, w3, w4, w5), + ("World","World","World","World","World")); +} diff --git a/src/test/ui/regions/regions-free-region-ordering-incorrect.rs b/src/test/ui/regions/regions-free-region-ordering-incorrect.rs index 9cb61c24922..250800262db 100644 --- a/src/test/ui/regions/regions-free-region-ordering-incorrect.rs +++ b/src/test/ui/regions/regions-free-region-ordering-incorrect.rs @@ -10,23 +10,23 @@ // Test that free regions ordering only goes one way. That is, // we have `&'a Node<'b, T>`, which implies that `'a <= 'b`, -// but not `'b <= 'a`. Hence returning `&self.val` (which has lifetime +// but not `'b <= 'a`. Hence, returning `&self.val` (which has lifetime // `'a`) where `'b` is expected yields an error. // // This test began its life as a test for issue #4325. -struct Node<'b, T:'b> { - val: T, - next: Option<&'b Node<'b, T>> +struct Node<'b, T: 'b> { + val: T, + next: Option<&'b Node<'b, T>> } impl<'b, T> Node<'b, T> { - fn get<'a>(&'a self) -> &'b T { - match self.next { - Some(ref next) => next.get(), - None => &self.val //~ ERROR cannot infer + fn get<'a>(&'a self) -> &'b T { + match self.next { + Some(ref next) => next.get(), + None => &self.val //~ ERROR cannot infer + } } - } } fn main() {} diff --git a/src/test/ui/regions/regions-free-region-ordering-incorrect.stderr b/src/test/ui/regions/regions-free-region-ordering-incorrect.stderr index 3dce04e2452..6b28ab4004f 100644 --- a/src/test/ui/regions/regions-free-region-ordering-incorrect.stderr +++ b/src/test/ui/regions/regions-free-region-ordering-incorrect.stderr @@ -1,32 +1,32 @@ error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements - --> $DIR/regions-free-region-ordering-incorrect.rs:27:15 + --> $DIR/regions-free-region-ordering-incorrect.rs:27:21 | -LL | None => &self.val //~ ERROR cannot infer - | ^^^^^^^^^ +LL | None => &self.val //~ ERROR cannot infer + | ^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime 'a as defined on the method body at 24:10... - --> $DIR/regions-free-region-ordering-incorrect.rs:24:10 +note: first, the lifetime cannot outlive the lifetime 'a as defined on the method body at 24:12... + --> $DIR/regions-free-region-ordering-incorrect.rs:24:12 | -LL | fn get<'a>(&'a self) -> &'b T { - | ^^ +LL | fn get<'a>(&'a self) -> &'b T { + | ^^ note: ...so that reference does not outlive borrowed content - --> $DIR/regions-free-region-ordering-incorrect.rs:27:15 + --> $DIR/regions-free-region-ordering-incorrect.rs:27:21 | -LL | None => &self.val //~ ERROR cannot infer - | ^^^^^^^^^ +LL | None => &self.val //~ ERROR cannot infer + | ^^^^^^^^^ note: but, the lifetime must be valid for the lifetime 'b as defined on the impl at 23:6... --> $DIR/regions-free-region-ordering-incorrect.rs:23:6 | LL | impl<'b, T> Node<'b, T> { | ^^ note: ...so that reference does not outlive borrowed content - --> $DIR/regions-free-region-ordering-incorrect.rs:25:5 + --> $DIR/regions-free-region-ordering-incorrect.rs:25:9 | -LL | / match self.next { -LL | | Some(ref next) => next.get(), -LL | | None => &self.val //~ ERROR cannot infer -LL | | } - | |_____^ +LL | / match self.next { +LL | | Some(ref next) => next.get(), +LL | | None => &self.val //~ ERROR cannot infer +LL | | } + | |_________^ error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-5035.rs b/src/test/ui/resolve/issue-5035.rs index e9b50dddd30..3ed41c6999f 100644 --- a/src/test/ui/resolve/issue-5035.rs +++ b/src/test/ui/resolve/issue-5035.rs @@ -14,6 +14,6 @@ impl K for isize {} //~ ERROR expected trait, found type alias `K` use ImportError; //~ ERROR unresolved import `ImportError` [E0432] //~^ no `ImportError` in the root -impl ImportError for () {} // check that this is not an additional error (c.f. #35142) +impl ImportError for () {} // check that this is not an additional error (cf. issue #35142) fn main() {} diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/meta.rs b/src/test/ui/rfc-2126-extern-absolute-paths/meta.rs index 499a322593c..004c4a00231 100644 --- a/src/test/ui/rfc-2126-extern-absolute-paths/meta.rs +++ b/src/test/ui/rfc-2126-extern-absolute-paths/meta.rs @@ -11,7 +11,7 @@ // 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`). +// 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-2166-underscore-imports/auxiliary/duplicate.rs b/src/test/ui/rfc-2166-underscore-imports/auxiliary/duplicate.rs new file mode 100644 index 00000000000..92d741b6a26 --- /dev/null +++ b/src/test/ui/rfc-2166-underscore-imports/auxiliary/duplicate.rs @@ -0,0 +1,14 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::*; + +#[proc_macro_attribute] +pub fn duplicate(_: TokenStream, input: TokenStream) -> TokenStream { + let clone = input.clone(); + input.into_iter().chain(clone.into_iter()).collect() +} diff --git a/src/test/ui/rfc-2166-underscore-imports/auxiliary/underscore-imports.rs b/src/test/ui/rfc-2166-underscore-imports/auxiliary/underscore-imports.rs new file mode 100644 index 00000000000..c335336bee8 --- /dev/null +++ b/src/test/ui/rfc-2166-underscore-imports/auxiliary/underscore-imports.rs @@ -0,0 +1,20 @@ +#[macro_export] +macro_rules! do_nothing { + () => () +} + +mod m1 { + pub trait InScope1 { + fn in_scope1(&self) {} + } + impl InScope1 for () {} +} +mod m2 { + pub trait InScope2 { + fn in_scope2(&self) {} + } + impl InScope2 for () {} +} + +pub use m1::InScope1 as _; +pub use m2::InScope2 as _; diff --git a/src/test/ui/rfc-2166-underscore-imports/basic.rs b/src/test/ui/rfc-2166-underscore-imports/basic.rs index 104bd9e166c..93b246fb92d 100644 --- a/src/test/ui/rfc-2166-underscore-imports/basic.rs +++ b/src/test/ui/rfc-2166-underscore-imports/basic.rs @@ -9,10 +9,15 @@ // except according to those terms. // compile-pass +// aux-build:underscore-imports.rs -#![feature(underscore_imports)] #![warn(unused_imports, unused_extern_crates)] +#[macro_use] +extern crate underscore_imports as _; + +do_nothing!(); // OK + struct S; mod m { diff --git a/src/test/ui/rfc-2166-underscore-imports/basic.stderr b/src/test/ui/rfc-2166-underscore-imports/basic.stderr index 2be0317019d..f2b8cc411ff 100644 --- a/src/test/ui/rfc-2166-underscore-imports/basic.stderr +++ b/src/test/ui/rfc-2166-underscore-imports/basic.stderr @@ -1,5 +1,5 @@ warning: unused import: `m::Tr1 as _` - --> $DIR/basic.rs:31:9 + --> $DIR/basic.rs:36:9 | LL | use m::Tr1 as _; //~ WARN unused import | ^^^^^^^^^^^ @@ -11,7 +11,7 @@ LL | #![warn(unused_imports, unused_extern_crates)] | ^^^^^^^^^^^^^^ warning: unused import: `S as _` - --> $DIR/basic.rs:32:9 + --> $DIR/basic.rs:37:9 | LL | use S as _; //~ WARN unused import | ^^^^^^ diff --git a/src/test/ui/rfc-2166-underscore-imports/duplicate.rs b/src/test/ui/rfc-2166-underscore-imports/duplicate.rs new file mode 100644 index 00000000000..95f7cae0b87 --- /dev/null +++ b/src/test/ui/rfc-2166-underscore-imports/duplicate.rs @@ -0,0 +1,15 @@ +// compile-pass +// aux-build:duplicate.rs + +extern crate duplicate; + +#[duplicate::duplicate] +use main as _; // OK + +macro_rules! duplicate { + ($item: item) => { $item $item } +} + +duplicate!(use std as _;); // OK + +fn main() {} diff --git a/src/test/ui/rfc-2166-underscore-imports/intercrate.rs b/src/test/ui/rfc-2166-underscore-imports/intercrate.rs new file mode 100644 index 00000000000..8b5bb8b3260 --- /dev/null +++ b/src/test/ui/rfc-2166-underscore-imports/intercrate.rs @@ -0,0 +1,11 @@ +// compile-pass +// aux-build:underscore-imports.rs + +extern crate underscore_imports; + +use underscore_imports::*; + +fn main() { + ().in_scope1(); + ().in_scope2(); +} diff --git a/src/test/ui/rfc-2166-underscore-imports/unused-2018.rs b/src/test/ui/rfc-2166-underscore-imports/unused-2018.rs new file mode 100644 index 00000000000..d06a26a5f11 --- /dev/null +++ b/src/test/ui/rfc-2166-underscore-imports/unused-2018.rs @@ -0,0 +1,17 @@ +// edition:2018 + +#![deny(unused_imports)] + +mod multi_segment { + use core::any; //~ ERROR unused import: `core::any` +} + +mod single_segment { + use core; //~ ERROR unused import: `core` +} + +mod single_segment_underscore { + use core as _; // OK +} + +fn main() {} diff --git a/src/test/ui/rfc-2166-underscore-imports/unused-2018.stderr b/src/test/ui/rfc-2166-underscore-imports/unused-2018.stderr new file mode 100644 index 00000000000..4163c287607 --- /dev/null +++ b/src/test/ui/rfc-2166-underscore-imports/unused-2018.stderr @@ -0,0 +1,20 @@ +error: unused import: `core::any` + --> $DIR/unused-2018.rs:6:9 + | +LL | use core::any; //~ ERROR unused import: `core::any` + | ^^^^^^^^^ + | +note: lint level defined here + --> $DIR/unused-2018.rs:3:9 + | +LL | #![deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: unused import: `core` + --> $DIR/unused-2018.rs:10:9 + | +LL | use core; //~ ERROR unused import: `core` + | ^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/run-pass/traits/trait-alias.rs b/src/test/ui/run-pass/traits/trait-alias.rs new file mode 100644 index 00000000000..9be5664869e --- /dev/null +++ b/src/test/ui/run-pass/traits/trait-alias.rs @@ -0,0 +1,7 @@ +// run-pass +#![feature(trait_alias)] + +pub trait Foo {} +pub trait FooAlias = Foo; + +fn main() {} diff --git a/src/test/ui/rust-2018/dyn-trait-compatibility.rs b/src/test/ui/rust-2018/dyn-trait-compatibility.rs index 9548df5959b..377c85fef49 100644 --- a/src/test/ui/rust-2018/dyn-trait-compatibility.rs +++ b/src/test/ui/rust-2018/dyn-trait-compatibility.rs @@ -1,7 +1,7 @@ // edition:2018 type A0 = dyn; -type A1 = dyn::dyn; //~ERROR expected identifier, found reserved keyword +type A1 = dyn::dyn; //~ERROR expected identifier, found keyword `dyn` type A2 = dyn; //~ERROR expected identifier, found `<` type A3 = dyn<::dyn>; diff --git a/src/test/ui/rust-2018/dyn-trait-compatibility.stderr b/src/test/ui/rust-2018/dyn-trait-compatibility.stderr index ea0483394b5..bd72f9c6786 100644 --- a/src/test/ui/rust-2018/dyn-trait-compatibility.stderr +++ b/src/test/ui/rust-2018/dyn-trait-compatibility.stderr @@ -1,8 +1,8 @@ -error: expected identifier, found reserved keyword `dyn` +error: expected identifier, found keyword `dyn` --> $DIR/dyn-trait-compatibility.rs:4:16 | -LL | type A1 = dyn::dyn; //~ERROR expected identifier, found reserved keyword - | ^^^ expected identifier, found reserved keyword +LL | type A1 = dyn::dyn; //~ERROR expected identifier, found keyword `dyn` + | ^^^ expected identifier, found keyword error: expected identifier, found `<` --> $DIR/dyn-trait-compatibility.rs:5:14 diff --git a/src/test/ui/rust-2018/future-proofing-locals.rs b/src/test/ui/rust-2018/future-proofing-locals.rs index d2e6dbbb954..4f0cadaae5d 100644 --- a/src/test/ui/rust-2018/future-proofing-locals.rs +++ b/src/test/ui/rust-2018/future-proofing-locals.rs @@ -1,6 +1,6 @@ // edition:2018 -#![feature(uniform_paths, underscore_imports)] +#![feature(uniform_paths)] mod T { pub struct U; diff --git a/src/test/ui/rust-2018/uniform-paths/macro-rules.rs b/src/test/ui/rust-2018/uniform-paths/macro-rules.rs index e8098a46790..fc433c201b0 100644 --- a/src/test/ui/rust-2018/uniform-paths/macro-rules.rs +++ b/src/test/ui/rust-2018/uniform-paths/macro-rules.rs @@ -2,7 +2,7 @@ // For the time being `macro_rules` items are treated as *very* private... -#![feature(underscore_imports, decl_macro, uniform_paths)] +#![feature(decl_macro, uniform_paths)] mod m1 { macro_rules! legacy_macro { () => () } diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs index d74d6815d5f..31ec8a7dc1c 100644 --- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs +++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs @@ -33,6 +33,7 @@ struct b8x8(pub i8, pub i8, pub i8, pub i8, extern "platform-intrinsic" { fn simd_select(x: T, a: U, b: U) -> U; + fn simd_select_bitmask(x: T, a: U, b: U) -> U; } fn main() { @@ -52,5 +53,20 @@ fn main() { simd_select(z, z, z); //~^ ERROR mask element type is `f32`, expected `i_` + + simd_select(m4, 0u32, 1u32); + //~^ ERROR found non-SIMD `u32` + + simd_select_bitmask(0u8, x, x); + //~^ ERROR mask length `8` != other vector length `4` + // + simd_select_bitmask(0u8, 1u32, 2u32); + //~^ ERROR found non-SIMD `u32` + + simd_select_bitmask(0.0f32, x, x); + //~^ ERROR `f32` is not an integral type + + simd_select_bitmask("x", x, x); + //~^ ERROR `&str` is not an integral type } } diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr index 61e42027039..05317da2475 100644 --- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr +++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr @@ -1,21 +1,51 @@ error[E0511]: invalid monomorphization of `simd_select` intrinsic: mismatched lengths: mask length `8` != other vector length `4` - --> $DIR/simd-intrinsic-generic-select.rs:47:9 + --> $DIR/simd-intrinsic-generic-select.rs:48:9 | LL | simd_select(m8, x, x); | ^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_select` intrinsic: mask element type is `u32`, expected `i_` - --> $DIR/simd-intrinsic-generic-select.rs:50:9 + --> $DIR/simd-intrinsic-generic-select.rs:51:9 | LL | simd_select(x, x, x); | ^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_select` intrinsic: mask element type is `f32`, expected `i_` - --> $DIR/simd-intrinsic-generic-select.rs:53:9 + --> $DIR/simd-intrinsic-generic-select.rs:54:9 | LL | simd_select(z, z, z); | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error[E0511]: invalid monomorphization of `simd_select` intrinsic: expected SIMD argument type, found non-SIMD `u32` + --> $DIR/simd-intrinsic-generic-select.rs:57:9 + | +LL | simd_select(m4, 0u32, 1u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: mismatched lengths: mask length `8` != other vector length `4` + --> $DIR/simd-intrinsic-generic-select.rs:60:9 + | +LL | simd_select_bitmask(0u8, x, x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: expected SIMD argument type, found non-SIMD `u32` + --> $DIR/simd-intrinsic-generic-select.rs:63:9 + | +LL | simd_select_bitmask(0u8, 1u32, 2u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: `f32` is not an integral type + --> $DIR/simd-intrinsic-generic-select.rs:66:9 + | +LL | simd_select_bitmask(0.0f32, x, x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: `&str` is not an integral type + --> $DIR/simd-intrinsic-generic-select.rs:69:9 + | +LL | simd_select_bitmask("x", x, x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0511`. diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-single-nominal-type.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-single-nominal-type.rs index 0d0bf240f72..5e009ea4431 100644 --- a/src/test/ui/simd-intrinsic/simd-intrinsic-single-nominal-type.rs +++ b/src/test/ui/simd-intrinsic/simd-intrinsic-single-nominal-type.rs @@ -16,7 +16,7 @@ struct A(i16, i16, i16, i16, i16, i16, i16, i16); struct B(i16, i16, i16, i16, i16, i16, i16, i16); // each intrinsic definition has to use the same nominal type for any -// vector structure throughout that declaration (i.e. every instance +// vector structure throughout that declaration (i.e., every instance // of i16x8 in each `fn ...;` needs to be either A or B) extern "platform-intrinsic" { diff --git a/src/test/ui/span/issue-24805-dropck-trait-has-items.rs b/src/test/ui/span/issue-24805-dropck-trait-has-items.rs index 75523386931..b9e4ffa84cd 100644 --- a/src/test/ui/span/issue-24805-dropck-trait-has-items.rs +++ b/src/test/ui/span/issue-24805-dropck-trait-has-items.rs @@ -25,7 +25,7 @@ impl<'a,T> HasSelfMethod for &'a T { } impl<'a,T> HasMethodWithSelfArg for &'a T { } impl<'a,T> HasType for &'a T { type Something = (); } -// e.g. `impl_drop!(Send, D_Send)` expands to: +// e.g., `impl_drop!(Send, D_Send)` expands to: // ```rust // struct D_Send(T); // impl Drop for D_Send { fn drop(&mut self) { } } diff --git a/src/test/ui/span/issue-27522.rs b/src/test/ui/span/issue-27522.rs index 1e3eba4bf36..11c90833e71 100644 --- a/src/test/ui/span/issue-27522.rs +++ b/src/test/ui/span/issue-27522.rs @@ -13,7 +13,7 @@ struct SomeType {} trait Foo { - fn handler(self: &SomeType); //~ ERROR invalid `self` type + fn handler(self: &SomeType); //~ ERROR invalid method receiver type } fn main() {} diff --git a/src/test/ui/span/issue-27522.stderr b/src/test/ui/span/issue-27522.stderr index 9b61ecae651..767b99a92cb 100644 --- a/src/test/ui/span/issue-27522.stderr +++ b/src/test/ui/span/issue-27522.stderr @@ -1,7 +1,7 @@ -error[E0307]: invalid `self` type: &SomeType +error[E0307]: invalid method receiver type: &SomeType --> $DIR/issue-27522.rs:16:22 | -LL | fn handler(self: &SomeType); //~ ERROR invalid `self` type +LL | fn handler(self: &SomeType); //~ ERROR invalid method receiver type | ^^^^^^^^^ | = note: type must be `Self` or a type that dereferences to it diff --git a/src/test/ui/suggestions/path-display.rs b/src/test/ui/suggestions/path-display.rs new file mode 100644 index 00000000000..62fc9e79f7a --- /dev/null +++ b/src/test/ui/suggestions/path-display.rs @@ -0,0 +1,7 @@ +use std::path::Path; + +fn main() { + let path = Path::new("/tmp/foo/bar.txt"); + println!("{}", path); + //~^ ERROR E0277 +} diff --git a/src/test/ui/suggestions/path-display.stderr b/src/test/ui/suggestions/path-display.stderr new file mode 100644 index 00000000000..39d236af4f3 --- /dev/null +++ b/src/test/ui/suggestions/path-display.stderr @@ -0,0 +1,14 @@ +error[E0277]: `std::path::Path` doesn't implement `std::fmt::Display` + --> $DIR/path-display.rs:5:20 + | +LL | println!("{}", path); + | ^^^^ `std::path::Path` cannot be formatted with the default formatter; call `.display()` on it + | + = help: the trait `std::fmt::Display` is not implemented for `std::path::Path` + = note: call `.display()` or `.to_string_lossy()` to safely print paths, as they may contain non-Unicode data + = note: required because of the requirements on the impl of `std::fmt::Display` for `&std::path::Path` + = note: required by `std::fmt::Display::fmt` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/suggest-impl-trait-lifetime.fixed b/src/test/ui/suggestions/suggest-impl-trait-lifetime.fixed new file mode 100644 index 00000000000..8592af1262e --- /dev/null +++ b/src/test/ui/suggestions/suggest-impl-trait-lifetime.fixed @@ -0,0 +1,18 @@ +// run-rustfix + +use std::fmt::Debug; + +fn foo(d: impl Debug + 'static) { +//~^ HELP consider adding an explicit lifetime bound `'static` to `impl Debug` + bar(d); +//~^ ERROR the parameter type `impl Debug` may not live long enough +//~| NOTE ...so that the type `impl Debug` will meet its required lifetime bounds +} + +fn bar(d: impl Debug + 'static) { + println!("{:?}", d) +} + +fn main() { + foo("hi"); +} diff --git a/src/test/ui/suggestions/suggest-impl-trait-lifetime.rs b/src/test/ui/suggestions/suggest-impl-trait-lifetime.rs new file mode 100644 index 00000000000..c67d78ea4c7 --- /dev/null +++ b/src/test/ui/suggestions/suggest-impl-trait-lifetime.rs @@ -0,0 +1,18 @@ +// run-rustfix + +use std::fmt::Debug; + +fn foo(d: impl Debug) { +//~^ HELP consider adding an explicit lifetime bound `'static` to `impl Debug` + bar(d); +//~^ ERROR the parameter type `impl Debug` may not live long enough +//~| NOTE ...so that the type `impl Debug` will meet its required lifetime bounds +} + +fn bar(d: impl Debug + 'static) { + println!("{:?}", d) +} + +fn main() { + foo("hi"); +} diff --git a/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr b/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr new file mode 100644 index 00000000000..cba231d0e86 --- /dev/null +++ b/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr @@ -0,0 +1,19 @@ +error[E0310]: the parameter type `impl Debug` may not live long enough + --> $DIR/suggest-impl-trait-lifetime.rs:7:5 + | +LL | bar(d); + | ^^^ + | +note: ...so that the type `impl Debug` will meet its required lifetime bounds + --> $DIR/suggest-impl-trait-lifetime.rs:7:5 + | +LL | bar(d); + | ^^^ +help: consider adding an explicit lifetime bound `'static` to `impl Debug`... + | +LL | fn foo(d: impl Debug + 'static) { + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0310`. diff --git a/src/test/ui/target-feature-gate.rs b/src/test/ui/target-feature-gate.rs index 8a045884cae..cb0938b861c 100644 --- a/src/test/ui/target-feature-gate.rs +++ b/src/test/ui/target-feature-gate.rs @@ -14,6 +14,11 @@ // ignore-emscripten // ignore-mips // ignore-mips64 +// ignore-powerpc +// ignore-powerpc64 +// ignore-powerpc64le +// ignore-sparc +// ignore-sparc64 // gate-test-sse4a_target_feature // gate-test-powerpc_target_feature // gate-test-avx512_target_feature @@ -24,6 +29,8 @@ // gate-test-mips_target_feature // gate-test-mmx_target_feature // gate-test-wasm_target_feature +// gate-test-adx_target_feature +// gate-test-cmpxchg16b_target_feature // min-llvm-version 6.0 #[target_feature(enable = "avx512bw")] diff --git a/src/test/ui/target-feature-gate.stderr b/src/test/ui/target-feature-gate.stderr index f18bebc0c29..d7154324d12 100644 --- a/src/test/ui/target-feature-gate.stderr +++ b/src/test/ui/target-feature-gate.stderr @@ -1,5 +1,5 @@ error[E0658]: the target feature `avx512bw` is currently unstable (see issue #44839) - --> $DIR/target-feature-gate.rs:29:18 + --> $DIR/target-feature-gate.rs:36:18 | LL | #[target_feature(enable = "avx512bw")] | ^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/thread-local-in-ctfe.nll.stderr b/src/test/ui/thread-local-in-ctfe.nll.stderr index 05f8f343380..83502bac446 100644 --- a/src/test/ui/thread-local-in-ctfe.nll.stderr +++ b/src/test/ui/thread-local-in-ctfe.nll.stderr @@ -18,9 +18,8 @@ LL | static C: &u32 = &A; | | | thread-local variables cannot be borrowed beyond the end of the function | - = warning: This error has been downgraded to a warning for backwards compatibility with previous releases. - It represents potential unsoundness in your code. - This warning will become a hard error in the future. + = warning: this error has been downgraded to a warning for backwards compatibility with previous releases + = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future error[E0625]: thread-local statics cannot be accessed at compile-time --> $DIR/thread-local-in-ctfe.rs:22:16 @@ -42,9 +41,8 @@ LL | const E: &u32 = &A; | | | thread-local variables cannot be borrowed beyond the end of the function | - = warning: This error has been downgraded to a warning for backwards compatibility with previous releases. - It represents potential unsoundness in your code. - This warning will become a hard error in the future. + = warning: this error has been downgraded to a warning for backwards compatibility with previous releases + = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future error[E0625]: thread-local statics cannot be accessed at compile-time --> $DIR/thread-local-in-ctfe.rs:29:5 diff --git a/src/test/ui/feature-gates/feature-gate-repr_packed.rs b/src/test/ui/trait-method-number-parameters.rs similarity index 69% rename from src/test/ui/feature-gates/feature-gate-repr_packed.rs rename to src/test/ui/trait-method-number-parameters.rs index 65e3be288fd..c2591e4bda6 100644 --- a/src/test/ui/feature-gates/feature-gate-repr_packed.rs +++ b/src/test/ui/trait-method-number-parameters.rs @@ -8,11 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[repr(packed(1))] //~ error: the `#[repr(packed(n))]` attribute is experimental -struct Foo(u64); +trait Foo { + fn foo(&mut self, x: i32, y: i32) -> i32; +} -#[repr(C)] -#[repr(packed(1))] //~ error: the `#[repr(packed(n))]` attribute is experimental -struct Bar(u64); +impl Foo for i32 { + fn foo( + &mut self, //~ ERROR + x: i32, + ) { + } +} fn main() {} diff --git a/src/test/ui/trait-method-number-parameters.stderr b/src/test/ui/trait-method-number-parameters.stderr new file mode 100644 index 00000000000..98a08d2474d --- /dev/null +++ b/src/test/ui/trait-method-number-parameters.stderr @@ -0,0 +1,13 @@ +error[E0050]: method `foo` has 2 parameters but the declaration in trait `Foo::foo` has 3 + --> $DIR/trait-method-number-parameters.rs:17:9 + | +LL | fn foo(&mut self, x: i32, y: i32) -> i32; + | ------------------------- trait requires 3 parameters +... +LL | / &mut self, //~ ERROR +LL | | x: i32, + | |______________^ expected 3 parameters, found 2 + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0050`. diff --git a/src/test/ui/traits/trait-impl-different-num-params.stderr b/src/test/ui/traits/trait-impl-different-num-params.stderr index c3bbf99b06a..18024449d81 100644 --- a/src/test/ui/traits/trait-impl-different-num-params.stderr +++ b/src/test/ui/traits/trait-impl-different-num-params.stderr @@ -2,7 +2,7 @@ error[E0050]: method `bar` has 1 parameter but the declaration in trait `foo::ba --> $DIR/trait-impl-different-num-params.rs:15:12 | LL | fn bar(&self, x: usize) -> Self; - | ----- trait requires 2 parameters + | --------------- trait requires 2 parameters ... LL | fn bar(&self) -> isize { | ^^^^^ expected 2 parameters, found 1 diff --git a/src/test/ui/traits/trait-object-with-self-in-projection-output-bad.rs b/src/test/ui/traits/trait-object-with-self-in-projection-output-bad.rs new file mode 100644 index 00000000000..766bd147431 --- /dev/null +++ b/src/test/ui/traits/trait-object-with-self-in-projection-output-bad.rs @@ -0,0 +1,50 @@ +// Regression test for #56288. Checks that if a supertrait defines an associated type +// projection that references `Self`, then that associated type must still be explicitly +// specified in the `dyn Trait` variant, since we don't know what `Self` is anymore. + +trait Base { + type Output; +} + +trait Helper: Base::Target> { + type Target; +} + +impl Base for u32 +{ + type Output = i32; +} + +impl Helper for u32 +{ + type Target = i32; +} + +trait ConstI32 { + type Out; +} + +impl ConstI32 for T { + type Out = i32; +} + +// Test that you still need to manually give a projection type if the Output type +// is normalizable. +trait NormalizableHelper: + Base::Out> +{ + type Target; +} + +impl NormalizableHelper for u32 +{ + type Target = i32; +} + +fn main() { + let _x: Box> = Box::new(2u32); + //~^ ERROR the value of the associated type `Output` (from the trait `Base`) must be specified + + let _y: Box> = Box::new(2u32); + //~^ ERROR the value of the associated type `Output` (from the trait `Base`) must be specified +} diff --git a/src/test/ui/traits/trait-object-with-self-in-projection-output-bad.stderr b/src/test/ui/traits/trait-object-with-self-in-projection-output-bad.stderr new file mode 100644 index 00000000000..350f8ea8507 --- /dev/null +++ b/src/test/ui/traits/trait-object-with-self-in-projection-output-bad.stderr @@ -0,0 +1,21 @@ +error[E0191]: the value of the associated type `Output` (from the trait `Base`) must be specified + --> $DIR/trait-object-with-self-in-projection-output-bad.rs:45:17 + | +LL | type Output; + | ------------ `Output` defined here +... +LL | let _x: Box> = Box::new(2u32); + | ^^^^^^^^^^^^^^^^^^^^^^ associated type `Output` must be specified + +error[E0191]: the value of the associated type `Output` (from the trait `Base`) must be specified + --> $DIR/trait-object-with-self-in-projection-output-bad.rs:48:17 + | +LL | type Output; + | ------------ `Output` defined here +... +LL | let _y: Box> = Box::new(2u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated type `Output` must be specified + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0191`. diff --git a/src/test/ui/traits/trait-object-with-self-in-projection-output-good.rs b/src/test/ui/traits/trait-object-with-self-in-projection-output-good.rs new file mode 100644 index 00000000000..793d556d08c --- /dev/null +++ b/src/test/ui/traits/trait-object-with-self-in-projection-output-good.rs @@ -0,0 +1,28 @@ +// compile-pass + +// Regression test related to #56288. Check that a supertrait projection (of +// `Output`) that references `Self` can be ok if it is referencing a projection (of +// `Self::Target`, in this case). Note that we still require the user to manually +// specify both `Target` and `Output` for now. + +trait Base { + type Output; +} + +trait Helper: Base::Target> { + type Target; +} + +impl Base for u32 +{ + type Output = i32; +} + +impl Helper for u32 +{ + type Target = i32; +} + +fn main() { + let _x: Box> = Box::new(2u32); +} diff --git a/src/test/ui/traits/trait-object-with-self-in-projection-output-repeated-supertrait.rs b/src/test/ui/traits/trait-object-with-self-in-projection-output-repeated-supertrait.rs new file mode 100644 index 00000000000..46c083f9305 --- /dev/null +++ b/src/test/ui/traits/trait-object-with-self-in-projection-output-repeated-supertrait.rs @@ -0,0 +1,48 @@ +// compile-pass + +// Regression test related to #56288. Check that a supertrait projection (of +// `Output`) that references `Self` is ok if there is another occurence of +// the same supertrait that specifies the projection explicitly, even if +// the projection's associated type is not explicitly specified in the object type. +// +// Note that in order for this to compile, we need the `Self`-referencing projection +// to normalize fairly directly to a concrete type, otherwise the trait resolver +// will hate us. +// +// There is a test in `trait-object-with-self-in-projection-output-bad.rs` that +// having a normalizing, but `Self`-containing projection does not *by itself* +// allow you to avoid writing the projected type (`Output`, in this example) +// explicitly. + +trait ConstI32 { + type Out; +} + +impl ConstI32 for T { + type Out = i32; +} + +trait Base { + type Output; +} + +trait NormalizingHelper: Base::Out> + Base { + type Target; +} + +impl Base for u32 +{ + type Output = i32; +} + +impl NormalizingHelper for u32 +{ + type Target = i32; +} + +fn main() { + // Make sure this works both with and without the associated type + // being specified. + let _x: Box> = Box::new(2u32); + let _y: Box> = Box::new(2u32); +} diff --git a/src/test/ui/type/type-alias-bounds.rs b/src/test/ui/type/type-alias-bounds.rs index a17bb9e952d..41f260aba55 100644 --- a/src/test/ui/type/type-alias-bounds.rs +++ b/src/test/ui/type/type-alias-bounds.rs @@ -48,7 +48,7 @@ fn foo<'a>(y: &'a i32) { x.1.push(y); // &'a i32: 'static does not hold } -// Bounds are not checked either, i.e. the definition is not necessarily well-formed +// Bounds are not checked either, i.e., the definition is not necessarily well-formed struct Sendable(T); type MySendable = Sendable; // no error here! diff --git a/src/test/ui/ufcs/ufcs-explicit-self-bad.rs b/src/test/ui/ufcs/ufcs-explicit-self-bad.rs index a0d1f2dc331..f87541b56ac 100644 --- a/src/test/ui/ufcs/ufcs-explicit-self-bad.rs +++ b/src/test/ui/ufcs/ufcs-explicit-self-bad.rs @@ -16,7 +16,7 @@ struct Foo { impl Foo { fn foo(self: isize, x: isize) -> isize { - //~^ ERROR invalid `self` type + //~^ ERROR invalid method receiver type self.f + x } } @@ -27,11 +27,11 @@ struct Bar { impl Bar { fn foo(self: Bar, x: isize) -> isize { - //~^ ERROR invalid `self` type + //~^ ERROR invalid method receiver type x } fn bar(self: &Bar, x: isize) -> isize { - //~^ ERROR invalid `self` type + //~^ ERROR invalid method receiver type x } } diff --git a/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr b/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr index fce74605cad..a229dabcce4 100644 --- a/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr +++ b/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr @@ -1,28 +1,28 @@ -error[E0307]: invalid `self` type: isize +error[E0307]: invalid method receiver type: isize --> $DIR/ufcs-explicit-self-bad.rs:18:18 | LL | fn foo(self: isize, x: isize) -> isize { | ^^^^^ | - = note: type must be `Foo` or a type that dereferences to it + = note: type must be `Self` or a type that dereferences to it = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box` -error[E0307]: invalid `self` type: Bar +error[E0307]: invalid method receiver type: Bar --> $DIR/ufcs-explicit-self-bad.rs:29:18 | LL | fn foo(self: Bar, x: isize) -> isize { | ^^^^^^^^^^ | - = note: type must be `Bar` or a type that dereferences to it + = note: type must be `Self` or a type that dereferences to it = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box` -error[E0307]: invalid `self` type: &Bar +error[E0307]: invalid method receiver type: &Bar --> $DIR/ufcs-explicit-self-bad.rs:33:18 | LL | fn bar(self: &Bar, x: isize) -> isize { | ^^^^^^^^^^^ | - = note: type must be `Bar` or a type that dereferences to it + = note: type must be `Self` or a type that dereferences to it = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box` error[E0308]: mismatched method receiver diff --git a/src/test/ui/uninhabited/privately-uninhabited-dead-code.rs b/src/test/ui/uninhabited/privately-uninhabited-dead-code.rs new file mode 100644 index 00000000000..9fe8a5c832c --- /dev/null +++ b/src/test/ui/uninhabited/privately-uninhabited-dead-code.rs @@ -0,0 +1,20 @@ +// compile-pass + +#![deny(unused_variables)] + +mod foo { + enum Bar {} + + #[allow(dead_code)] + pub struct Foo { + value: Bar, // "privately" uninhabited + } + + pub fn give_foo() -> Foo { panic!() } +} + +fn main() { + let a = 42; + foo::give_foo(); + println!("Hello, {}", a); // ok: we can't tell that this code is dead +} diff --git a/src/test/ui/unnecessary-extern-crate.rs b/src/test/ui/unnecessary-extern-crate.rs index 110cfefcd92..4eb3c3d6436 100644 --- a/src/test/ui/unnecessary-extern-crate.rs +++ b/src/test/ui/unnecessary-extern-crate.rs @@ -11,7 +11,7 @@ // edition:2018 #![deny(unused_extern_crates)] -#![feature(alloc, test, libc, crate_visibility_modifier)] +#![feature(alloc, test, rustc_private, crate_visibility_modifier)] extern crate libc; //~^ ERROR unused extern crate diff --git a/src/test/ui/unsafe/ranged_ints.rs b/src/test/ui/unsafe/ranged_ints.rs new file mode 100644 index 00000000000..0fa2da917e9 --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints.rs @@ -0,0 +1,8 @@ +#![feature(rustc_attrs)] + +#[rustc_layout_scalar_valid_range_start(1)] +#[repr(transparent)] +pub(crate) struct NonZero(pub(crate) T); +fn main() { + let _x = NonZero(0); //~ ERROR initializing type with `rustc_layout_scalar_valid_range` attr +} diff --git a/src/test/ui/unsafe/ranged_ints.stderr b/src/test/ui/unsafe/ranged_ints.stderr new file mode 100644 index 00000000000..f59a930b5a9 --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints.stderr @@ -0,0 +1,11 @@ +error[E0133]: initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe function or block + --> $DIR/ranged_ints.rs:7:14 + | +LL | let _x = NonZero(0); //~ ERROR initializing type with `rustc_layout_scalar_valid_range` attr + | ^^^^^^^^^^ initializing type with `rustc_layout_scalar_valid_range` attr + | + = note: initializing a layout restricted type's field with a value outside the valid range is undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/unsafe/ranged_ints2.rs b/src/test/ui/unsafe/ranged_ints2.rs new file mode 100644 index 00000000000..68ba120b279 --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints2.rs @@ -0,0 +1,9 @@ +#![feature(rustc_attrs)] + +#[rustc_layout_scalar_valid_range_start(1)] +#[repr(transparent)] +pub(crate) struct NonZero(pub(crate) T); +fn main() { + let mut x = unsafe { NonZero(1) }; + let y = &mut x.0; //~ ERROR mutation of layout constrained field is unsafe +} diff --git a/src/test/ui/unsafe/ranged_ints2.stderr b/src/test/ui/unsafe/ranged_ints2.stderr new file mode 100644 index 00000000000..ae63f47ed74 --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints2.stderr @@ -0,0 +1,11 @@ +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/ranged_ints2.rs:8:13 + | +LL | let y = &mut x.0; //~ ERROR mutation of layout constrained field is unsafe + | ^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/unsafe/ranged_ints2_const.rs b/src/test/ui/unsafe/ranged_ints2_const.rs new file mode 100644 index 00000000000..a61e3329bdc --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints2_const.rs @@ -0,0 +1,20 @@ +#![feature(rustc_attrs, const_let, const_fn)] + +#[rustc_layout_scalar_valid_range_start(1)] +#[repr(transparent)] +pub(crate) struct NonZero(pub(crate) T); +fn main() { +} + +const fn foo() -> NonZero { + let mut x = unsafe { NonZero(1) }; + let y = &mut x.0; //~ ERROR references in constant functions may only refer to immutable + //~^ ERROR mutation of layout constrained field is unsafe + unsafe { NonZero(1) } +} + +const fn bar() -> NonZero { + let mut x = unsafe { NonZero(1) }; + let y = unsafe { &mut x.0 }; //~ ERROR references in constant functions may only refer to immut + unsafe { NonZero(1) } +} diff --git a/src/test/ui/unsafe/ranged_ints2_const.stderr b/src/test/ui/unsafe/ranged_ints2_const.stderr new file mode 100644 index 00000000000..f79792ffba9 --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints2_const.stderr @@ -0,0 +1,24 @@ +error[E0017]: references in constant functions may only refer to immutable values + --> $DIR/ranged_ints2_const.rs:11:13 + | +LL | let y = &mut x.0; //~ ERROR references in constant functions may only refer to immutable + | ^^^^^^^^ constant functions require immutable values + +error[E0017]: references in constant functions may only refer to immutable values + --> $DIR/ranged_ints2_const.rs:18:22 + | +LL | let y = unsafe { &mut x.0 }; //~ ERROR references in constant functions may only refer to immut + | ^^^^^^^^ constant functions require immutable values + +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/ranged_ints2_const.rs:11:13 + | +LL | let y = &mut x.0; //~ ERROR references in constant functions may only refer to immutable + | ^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to 3 previous errors + +Some errors occurred: E0017, E0133. +For more information about an error, try `rustc --explain E0017`. diff --git a/src/test/ui/unsafe/ranged_ints3.rs b/src/test/ui/unsafe/ranged_ints3.rs new file mode 100644 index 00000000000..47d67fac678 --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints3.rs @@ -0,0 +1,11 @@ +#![feature(rustc_attrs)] + +use std::cell::Cell; + +#[rustc_layout_scalar_valid_range_start(1)] +#[repr(transparent)] +pub(crate) struct NonZero(pub(crate) T); +fn main() { + let mut x = unsafe { NonZero(Cell::new(1)) }; + let y = &x.0; //~ ERROR borrow of layout constrained field with interior mutability +} diff --git a/src/test/ui/unsafe/ranged_ints3.stderr b/src/test/ui/unsafe/ranged_ints3.stderr new file mode 100644 index 00000000000..311a058fdb0 --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints3.stderr @@ -0,0 +1,11 @@ +error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block + --> $DIR/ranged_ints3.rs:10:13 + | +LL | let y = &x.0; //~ ERROR borrow of layout constrained field with interior mutability + | ^^^^ borrow of layout constrained field with interior mutability + | + = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/unsafe/ranged_ints3_const.rs b/src/test/ui/unsafe/ranged_ints3_const.rs new file mode 100644 index 00000000000..6497b611224 --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints3_const.rs @@ -0,0 +1,21 @@ +#![feature(rustc_attrs, const_let, const_fn)] + +use std::cell::Cell; + +#[rustc_layout_scalar_valid_range_start(1)] +#[repr(transparent)] +pub(crate) struct NonZero(pub(crate) T); +fn main() {} + +const fn foo() -> NonZero> { + let mut x = unsafe { NonZero(Cell::new(1)) }; + let y = &x.0; //~ ERROR cannot borrow a constant which may contain interior mutability + //~^ ERROR borrow of layout constrained field with interior mutability + unsafe { NonZero(Cell::new(1)) } +} + +const fn bar() -> NonZero> { + let mut x = unsafe { NonZero(Cell::new(1)) }; + let y = unsafe { &x.0 }; //~ ERROR cannot borrow a constant which may contain interior mut + unsafe { NonZero(Cell::new(1)) } +} diff --git a/src/test/ui/unsafe/ranged_ints3_const.stderr b/src/test/ui/unsafe/ranged_ints3_const.stderr new file mode 100644 index 00000000000..d83d75787d9 --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints3_const.stderr @@ -0,0 +1,24 @@ +error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead + --> $DIR/ranged_ints3_const.rs:12:13 + | +LL | let y = &x.0; //~ ERROR cannot borrow a constant which may contain interior mutability + | ^^^^ + +error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead + --> $DIR/ranged_ints3_const.rs:19:22 + | +LL | let y = unsafe { &x.0 }; //~ ERROR cannot borrow a constant which may contain interior mut + | ^^^^ + +error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block + --> $DIR/ranged_ints3_const.rs:12:13 + | +LL | let y = &x.0; //~ ERROR cannot borrow a constant which may contain interior mutability + | ^^^^ borrow of layout constrained field with interior mutability + | + = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values + +error: aborting due to 3 previous errors + +Some errors occurred: E0133, E0492. +For more information about an error, try `rustc --explain E0133`. diff --git a/src/test/ui/unsafe/ranged_ints4.rs b/src/test/ui/unsafe/ranged_ints4.rs new file mode 100644 index 00000000000..d8632c48434 --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints4.rs @@ -0,0 +1,9 @@ +#![feature(rustc_attrs)] + +#[rustc_layout_scalar_valid_range_start(1)] +#[repr(transparent)] +pub(crate) struct NonZero(pub(crate) T); +fn main() { + let mut x = unsafe { NonZero(1) }; + x.0 = 0; //~ ERROR mutation of layout constrained field is unsafe +} diff --git a/src/test/ui/unsafe/ranged_ints4.stderr b/src/test/ui/unsafe/ranged_ints4.stderr new file mode 100644 index 00000000000..c6468b643b4 --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints4.stderr @@ -0,0 +1,11 @@ +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/ranged_ints4.rs:8:5 + | +LL | x.0 = 0; //~ ERROR mutation of layout constrained field is unsafe + | ^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/unsafe/ranged_ints4_const.rs b/src/test/ui/unsafe/ranged_ints4_const.rs new file mode 100644 index 00000000000..f589e4739ba --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints4_const.rs @@ -0,0 +1,19 @@ +#![feature(rustc_attrs, const_let, const_fn)] + +#[rustc_layout_scalar_valid_range_start(1)] +#[repr(transparent)] +pub(crate) struct NonZero(pub(crate) T); +fn main() {} + +const fn foo() -> NonZero { + let mut x = unsafe { NonZero(1) }; + x.0 = 0; + //~^ ERROR mutation of layout constrained field is unsafe + x +} + +const fn bar() -> NonZero { + let mut x = unsafe { NonZero(1) }; + unsafe { x.0 = 0 }; // this is UB + x +} diff --git a/src/test/ui/unsafe/ranged_ints4_const.stderr b/src/test/ui/unsafe/ranged_ints4_const.stderr new file mode 100644 index 00000000000..fe83b15ce5c --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints4_const.stderr @@ -0,0 +1,11 @@ +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/ranged_ints4_const.rs:10:5 + | +LL | x.0 = 0; + | ^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/unsafe/ranged_ints_const.rs b/src/test/ui/unsafe/ranged_ints_const.rs new file mode 100644 index 00000000000..8477772867e --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints_const.rs @@ -0,0 +1,11 @@ +#![feature(rustc_attrs)] + +#[rustc_layout_scalar_valid_range_start(1)] +#[repr(transparent)] +pub(crate) struct NonZero(pub(crate) T); +fn main() {} + +const fn foo() -> NonZero { NonZero(0) } +//~^ ERROR initializing type with `rustc_layout_scalar_valid_range` attr is unsafe + +const fn bar() -> NonZero { unsafe { NonZero(0) } } diff --git a/src/test/ui/unsafe/ranged_ints_const.stderr b/src/test/ui/unsafe/ranged_ints_const.stderr new file mode 100644 index 00000000000..584ad40a92b --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints_const.stderr @@ -0,0 +1,11 @@ +error[E0133]: initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe function or block + --> $DIR/ranged_ints_const.rs:8:34 + | +LL | const fn foo() -> NonZero { NonZero(0) } + | ^^^^^^^^^^ initializing type with `rustc_layout_scalar_valid_range` attr + | + = note: initializing a layout restricted type's field with a value outside the valid range is undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index bf95b31ae3c..aba0472ae36 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -14,7 +14,7 @@ extern crate serde_derive; use std::collections::BTreeMap; use std::env; -use std::fs::File; +use std::fs; use std::io::{self, Read, Write}; use std::path::{PathBuf, Path}; use std::process::{Command, Stdio}; @@ -61,7 +61,9 @@ static TARGETS: &'static [&'static str] = &[ "armv5te-unknown-linux-musleabi", "armv7-apple-ios", "armv7-linux-androideabi", + "thumbv7neon-linux-androideabi", "armv7-unknown-linux-gnueabihf", + "thumbv7neon-unknown-linux-gnueabihf", "armv7-unknown-linux-musleabihf", "armebv7r-none-eabi", "armebv7r-none-eabihf", @@ -606,7 +608,7 @@ impl Builder { let filename = path.file_name().unwrap().to_str().unwrap(); let sha256 = self.output.join(format!("{}.sha256", filename)); - t!(t!(File::create(&sha256)).write_all(&sha.stdout)); + t!(fs::write(&sha256, &sha.stdout)); let stdout = String::from_utf8_lossy(&sha.stdout); stdout.split_whitespace().next().unwrap().to_string() @@ -621,8 +623,10 @@ impl Builder { let asc = self.output.join(format!("{}.asc", filename)); println!("signing: {:?}", path); let mut cmd = Command::new("gpg"); - cmd.arg("--no-tty") + cmd.arg("--pinentry-mode=loopback") + .arg("--no-tty") .arg("--yes") + .arg("--batch") .arg("--passphrase-fd").arg("0") .arg("--personal-digest-preferences").arg("SHA512") .arg("--armor") @@ -643,7 +647,7 @@ impl Builder { fn write(&self, contents: &str, channel_name: &str, suffix: &str) { let dst = self.output.join(format!("channel-rust-{}{}", channel_name, suffix)); - t!(t!(File::create(&dst)).write_all(contents.as_bytes())); + t!(fs::write(&dst, contents)); self.hash(&dst); self.sign(&dst); } diff --git a/src/tools/cargo b/src/tools/cargo index 5e85ba14aaa..2cf1f5dda2f 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 5e85ba14aaa20f8133863373404cb0af69eeef2c +Subproject commit 2cf1f5dda2f7ed84e94c4d32f643e0f1f15352f0 diff --git a/src/tools/cargotest/main.rs b/src/tools/cargotest/main.rs index 5b717c45254..ab74e7b7a7f 100644 --- a/src/tools/cargotest/main.rs +++ b/src/tools/cargotest/main.rs @@ -11,8 +11,7 @@ use std::env; use std::process::Command; use std::path::{Path, PathBuf}; -use std::fs::File; -use std::io::Write; +use std::fs; struct Test { repo: &'static str, @@ -91,10 +90,7 @@ fn test_repo(cargo: &Path, out_dir: &Path, test: &Test) { println!("testing {}", test.repo); let dir = clone_repo(test, out_dir); if let Some(lockfile) = test.lock { - File::create(&dir.join("Cargo.lock")) - .expect("") - .write_all(lockfile.as_bytes()) - .expect(""); + fs::write(&dir.join("Cargo.lock"), lockfile).unwrap(); } if !run_cargo_test(cargo, &dir, test.packages) { panic!("tests failed for {}", test.repo); diff --git a/src/tools/clippy b/src/tools/clippy index b2601beb35b..a416c5e0f7c 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit b2601beb35b56fd33bd387a1faeccd3ae02352ed +Subproject commit a416c5e0f7c4c9473069a58410d3ec3e86b1ac0d diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml index 0ee31439358..edf4aeab1c7 100644 --- a/src/tools/compiletest/Cargo.toml +++ b/src/tools/compiletest/Cargo.toml @@ -15,6 +15,7 @@ serde_json = "1.0" serde_derive = "1.0" rustfix = "0.4.1" lazy_static = "1.0" +walkdir = "2" [target.'cfg(unix)'.dependencies] libc = "0.2" diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs index dd2e5557c16..7b967a10c87 100644 --- a/src/tools/compiletest/src/errors.rs +++ b/src/tools/compiletest/src/errors.rs @@ -56,7 +56,7 @@ impl fmt::Display for ErrorKind { #[derive(Debug)] pub struct Error { pub line_num: usize, - /// What kind of message we expect (e.g. warning, error, suggestion). + /// What kind of message we expect (e.g., warning, error, suggestion). /// `None` if not specified or unknown message kind. pub kind: Option, pub msg: String, @@ -119,10 +119,7 @@ fn parse_expected( line: &str, tag: &str, ) -> Option<(WhichLine, Error)> { - let start = match line.find(tag) { - Some(i) => i, - None => return None, - }; + let start = line.find(tag)?; let (follow, adjusts) = if line[start + tag.len()..].chars().next().unwrap() == '|' { (true, 0) } else { diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index ed2114b6530..4e25e3a7711 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -205,7 +205,7 @@ impl EarlyProps { fn ignore_lldb(config: &Config, line: &str) -> bool { if let Some(ref actual_version) = config.lldb_version { if line.starts_with("min-lldb-version") { - let min_version = line.trim_right() + let min_version = line.trim_end() .rsplit(' ') .next() .expect("Malformed lldb version directive"); @@ -228,7 +228,7 @@ impl EarlyProps { } if let Some(ref actual_version) = config.llvm_version { if line.starts_with("min-llvm-version") { - let min_version = line.trim_right() + let min_version = line.trim_end() .rsplit(' ') .next() .expect("Malformed llvm version directive"); @@ -236,7 +236,7 @@ impl EarlyProps { // version &actual_version[..] < min_version } else if line.starts_with("min-system-llvm-version") { - let min_version = line.trim_right() + let min_version = line.trim_end() .rsplit(' ') .next() .expect("Malformed llvm version directive"); @@ -573,14 +573,14 @@ fn iter_header(testfile: &Path, cfg: Option<&str>, it: &mut dyn FnMut(&str)) { None => false, }; if matches { - it(ln[(close_brace + 1)..].trim_left()); + it(ln[(close_brace + 1)..].trim_start()); } } else { panic!("malformed condition directive: expected `{}foo]`, found `{}`", comment_with_brace, ln) } } else if ln.starts_with(comment) { - it(ln[comment.len() ..].trim_left()); + it(ln[comment.len() ..].trim_start()); } } return; @@ -707,21 +707,15 @@ impl Config { fn parse_custom_normalization(&self, mut line: &str, prefix: &str) -> Option<(String, String)> { if self.parse_cfg_name_directive(line, prefix) == ParsedNameDirective::Match { - let from = match parse_normalization_string(&mut line) { - Some(s) => s, - None => return None, - }; - let to = match parse_normalization_string(&mut line) { - Some(s) => s, - None => return None, - }; + let from = parse_normalization_string(&mut line)?; + let to = parse_normalization_string(&mut line)?; Some((from, to)) } else { None } } - /// Parses a name-value directive which contains config-specific information, e.g. `ignore-x86` + /// Parses a name-value directive which contains config-specific information, e.g., `ignore-x86` /// or `normalize-stderr-32bit`. fn parse_cfg_name_directive(&self, line: &str, prefix: &str) -> ParsedNameDirective { if line.starts_with(prefix) && line.as_bytes().get(prefix.len()) == Some(&b'-') { @@ -873,15 +867,35 @@ fn expand_variables(mut value: String, config: &Config) -> String { /// ``` fn parse_normalization_string(line: &mut &str) -> Option { // FIXME support escapes in strings. - let begin = match line.find('"') { - Some(i) => i + 1, - None => return None, - }; - let end = match line[begin..].find('"') { - Some(i) => i + begin, - None => return None, - }; + let begin = line.find('"')? + 1; + let end = line[begin..].find('"')? + begin; let result = line[begin..end].to_owned(); *line = &line[end + 1..]; Some(result) } + +#[test] +fn test_parse_normalization_string() { + let mut s = "normalize-stderr-32bit: \"something (32 bits)\" -> \"something ($WORD bits)\"."; + let first = parse_normalization_string(&mut s); + assert_eq!(first, Some("something (32 bits)".to_owned())); + assert_eq!(s, " -> \"something ($WORD bits)\"."); + + // Nothing to normalize (No quotes) + let mut s = "normalize-stderr-32bit: something (32 bits) -> something ($WORD bits)."; + let first = parse_normalization_string(&mut s); + assert_eq!(first, None); + assert_eq!(s, r#"normalize-stderr-32bit: something (32 bits) -> something ($WORD bits)."#); + + // Nothing to normalize (Only a single quote) + let mut s = "normalize-stderr-32bit: \"something (32 bits) -> something ($WORD bits)."; + let first = parse_normalization_string(&mut s); + assert_eq!(first, None); + assert_eq!(s, "normalize-stderr-32bit: \"something (32 bits) -> something ($WORD bits)."); + + // Nothing to normalize (Three quotes) + let mut s = "normalize-stderr-32bit: \"something (32 bits)\" -> \"something ($WORD bits)."; + let first = parse_normalization_string(&mut s); + assert_eq!(first, Some("something (32 bits)".to_owned())); + assert_eq!(s, " -> \"something ($WORD bits)."); +} diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index f63950b448a..a532e900ea3 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -28,6 +28,7 @@ extern crate serde_derive; extern crate serde_json; extern crate test; extern crate rustfix; +extern crate walkdir; use common::CompareMode; use common::{expected_output_path, output_base_dir, output_relative_path, UI_EXTENSIONS}; @@ -38,11 +39,12 @@ use getopts::Options; use std::env; use std::ffi::OsString; use std::fs; -use std::io::{self, Read}; +use std::io::{self, ErrorKind}; use std::path::{Path, PathBuf}; use std::process::Command; use test::ColorConfig; use util::logv; +use walkdir::WalkDir; use self::header::{EarlyProps, Ignore}; @@ -511,7 +513,11 @@ pub fn test_opts(config: &Config) -> test::TestOpts { test::TestOpts { filter: config.filter.clone(), filter_exact: config.filter_exact, - run_ignored: config.run_ignored, + run_ignored: if config.run_ignored { + test::RunIgnored::Yes + } else { + test::RunIgnored::No + }, format: if config.quiet { test::OutputFormat::Terse } else { @@ -678,6 +684,15 @@ fn stamp(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> Path output_base_dir(config, testpaths, revision).join("stamp") } +/// Return an iterator over timestamps of files in the directory at `path`. +fn collect_timestamps(path: &PathBuf) -> impl Iterator { + WalkDir::new(path) + .into_iter() + .map(|entry| entry.unwrap()) + .filter(|entry| entry.metadata().unwrap().is_file()) + .map(|entry| mtime(entry.path())) +} + fn up_to_date( config: &Config, testpaths: &TestPaths, @@ -686,13 +701,11 @@ fn up_to_date( ) -> bool { let stamp_name = stamp(config, testpaths, revision); // Check hash. - let mut f = match fs::File::open(&stamp_name) { + let contents = match fs::read_to_string(&stamp_name) { Ok(f) => f, + Err(ref e) if e.kind() == ErrorKind::InvalidData => panic!("Can't read stamp contents"), Err(_) => return true, }; - let mut contents = String::new(); - f.read_to_string(&mut contents) - .expect("Can't read stamp contents"); let expected_hash = runtest::compute_stamp_hash(config); if contents != expected_hash { return true; @@ -723,16 +736,7 @@ fn up_to_date( for pretty_printer_file in &pretty_printer_files { inputs.push(mtime(&rust_src_dir.join(pretty_printer_file))); } - let mut entries = config.run_lib_path.read_dir().unwrap().collect::>(); - while let Some(entry) = entries.pop() { - let entry = entry.unwrap(); - let path = entry.path(); - if entry.metadata().unwrap().is_file() { - inputs.push(mtime(&path)); - } else { - entries.extend(path.read_dir().unwrap()); - } - } + inputs.extend(collect_timestamps(&config.run_lib_path)); if let Some(ref rustdoc_path) = config.rustdoc_path { inputs.push(mtime(&rustdoc_path)); inputs.push(mtime(&rust_src_dir.join("src/etc/htmldocck.py"))); @@ -744,6 +748,9 @@ fn up_to_date( inputs.push(mtime(path)); } + // Compiletest itself. + inputs.extend(collect_timestamps(&rust_src_dir.join("src/tools/compiletest/"))); + inputs.iter().any(|input| *input > stamp) } diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index c654230e203..0b3fc5a1924 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -168,7 +168,10 @@ pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec) { match &*config.target { - "arm-linux-androideabi" | "armv7-linux-androideabi" | "aarch64-linux-android" => { + "arm-linux-androideabi" + | "armv7-linux-androideabi" + | "thumbv7neon-linux-androideabi" + | "aarch64-linux-android" => { if !config.adb_device_status { panic!("android device not available"); } @@ -458,11 +461,7 @@ impl<'test> TestCx<'test> { None => 2, }; - let mut src = String::new(); - File::open(&self.testpaths.file) - .unwrap() - .read_to_string(&mut src) - .unwrap(); + let src = fs::read_to_string(&self.testpaths.file).unwrap(); let mut srcs = vec![src]; let mut round = 0; @@ -500,12 +499,7 @@ impl<'test> TestCx<'test> { let mut expected = match self.props.pp_exact { Some(ref file) => { let filepath = self.testpaths.file.parent().unwrap().join(file); - let mut s = String::new(); - File::open(&filepath) - .unwrap() - .read_to_string(&mut s) - .unwrap(); - s + fs::read_to_string(&filepath).unwrap() } None => srcs[srcs.len() - 2].clone(), }; @@ -1088,7 +1082,7 @@ impl<'test> TestCx<'test> { match line { Ok(line) => { let line = if line.starts_with("//") { - line[2..].trim_left() + line[2..].trim_start() } else { line.as_str() }; @@ -1949,10 +1943,7 @@ impl<'test> TestCx<'test> { fn dump_output_file(&self, out: &str, extension: &str) { let outfile = self.make_out_name(extension); - File::create(&outfile) - .unwrap() - .write_all(out.as_bytes()) - .unwrap(); + fs::write(&outfile, out).unwrap(); } /// Create a filename for output with the given extension. Example: @@ -2149,18 +2140,14 @@ impl<'test> TestCx<'test> { path: &P, mut other_files: Option<&mut Vec>, ) -> Vec { - let mut file = - fs::File::open(path).expect("markdown_test_output_check_entry File::open failed"); - let mut content = String::new(); - file.read_to_string(&mut content) - .expect("markdown_test_output_check_entry read_to_string failed"); + let content = fs::read_to_string(&path).unwrap(); let mut ignore = false; content .lines() .enumerate() .filter_map(|(line_nb, line)| { - if (line.trim_left().starts_with("pub mod ") - || line.trim_left().starts_with("mod ")) + if (line.trim_start().starts_with("pub mod ") + || line.trim_start().starts_with("mod ")) && line.ends_with(';') { if let Some(ref mut other_files) = other_files { @@ -2169,7 +2156,7 @@ impl<'test> TestCx<'test> { None } else { let sline = line.split("///").last().unwrap_or(""); - let line = sline.trim_left(); + let line = sline.trim_start(); if line.starts_with("```") { if ignore { ignore = false; @@ -2826,11 +2813,7 @@ impl<'test> TestCx<'test> { } fn check_mir_dump(&self) { - let mut test_file_contents = String::new(); - fs::File::open(self.testpaths.file.clone()) - .unwrap() - .read_to_string(&mut test_file_contents) - .unwrap(); + let test_file_contents = fs::read_to_string(&self.testpaths.file).unwrap(); if let Some(idx) = test_file_contents.find("// END RUST SOURCE") { let (_, tests_text) = test_file_contents.split_at(idx + "// END_RUST SOURCE".len()); let tests_text_str = String::from(tests_text); @@ -2894,9 +2877,7 @@ impl<'test> TestCx<'test> { } self.check_mir_test_timestamp(test_name, &output_file); - let mut dumped_file = fs::File::open(output_file.clone()).unwrap(); - let mut dumped_string = String::new(); - dumped_file.read_to_string(&mut dumped_string).unwrap(); + let dumped_string = fs::read_to_string(&output_file).unwrap(); let mut dumped_lines = dumped_string .lines() .map(|l| nocomment_mir_line(l)) @@ -3108,19 +3089,13 @@ impl<'test> TestCx<'test> { } fn load_expected_output_from_path(&self, path: &Path) -> Result { - let mut result = String::new(); - match File::open(path).and_then(|mut f| f.read_to_string(&mut result)) { - Ok(_) => Ok(result), - Err(e) => Err(format!( - "failed to load expected output from `{}`: {}", - path.display(), - e - )), - } + fs::read_to_string(path).map_err(|err| { + format!("failed to load expected output from `{}`: {}", path.display(), err) + }) } fn delete_file(&self, file: &PathBuf) { - if let Err(e) = ::std::fs::remove_file(file) { + if let Err(e) = fs::remove_file(file) { self.fatal(&format!( "failed to delete `{}`: {}", file.display(), @@ -3182,16 +3157,13 @@ impl<'test> TestCx<'test> { for output_file in &files { if actual.is_empty() { self.delete_file(output_file); - } else { - match File::create(&output_file).and_then(|mut f| f.write_all(actual.as_bytes())) { - Ok(()) => {} - Err(e) => self.fatal(&format!( - "failed to write {} to `{}`: {}", - kind, - output_file.display(), - e - )), - } + } else if let Err(err) = fs::write(&output_file, &actual) { + self.fatal(&format!( + "failed to write {} to `{}`: {}", + kind, + output_file.display(), + err, + )); } } @@ -3243,9 +3215,8 @@ impl<'test> TestCx<'test> { } fn create_stamp(&self) { - let mut f = File::create(::stamp(&self.config, self.testpaths, self.revision)).unwrap(); - f.write_all(compute_stamp_hash(&self.config).as_bytes()) - .unwrap(); + let stamp = ::stamp(&self.config, self.testpaths, self.revision); + fs::write(&stamp, compute_stamp_hash(&self.config)).unwrap(); } } @@ -3316,7 +3287,7 @@ fn normalize_mir_line(line: &str) -> String { fn nocomment_mir_line(line: &str) -> &str { if let Some(idx) = line.find("//") { let (l, _) = line.split_at(idx); - l.trim_right() + l.trim_end() } else { line } diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index 2a716970ca7..381d808e802 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -86,6 +86,8 @@ pub fn matches_os(triple: &str, name: &str) -> bool { } panic!("Cannot determine OS from triple"); } + +/// Determine the architecture from `triple` pub fn get_arch(triple: &str) -> &'static str { let triple: Vec<_> = triple.split('-').collect(); for &(triple_arch, arch) in ARCH_TABLE { @@ -151,3 +153,29 @@ impl PathBufExt for PathBuf { } } } + +#[test] +#[should_panic(expected = "Cannot determine Architecture from triple")] +fn test_get_arch_failure() { + get_arch("abc"); +} + +#[test] +fn test_get_arch() { + assert_eq!("x86_64", get_arch("x86_64-unknown-linux-gnu")); + assert_eq!("x86_64", get_arch("amd64")); +} + +#[test] +#[should_panic(expected = "Cannot determine OS from triple")] +fn test_matches_os_failure() { + matches_os("abc", "abc"); +} + +#[test] +fn test_matches_os() { + assert!(matches_os("x86_64-unknown-linux-gnu", "linux")); + assert!(matches_os("wasm32-unknown-unknown", "emscripten")); + assert!(matches_os("wasm32-unknown-unknown", "wasm32-bare")); + assert!(!matches_os("wasm32-unknown-unknown", "windows")); +} diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs index a5556e1d570..03add412b64 100644 --- a/src/tools/error_index_generator/main.rs +++ b/src/tools/error_index_generator/main.rs @@ -18,8 +18,8 @@ extern crate serialize as rustc_serialize; use std::collections::BTreeMap; use std::env; use std::error::Error; -use std::fs::{read_dir, File}; -use std::io::{Read, Write}; +use std::fs::{self, read_dir, File}; +use std::io::Write; use std::path::Path; use std::path::PathBuf; use std::cell::RefCell; @@ -210,8 +210,7 @@ fn load_all_errors(metadata_dir: &Path) -> Result Option { const REDIRECT: &'static str = "

Redirecting to "] +license = 'MIT/Apache-2.0' +description = """ +Hack for the compiler's own build system +""" + +[lib] +path = "lib.rs" + +[dependencies] +core = { path = "../../libcore" } diff --git a/src/tools/rustc-std-workspace-core/README.md b/src/tools/rustc-std-workspace-core/README.md new file mode 100644 index 00000000000..9c2b1fa91d3 --- /dev/null +++ b/src/tools/rustc-std-workspace-core/README.md @@ -0,0 +1,29 @@ +# The `rustc-std-workspace-core` crate + +This crate is a shim and empty crate which simply depends on `libcore` and +reexports all of its contents. The crate is the crux of empowering the standard +library to depend on crates from crates.io + +Crates on crates.io that the standard library depend on the +`rustc-std-workspace-core` crate from crates.io. On crates.io, however, this +crate is empty. We use `[patch]` to override it to this crate in this +repository. As a result, crates on crates.io will draw a dependency edge to +`libcore`, the version defined in this repository. That should draw all the +dependency edges to ensure Cargo builds crates successfully! + +Note that crates on crates.io need to depend on this crate with the name `core` +for everything to work correctly. To do that they can use: + +```toml +core = { version = "1.0.0", optional = true, package = 'rustc-std-workspace-core' } +``` + +Through the use of the `package` key the crate is renamed to `core`, meaning +it'll look like + +``` +--extern core=.../librustc_std_workspace_core-XXXXXXX.rlib +``` + +when Cargo invokes the compiler, satisfying the implicit `extern crate core` +directive injected by the compiler. diff --git a/src/tools/rustc-std-workspace-core/lib.rs b/src/tools/rustc-std-workspace-core/lib.rs new file mode 100644 index 00000000000..e2946fe2a97 --- /dev/null +++ b/src/tools/rustc-std-workspace-core/lib.rs @@ -0,0 +1,6 @@ +#![feature(no_core)] +#![no_core] + +extern crate core; + +pub use core::*; diff --git a/src/tools/rustc-workspace-hack/Cargo.toml b/src/tools/rustc-workspace-hack/Cargo.toml index f2b08f8e0bb..5acfee28fad 100644 --- a/src/tools/rustc-workspace-hack/Cargo.toml +++ b/src/tools/rustc-workspace-hack/Cargo.toml @@ -17,7 +17,7 @@ path = "lib.rs" # Currently Cargo/RLS depend on `failure` which depends on `synstructure` which # enables this feature. Clippy, however, does not depend on anything that # enables this feature. Enable it unconditionally. -syn = { version = "0.14", features = ['extra-traits'] } +syn = { version = "0.15", features = ['extra-traits'] } [target.'cfg(windows)'.dependencies.winapi] version = "0.3" @@ -50,9 +50,11 @@ features = [ ] [dependencies] -serde_json = { version = "1.0.31", features = ["raw_value"] } -rand = { version = "0.5.5", features = ["i128_support"] } curl-sys = { version = "0.4.13", optional = true } +parking_lot = { version = "0.6", features = ['nightly'] } +rand = { version = "0.5.5", features = ["i128_support"] } +serde_json = { version = "1.0.31", features = ["raw_value"] } +smallvec = { version = "0.6", features = ['union'] } [target.'cfg(not(windows))'.dependencies] openssl = { version = "0.10.12", optional = true } diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index c8ce4cf8bb5..65ed86742e7 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -26,7 +26,10 @@ function getNextStep(content, pos, stop) { return pos; } -// Stupid function extractor based on indent. +// Stupid function extractor based on indent. Doesn't support block +// comments. If someone puts a ' or an " in a block comment this +// will blow up. Template strings are not tested and might also be +// broken. function extractFunction(content, functionName) { var indent = 0; var splitter = "function " + functionName + "("; @@ -51,7 +54,14 @@ function extractFunction(content, functionName) { continue; } while (pos < content.length) { - if (content[pos] === '"' || content[pos] === "'") { + // Eat single-line comments + if (content[pos] === '/' && pos > 0 && content[pos-1] === '/') { + do { + pos += 1; + } while (pos < content.length && content[pos] !== '\n'); + + // Eat quoted strings + } else if (content[pos] === '"' || content[pos] === "'" || content[pos] === "`") { var stop = content[pos]; var is_escaped = false; do { @@ -62,6 +72,8 @@ function extractFunction(content, functionName) { } } while (pos < content.length && (content[pos] !== stop || content[pos - 1] === '\\')); + + // Otherwise, check for indent } else if (content[pos] === '{') { indent += 1; } else if (content[pos] === '}') { @@ -259,6 +271,7 @@ function main(argv) { 'exports.QUERY = QUERY;exports.EXPECTED = EXPECTED;'); const expected = loadedFile.EXPECTED; const query = loadedFile.QUERY; + const filter_crate = loadedFile.FILTER_CRATE; const ignore_order = loadedFile.ignore_order; const exact_check = loadedFile.exact_check; const should_fail = loadedFile.should_fail; diff --git a/src/tools/rustfmt b/src/tools/rustfmt index 43206f41625..be135599ef5 160000 --- a/src/tools/rustfmt +++ b/src/tools/rustfmt @@ -1 +1 @@ -Subproject commit 43206f41625b8ad670d65bcad37686b40a1c7c48 +Subproject commit be135599ef5e54b5219f9adec68e1ee267ea0584 diff --git a/src/tools/tidy/src/bins.rs b/src/tools/tidy/src/bins.rs index f6e42c8dc17..ae930555d09 100644 --- a/src/tools/tidy/src/bins.rs +++ b/src/tools/tidy/src/bins.rs @@ -24,13 +24,10 @@ pub fn check(_path: &Path, _bad: &mut bool) {} #[cfg(unix)] pub fn check(path: &Path, bad: &mut bool) { use std::fs; - use std::io::Read; use std::process::{Command, Stdio}; use std::os::unix::prelude::*; - if let Ok(mut file) = fs::File::open("/proc/version") { - let mut contents = String::new(); - file.read_to_string(&mut contents).unwrap(); + if let Ok(contents) = fs::read_to_string("/proc/version") { // Probably on Windows Linux Subsystem or Docker via VirtualBox, // all files will be marked as executable, so skip checking. if contents.contains("Microsoft") || contents.contains("boot2docker") { diff --git a/src/tools/tidy/src/cargo.rs b/src/tools/tidy/src/cargo.rs index 466d2fa0d2b..ac7e968dff7 100644 --- a/src/tools/tidy/src/cargo.rs +++ b/src/tools/tidy/src/cargo.rs @@ -15,8 +15,7 @@ //! `extern crate` declarations. This should help us keep the DAG correctly //! structured through various refactorings to prune out unnecessary edges. -use std::io::prelude::*; -use std::fs::File; +use std::fs; use std::path::Path; pub fn check(path: &Path, bad: &mut bool) { @@ -41,10 +40,8 @@ pub fn check(path: &Path, bad: &mut bool) { // Verify that the dependencies in Cargo.toml at `tomlfile` are sync'd with the // `extern crate` annotations in the lib.rs at `libfile`. fn verify(tomlfile: &Path, libfile: &Path, bad: &mut bool) { - let mut toml = String::new(); - let mut librs = String::new(); - t!(t!(File::open(tomlfile)).read_to_string(&mut toml)); - t!(t!(File::open(libfile)).read_to_string(&mut librs)); + let toml = t!(fs::read_to_string(&tomlfile)); + let librs = t!(fs::read_to_string(&libfile)); if toml.contains("name = \"bootstrap\"") { return diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 3e27c3d4915..d1e4387166c 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -11,8 +11,7 @@ //! Check license of third-party deps by inspecting vendor use std::collections::{BTreeSet, HashSet, HashMap}; -use std::fs::File; -use std::io::Read; +use std::fs; use std::path::Path; use std::process::Command; @@ -53,6 +52,8 @@ const EXCEPTIONS: &[&str] = &[ "ryu", // Apache-2.0, rls/cargo/... (b/c of serde) "bytesize", // Apache-2.0, cargo "im-rc", // MPL-2.0+, cargo + "adler32", // BSD-3-Clause AND Zlib, cargo dep that isn't used + "fortanix-sgx-abi", // MPL-2.0+, libstd but only for sgx target ]; /// Which crates to check against the whitelist? @@ -63,12 +64,14 @@ const WHITELIST_CRATES: &[CrateVersion] = &[ /// Whitelist of crates rustc is allowed to depend on. Avoid adding to the list if possible. const WHITELIST: &[Crate] = &[ + Crate("adler32"), Crate("aho-corasick"), Crate("arrayvec"), Crate("atty"), Crate("backtrace"), Crate("backtrace-sys"), Crate("bitflags"), + Crate("build_const"), Crate("byteorder"), Crate("cc"), Crate("cfg-if"), @@ -76,6 +79,9 @@ const WHITELIST: &[Crate] = &[ Crate("chalk-macros"), Crate("cloudabi"), Crate("cmake"), + Crate("compiler_builtins"), + Crate("crc"), + Crate("crc32fast"), Crate("crossbeam-deque"), Crate("crossbeam-epoch"), Crate("crossbeam-utils"), @@ -101,6 +107,8 @@ const WHITELIST: &[Crate] = &[ Crate("memmap"), Crate("memoffset"), Crate("miniz-sys"), + Crate("miniz_oxide"), + Crate("miniz_oxide_c_api"), Crate("nodrop"), Crate("num_cpus"), Crate("owning_ref"), @@ -110,7 +118,12 @@ const WHITELIST: &[Crate] = &[ Crate("polonius-engine"), Crate("quick-error"), Crate("rand"), + Crate("rand_chacha"), Crate("rand_core"), + Crate("rand_hc"), + Crate("rand_isaac"), + Crate("rand_pcg"), + Crate("rand_xorshift"), Crate("redox_syscall"), Crate("redox_termios"), Crate("regex"), @@ -120,8 +133,12 @@ const WHITELIST: &[Crate] = &[ Crate("rustc-hash"), Crate("rustc-rayon"), Crate("rustc-rayon-core"), + Crate("rustc_version"), Crate("scoped-tls"), Crate("scopeguard"), + Crate("semver"), + Crate("semver-parser"), + Crate("serde"), Crate("smallvec"), Crate("stable_deref_trait"), Crate("tempfile"), @@ -133,9 +150,9 @@ const WHITELIST: &[Crate] = &[ Crate("unicode-width"), Crate("unreachable"), Crate("utf8-ranges"), + Crate("vcpkg"), Crate("version_check"), Crate("void"), - Crate("vcpkg"), Crate("winapi"), Crate("winapi-build"), Crate("winapi-i686-pc-windows-gnu"), @@ -262,8 +279,7 @@ fn check_license(path: &Path) -> bool { if !path.exists() { panic!("{} does not exist", path.display()); } - let mut contents = String::new(); - t!(t!(File::open(path)).read_to_string(&mut contents)); + let contents = t!(fs::read_to_string(&path)); let mut found_license = false; for line in contents.lines() { diff --git a/src/tools/tidy/src/extdeps.rs b/src/tools/tidy/src/extdeps.rs index a78d2d4ee4e..377a7c33d75 100644 --- a/src/tools/tidy/src/extdeps.rs +++ b/src/tools/tidy/src/extdeps.rs @@ -10,8 +10,7 @@ // ! Check for external package sources. Allow only vendorable packages. -use std::fs::File; -use std::io::Read; +use std::fs; use std::path::Path; /// List of whitelisted sources for packages @@ -25,8 +24,7 @@ pub fn check(path: &Path, bad: &mut bool) { let path = path.join("../Cargo.lock"); // open and read the whole file - let mut cargo_lock = String::new(); - t!(t!(File::open(path)).read_to_string(&mut cargo_lock)); + let cargo_lock = t!(fs::read_to_string(&path)); // process each line for line in cargo_lock.lines() { diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index 85b123e4af5..ff8fa2f920e 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -20,7 +20,7 @@ use std::collections::HashMap; use std::fmt; -use std::fs::File; +use std::fs::{self, File}; use std::io::prelude::*; use std::path::Path; @@ -61,12 +61,9 @@ pub fn check(path: &Path, bad: &mut bool, quiet: bool) { let mut contents = String::new(); - super::walk_many(&[&path.join("test/ui-fulldeps"), - &path.join("test/ui"), - &path.join("test/compile-fail"), - &path.join("test/compile-fail-fulldeps"), - &path.join("test/parse-fail"), - &path.join("test/ui"),], + super::walk_many(&[&path.join("test/ui"), + &path.join("test/ui-fulldeps"), + &path.join("test/compile-fail")], &mut |path| super::filter_dirs(path), &mut |file| { let filename = file.file_name().unwrap().to_string_lossy(); @@ -183,9 +180,7 @@ fn test_filen_gate(filen_underscore: &str, features: &mut Features) -> bool { } pub fn collect_lang_features(base_src_path: &Path, bad: &mut bool) -> Features { - let mut contents = String::new(); - let path = base_src_path.join("libsyntax/feature_gate.rs"); - t!(t!(File::open(path)).read_to_string(&mut contents)); + let contents = t!(fs::read_to_string(base_src_path.join("libsyntax/feature_gate.rs"))); // we allow rustc-internal features to omit a tracking issue. // these features must be marked with `// rustc internal` in its own group. diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index 700103d35d8..614d2053a43 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -56,15 +56,11 @@ pub mod libcoretest; fn filter_dirs(path: &Path) -> bool { let skip = [ - "src/dlmalloc", "src/llvm", "src/llvm-emscripten", "src/libbacktrace", - "src/libcompiler_builtins", "src/librustc_data_structures/owning_ref", - "src/compiler-rt", - "src/liblibc", - "src/rt/hoedown", + "src/vendor", "src/tools/cargo", "src/tools/clang", "src/tools/rls", @@ -76,6 +72,7 @@ fn filter_dirs(path: &Path) -> bool { "src/tools/lldb", "src/target", "src/stdsimd", + "src/rust-sgx", "target", "vendor", ]; diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs index 822db253191..acf72022c60 100644 --- a/src/tools/tidy/src/pal.rs +++ b/src/tools/tidy/src/pal.rs @@ -26,7 +26,6 @@ //! exceptions: //! //! - core may not have platform-specific code -//! - libcompiler_builtins may have platform-specific code //! - libpanic_abort may have platform-specific code //! - libpanic_unwind may have platform-specific code //! - libunwind may have platform-specific code @@ -50,8 +49,6 @@ use std::iter::Iterator; // Paths that may contain platform-specific code const EXCEPTION_PATHS: &[&str] = &[ // std crates - "src/libcompiler_builtins", - "src/liblibc", "src/libpanic_abort", "src/libpanic_unwind", "src/libunwind",

", HDRS.len())?; write!(w, "{:?}", block.index())?; write!(w, "