diff options
| author | Nikolai Vazquez <nvazquez1297@gmail.com> | 2017-09-30 10:08:33 -0400 |
|---|---|---|
| committer | Nikolai Vazquez <nvazquez1297@gmail.com> | 2017-09-30 10:08:33 -0400 |
| commit | 4c853adce9103b8bc84cd6b0026bcdc2eed7da31 (patch) | |
| tree | f71af0eb9d7139af598684355e690596721eac1b /src | |
| parent | d9d877221f65b26e52f49bfc639ef705ff396deb (diff) | |
| parent | c4cca3a72df87def5cb18ff500c643fbff8ad08e (diff) | |
| download | rust-4c853adce9103b8bc84cd6b0026bcdc2eed7da31.tar.gz rust-4c853adce9103b8bc84cd6b0026bcdc2eed7da31.zip | |
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'src')
360 files changed, 7945 insertions, 4158 deletions
diff --git a/src/Cargo.lock b/src/Cargo.lock index 3a9d9ad9c54..c77be5154d3 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1,10 +1,6 @@ [root] -name = "unwind" -version = "0.0.0" -dependencies = [ - "core 0.0.0", - "libc 0.0.0", -] +name = "workspace_symbol" +version = "0.1.0" [[package]] name = "advapi32-sys" @@ -46,8 +42,8 @@ dependencies = [ "alloc 0.0.0", "alloc_system 0.0.0", "build_helper 0.1.0", + "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", - "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.0.0", ] @@ -80,31 +76,31 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace-sys 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "dbghelp-sys 0.2.0 (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.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace-sys" -version = "0.1.12" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -140,16 +136,16 @@ name = "bootstrap" version = "0.0.0" dependencies = [ "build_helper 0.1.0", - "cmake 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "filetime 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -166,8 +162,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "build-manifest" version = "0.1.0" dependencies = [ - "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -175,7 +171,7 @@ dependencies = [ name = "build_helper" version = "0.1.0" dependencies = [ - "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "filetime 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -193,8 +189,8 @@ dependencies = [ "docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", + "filetime 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", "fs2 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "git2 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "git2-curl 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -205,20 +201,20 @@ dependencies = [ "ignore 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "jobserver 0.1.6 (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.30 (registry+https://github.com/rust-lang/crates.io-index)", - "libgit2-sys 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", + "libgit2-sys 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)", "psapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.15 (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.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -233,13 +229,13 @@ name = "cargotest" version = "0.1.0" dependencies = [ "cargo 0.23.0", - "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", + "filetime 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", "git2 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -249,13 +245,18 @@ name = "cargotest2" version = "0.1.0" [[package]] +name = "cc" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "cfg-if" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "clap" -version = "2.26.0" +version = "2.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -263,8 +264,7 @@ dependencies = [ "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "textwrap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -272,10 +272,10 @@ dependencies = [ [[package]] name = "cmake" -version = "0.1.25" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -300,9 +300,9 @@ version = "0.0.0" dependencies = [ "diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "filetime 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -332,7 +332,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -340,7 +340,7 @@ name = "core-foundation-sys" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -349,9 +349,9 @@ version = "0.12.0" dependencies = [ "curl 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -394,23 +394,23 @@ name = "curl" version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "curl-sys 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)", - "socket2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "curl-sys" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", - "libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", + "libz-sys 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -459,8 +459,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -500,7 +500,7 @@ name = "error-chain" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -508,7 +508,7 @@ name = "error-chain" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -520,10 +520,11 @@ dependencies = [ [[package]] name = "filetime" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -540,11 +541,11 @@ version = "0.1.0" [[package]] name = "flate2" -version = "0.2.19" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -567,7 +568,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -582,7 +583,7 @@ dependencies = [ [[package]] name = "futures" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -592,7 +593,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "getopts" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -601,10 +602,10 @@ version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", - "libgit2-sys 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", + "libgit2-sys 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -661,10 +662,10 @@ dependencies = [ "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "quick-error 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -753,9 +754,9 @@ version = "0.1.0" name = "installer" version = "0.0.0" dependencies = [ - "clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.26.2 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -766,7 +767,7 @@ dependencies = [ [[package]] name = "itoa" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -774,20 +775,20 @@ name = "jobserver" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-core" -version = "7.1.0" +version = "7.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -816,9 +817,9 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -837,21 +838,21 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.30" +version = "0.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libgit2-sys" -version = "0.6.14" +version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cmake 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "curl-sys 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)", + "libz-sys 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -860,20 +861,20 @@ name = "libssh2-sys" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cmake 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", - "libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", + "libz-sys 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libz-sys" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -889,12 +890,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lzma-sys" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "filetime 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -942,18 +944,18 @@ name = "mdbook" version = "0.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.26.2 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "handlebars 0.27.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "open 1.2.0 (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.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -963,7 +965,7 @@ name = "memchr" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -971,16 +973,16 @@ name = "memchr" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "miniz-sys" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1005,7 +1007,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (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.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1081,7 +1083,7 @@ name = "num_cpus" version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1090,19 +1092,19 @@ version = "0.1.0" [[package]] name = "open" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl" -version = "0.9.17" +version = "0.9.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1112,11 +1114,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl-sys" -version = "0.9.17" +version = "0.9.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1219,8 +1221,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "profiler_builtins" version = "0.0.0" dependencies = [ + "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", - "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1238,12 +1240,12 @@ version = "0.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "quick-error" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1261,7 +1263,7 @@ name = "racer" version = "2.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.26.2 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1282,11 +1284,16 @@ name = "rand" version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "magenta 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] +name = "redox_syscall" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "reformat" version = "0.1.0" @@ -1346,26 +1353,26 @@ version = "0.122.0" dependencies = [ "cargo 0.23.0", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 7.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 7.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "languageserver-types 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "racer 2.0.10 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-analysis 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-analysis 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "rls-data 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-rustc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-vfs 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustfmt-nightly 0.2.5", - "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustfmt-nightly 0.2.7", + "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rls-analysis" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "derive-new 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1382,8 +1389,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.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1397,8 +1404,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.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1414,7 +1421,7 @@ dependencies = [ name = "rustbook" version = "0.1.0" dependencies = [ - "clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.26.2 (registry+https://github.com/rust-lang/crates.io-index)", "mdbook 0.0.25 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1424,7 +1431,7 @@ version = "0.0.0" dependencies = [ "arena 0.0.0", "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", "fmt_macros 0.0.0", "graphviz 0.0.0", "jobserver 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1482,7 +1489,7 @@ dependencies = [ "alloc 0.0.0", "alloc_system 0.0.0", "build_helper 0.1.0", - "cmake 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -1621,7 +1628,7 @@ version = "0.0.0" dependencies = [ "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "build_helper 0.1.0", - "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_cratesio_shim 0.0.0", ] @@ -1632,7 +1639,7 @@ dependencies = [ "alloc 0.0.0", "alloc_system 0.0.0", "build_helper 0.1.0", - "cmake 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -1640,7 +1647,7 @@ dependencies = [ name = "rustc_metadata" version = "0.0.0" dependencies = [ - "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "proc_macro 0.0.0", @@ -1677,7 +1684,7 @@ dependencies = [ "alloc 0.0.0", "alloc_system 0.0.0", "build_helper 0.1.0", - "cmake 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -1715,6 +1722,7 @@ name = "rustc_privacy" version = "0.0.0" dependencies = [ "rustc 0.0.0", + "rustc_typeck 0.0.0", "syntax 0.0.0", "syntax_pos 0.0.0", ] @@ -1751,8 +1759,8 @@ name = "rustc_trans" version = "0.0.0" dependencies = [ "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", - "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", "jobserver 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1777,7 +1785,12 @@ dependencies = [ name = "rustc_trans_utils" version = "0.0.0" dependencies = [ + "ar 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", + "rustc_back 0.0.0", "syntax 0.0.0", "syntax_pos 0.0.0", ] @@ -1789,7 +1802,7 @@ dependencies = [ "alloc 0.0.0", "alloc_system 0.0.0", "build_helper 0.1.0", - "cmake 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -1815,8 +1828,8 @@ name = "rustdoc" version = "0.0.0" dependencies = [ "build_helper 0.1.0", + "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", "html-diff 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1831,18 +1844,18 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "0.2.5" +version = "0.2.7" dependencies = [ "diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.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.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1890,7 +1903,7 @@ version = "0.8.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.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1900,22 +1913,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.11" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.11" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive_internals 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive_internals" -version = "0.15.1" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1927,18 +1940,18 @@ name = "serde_ignored" version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1962,12 +1975,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "socket2" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (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.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1985,10 +1998,10 @@ dependencies = [ "alloc_jemalloc 0.0.0", "alloc_system 0.0.0", "build_helper 0.1.0", + "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "collections 0.0.0", "compiler_builtins 0.0.0", "core 0.0.0", - "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.0.0", "panic_abort 0.0.0", "panic_unwind 0.0.0", @@ -2018,7 +2031,7 @@ dependencies = [ "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", "precomputed-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2116,7 +2129,7 @@ name = "syntex_errors" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2138,7 +2151,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2152,8 +2165,8 @@ name = "tar" version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "filetime 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2194,7 +2207,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2210,13 +2223,13 @@ dependencies = [ name = "test" version = "0.0.0" dependencies = [ - "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.0.0", ] [[package]] name = "textwrap" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2229,7 +2242,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2266,7 +2279,7 @@ name = "toml" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2308,6 +2321,10 @@ version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "unicødë" +version = "0.1.0" + +[[package]] name = "unreachable" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2331,6 +2348,14 @@ dependencies = [ ] [[package]] +name = "unwind" +version = "0.0.0" +dependencies = [ + "core 0.0.0", + "libc 0.0.0", +] + +[[package]] name = "url" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2345,7 +2370,7 @@ name = "url_serde" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2434,7 +2459,7 @@ name = "xattr" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2442,7 +2467,7 @@ name = "xz2" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lzma-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "lzma-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2457,16 +2482,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" "checksum ar 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b24e4eef8e3fa7e2ca75b157e6039cdf8d9d3a68213ddc19d0fd9d576b9717c9" "checksum atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159" -"checksum backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72f9b4182546f4b04ebc4ab7f84948953a118bd6021a1b6a6c909e3e94f6be76" -"checksum backtrace-sys 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "afccc5772ba333abccdf60d55200fa3406f8c59dcf54d5f7998c9107d3799c7c" +"checksum backtrace 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "99f2ce94e22b8e664d95c57fff45b98a966c2252b60691d0b7aeeccd88d70983" +"checksum backtrace-sys 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "c63ea141ef8fdb10409d0f5daf30ac51f84ef43bff66f16627773d2a292cd189" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5cde24d1b2e2216a726368b2363a273739c91f4e3eb4e0dd12d672d396ad989" "checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32" +"checksum cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7db2f146208d7e0fbee761b09cd65a7f51ccc38705d4e7262dad4d73b12a76b1" "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" -"checksum clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2267a8fdd4dce6956ba6649e130f62fb279026e5e84b92aa939ac8f85ce3f9f0" -"checksum cmake 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "0c8a6541a55bcd72d3de4faee2d101a5a66df29790282c7f797082a7228a9b3d" +"checksum clap 2.26.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3451e409013178663435d6f15fdb212f14ee4424a3d74f979d081d0a66b6f1f2" +"checksum cmake 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "357c07e7a1fc95732793c1edb5901e1a1f305cfcf63a90eb12dbd22bdb6b789d" "checksum conv 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "78ff10625fd0ac447827aa30ea8b861fead473bb60aeb73af6c1c58caf0d1299" "checksum core-foundation 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5909502e547762013619f4c4e01cc7393c20fe2d52d7fa471c1210adb2320dc7" "checksum core-foundation-sys 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bc9fb3d6cb663e6fd7cf1c63f9b144ee2b1e4a78595a0451dd34bff85b9a3387" @@ -2475,7 +2501,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ef6124306e5ebc5ab11891d063aeafdd0cdc308079b708c8b566125f3680292b" "checksum cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "079adec4af52bb5275eadd004292028c79eb3c5f5b4ee8086a36d4197032f6df" "checksum curl 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7034c534a1d7d22f7971d6088aa9d281d219ef724026c3428092500f41ae9c2c" -"checksum curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d5481162dc4f424d088581db2f979fa7d4c238fe9794595de61d8d7522e277de" +"checksum curl-sys 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "4bee31aa3a079d5f3ff9579ea4dcfb1b1a17a40886f5f467436d383e78134b55" "checksum custom_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ef8ae57c4978a2acd8b869ce6b9ca1dfe817bff704c220209fdef2c0b75a01b9" "checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850" "checksum debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3" @@ -2488,15 +2514,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" "checksum error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9435d864e017c3c6afeac1654189b06cdb491cf2ff73dbf0d73b0f292f42ff8" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" -"checksum filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5363ab8e4139b8568a6237db5248646e5a8a2f89bd5ccb02092182b11fd3e922" -"checksum flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "36df0166e856739905cd3d7e0b210fe818592211a008862599845e012d8d304c" +"checksum filetime 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "6ab199bf38537c6f38792669e081e0bb278b9b7405bba2642e4e5d15bf732c0e" +"checksum flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "e6234dd4468ae5d1e2dbb06fe2b058696fdc50a339c68a393aefbf00bc81e423" "checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344" "checksum foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e4056b9bd47f8ac5ba12be771f77a0dae796d1bbaaf5fd0b9c2d38b69b8a29d" "checksum fs2 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ab76cfd2aaa59b7bf6688ad9ba15bbae64bff97f04ea02144cfd3443e5c2866" "checksum futf 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "51f93f3de6ba1794dcd5810b3546d004600a59a98266487c8407bc4b24e398f3" -"checksum futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a82bdc62350ca9d7974c760e9665102fc9d740992a528c2254aa930e53b783c4" +"checksum futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "05a23db7bd162d4e8265968602930c476f688f0c180b44bdaf55e0cb2c687558" "checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" -"checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685" +"checksum getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "65922871abd2f101a2eb0eaebadc66668e54a87ad9c3dd82520b5f86ede5eff9" "checksum git2 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0c1c0203d653f4140241da0c1375a404f0a397249ec818cd2076c6280c50f6fa" "checksum git2-curl 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "68676bc784bf0bef83278898929bf64a251e87c0340723d0b93fa096c9c5bf8e" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" @@ -2509,19 +2535,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum html5ever 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a49d5001dd1bddf042ea41ed4e0a671d50b1bf187e66b349d7ec613bdce4ad90" "checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d" "checksum ignore 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b3fcaf2365eb14b28ec7603c98c06cc531f19de9eb283d89a3dff8417c8c99f5" -"checksum itoa 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ac17257442c2ed77dbc9fd555cf83c58b0c7f7d0e8f2ae08c0ac05c72842e1f6" +"checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" "checksum jobserver 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "443ae8bc0af6c106e6e8b77e04684faecc1a5ce94e058f4c2b0a037b0ea1b133" -"checksum jsonrpc-core 7.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "903e5eee845f3d83c1436d12848d97b1247cf850ff06a8e1db2f1ce3543af2cf" +"checksum jsonrpc-core 7.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b1acd0f9934da94466d2370f36832b9b19271b4abdfdb5e69f0bcd991ebcd515" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum kuchiki 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ef2ea4f2f7883cd7c6772b06c14abca01a2cc1f75c426cebffcf6b3b925ef9fc" "checksum languageserver-types 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d52e477b23bf52cd3ca0f9fc6c5d14be954eec97e3b9cdfbd962d911bd533caf" "checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf" -"checksum libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)" = "2370ca07ec338939e356443dac2296f581453c35fe1e3a3ed06023c49435f915" -"checksum libgit2-sys 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)" = "c00f6e5bc3fb2b5f87e75e8d0fd4ae6720d55f3ee23d389b7c6cae30f8db8db1" +"checksum libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "d1419b2939a0bc44b77feb34661583c7546b532b192feab36249ab584b86856c" +"checksum libgit2-sys 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)" = "205fc37e829c5b36de63d14c8dc8b62c5a6a2519b16318ed0977079ca97256a9" "checksum libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0db4ec23611747ef772db1c4d650f8bd762f07b461727ec998f953c614024b75" -"checksum libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd64ef8ee652185674455c1d450b83cbc8ad895625d543b5324d923f82e4d8" +"checksum libz-sys 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "44ebbc760fd2d2f4d93de09a0e13d97e057612052e871da9985cedcb451e6bd5" "checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b" -"checksum lzma-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "66b2e318eb97ab84f05725471f90c52a09c964053a5899a13fd0165acc26d00b" +"checksum lzma-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c1b93b78f89e8737dac81837fc8f5521ac162abcba902e1a3db949d55346d1da" "checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" "checksum magenta 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf0336886480e671965f794bc9b6fce88503563013d1bfb7a502c81fe3ac527" "checksum magenta-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40d014c7011ac470ae28e2f76a02bfea4a8480f73e701353b49ad7a8d75f4699" @@ -2530,7 +2556,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum mdbook 0.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "146eadfc6d141452a364c351f07bb19208d1401e931f40b8532f87bba3ecc40f" "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" "checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" -"checksum miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "28eaee17666671fa872e567547e8428e83308ebe5808cdf6a0e28397dbe2c726" +"checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09" "checksum num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "a311b77ebdc5dd4cf6449d81e4135d9f0e3b153839ac90e648a8ef538f923525" @@ -2541,10 +2567,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum num-rational 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "288629c76fac4b33556f4b7ab57ba21ae202da65ba8b77466e6d598e31990790" "checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0" "checksum num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aec53c34f2d0247c5ca5d32cca1478762f301740468ee9ee6dcb7a0dd7a0c584" -"checksum open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3478ed1686bd1300c8a981a940abc92b06fac9cbef747f4c668d4e032ff7b842" -"checksum openssl 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)" = "085aaedcc89a2fac1eb2bc19cd66f29d4ea99fec60f82a5f3a88a6be7dbd90b5" +"checksum open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c281318d992e4432cfa799969467003d05921582a7489a8325e37f8a450d5113" +"checksum openssl 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)" = "816914b22eb15671d62c73442a51978f311e911d6a6f6cbdafa6abce1b5038fc" "checksum openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d98df0270d404ccd3c050a41d579c52d1db15375168bb3471e04ec0f5f378daf" -"checksum openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)" = "7e3a9845a4c9fdb321931868aae5549e96bb7b979bf9af7de03603d74691b5f3" +"checksum openssl-sys 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)" = "1e4c63a7d559c1e5afa6d6a9e6fa34bbc5f800ffc9ae08b72c605420b0c4f5e8" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" "checksum percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de154f638187706bde41d9b4738748933d64e6b37bdbffc0b47a97d16a6ae356" "checksum pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0a6dda33d67c26f0aac90d324ab2eb7239c819fc7b2552fe9faa4fe88441edc8" @@ -2557,16 +2583,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum procedural-masquerade 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c93cdc1fb30af9ddf3debc4afbdb0f35126cbd99daa229dd76cdd5349b41d989" "checksum psapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "abcd5d1a07d360e29727f757a9decb3ce8bc6e0efa8969cfaad669a8317a2478" "checksum pulldown-cmark 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9ab1e588ef8efd702c7ed9d2bd774db5e6f4d878bb5a1a9f371828fbdff6973" -"checksum quick-error 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c36987d4978eb1be2e422b1e0423a557923a5c3e7e6f31d5699e9aafaefa469" +"checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4" "checksum quote 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4c5cf478fe1006dbcc72567121d23dbdae5f1632386068c5c86ff4f645628504" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum racer 2.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "f120c7510ef7aff254aeb06067fb6fac573ec96a1660e194787cf9dced412bf0" "checksum rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "eb250fd207a4729c976794d03db689c9be1d634ab5a1c9da9492a13d8fecbcdf" +"checksum redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "8dde11f18c108289bef24469638a04dce49da56084f2d50618b226e47eb04509" "checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" "checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b" "checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" -"checksum rls-analysis 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "4302cc8291570d7f817945845d8c01756e833dbc93c0a87d4f6c9a0b0b7992f1" +"checksum rls-analysis 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "fa390bdc70b0a90d07d9cd5c6989ba5fca2d59728903919ebda1a1b2037b18d7" "checksum rls-data 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "11d339f1888e33e74d8032de0f83c40b2bdaaaf04a8cfc03b32186c3481fb534" "checksum rls-rustc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b21ea952e9bf1569929abf1bb920262cde04b7b1b26d8e0260286302807299d2" "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a" @@ -2579,15 +2606,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum selectors 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3c89b1c6a3c029c82263f7dd2d44d0005ee7374eb09e254ab59dede4353a8c0" "checksum semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bee2bc909ab2d8d60dab26e8cad85b25d795b14603a0dcb627b78b9d30b6454b" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f7726f29ddf9731b17ff113c461e362c381d9d69433f79de4f3dd572488823e9" -"checksum serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cf823e706be268e73e7747b147aa31c8f633ab4ba31f115efb57e5047c3a76dd" -"checksum serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37aee4e0da52d801acfbc0cc219eb1eda7142112339726e427926a6f6ee65d3a" +"checksum serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "6a7046c9d4c6c522d10b2d098f9bebe2bef227e0e74044d8c1bfcf6b476af799" +"checksum serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "1afcaae083fd1c46952a315062326bc9957f182358eb7da03b57ef1c688f7aa9" +"checksum serde_derive_internals 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd381f6d01a6616cdba8530492d453b7761b456ba974e98768a18cad2cd76f58" "checksum serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "190e9765dcedb56be63b6e0993a006c7e3b071a016a304736e4a315dc01fb142" -"checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b" +"checksum serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d243424e06f9f9c39e3cd36147470fd340db785825e367625f79298a6ac6b7ac" "checksum shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dd5cc96481d54583947bfe88bf30c23d53f883c6cd0145368b69989d97b84ef8" "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" "checksum smallvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4f8266519bc1d17d0b5b16f6c21295625d562841c708f6376f49028a43e9c11e" -"checksum socket2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4daf80fcf54186fac4fe049e0b39d36a5cfde69a11a06413e61e77f553cccf9a" +"checksum socket2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9e76b159741052c7deaa9fd0b5ca6b5f79cecf525ed665abfe5002086c6b2791" "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b" "checksum string_cache 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "413fc7852aeeb5472f1986ef755f561ddf0c789d3d796e65f0b6fe293ecd4ef8" "checksum string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "479cde50c3539481f33906a387f2bd17c8e87cb848c35b6021d41fb81ff9b4d7" @@ -2606,7 +2633,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" "checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209" "checksum termcolor 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9065bced9c3e43453aa3d56f1e98590b8455b341d2fa191a1090c0dd0b242c75" -"checksum textwrap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f728584ea33b0ad19318e20557cb0a39097751dbb07171419673502f848c7af6" +"checksum textwrap 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df8e08afc40ae3459e4838f303e465aa50d823df8d7f83ca88108f6d3afe7edd" "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" "checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" "checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14" diff --git a/src/Cargo.toml b/src/Cargo.toml index 12c074b6a41..f4b4189e01f 100644 --- a/src/Cargo.toml +++ b/src/Cargo.toml @@ -38,6 +38,8 @@ members = [ "tools/rls/test_data/infer_custom_bin", "tools/rls/test_data/infer_lib", "tools/rls/test_data/omit_init_build", + "tools/rls/test_data/unicødë", + "tools/rls/test_data/workspace_symbol", ] # Curiously, compiletest will segfault if compiled with opt-level=3 on 64-bit @@ -60,10 +62,5 @@ debug-assertions = false [patch."https://github.com/rust-lang/cargo"] cargo = { path = "tools/cargo" } -# Override rustfmt dependencies both on the repo and the crate (the RLS -# sometimes uses either). -# FIXME should only need the crates.io patch, long term. -[patch."https://github.com/rust-lang-nursery/rustfmt"] -rustfmt-nightly = { path = "tools/rustfmt" } [patch.crates-io] rustfmt-nightly = { path = "tools/rustfmt" } diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 85e3b65c195..3f1d03b1872 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -34,7 +34,7 @@ cmake = "0.1.23" filetime = "0.1" num_cpus = "1.0" getopts = "0.2" -gcc = "0.3.54" +cc = "1.0" libc = "0.2" serde = "1.0.8" serde_derive = "1.0.8" diff --git a/src/bootstrap/bin/sccache-plus-cl.rs b/src/bootstrap/bin/sccache-plus-cl.rs index 266dffa5c92..8584014d48d 100644 --- a/src/bootstrap/bin/sccache-plus-cl.rs +++ b/src/bootstrap/bin/sccache-plus-cl.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern crate gcc; +extern crate cc; use std::env; use std::process::{self, Command}; @@ -18,7 +18,7 @@ fn main() { // Locate the actual compiler that we're invoking env::remove_var("CC"); env::remove_var("CXX"); - let mut cfg = gcc::Build::new(); + let mut cfg = cc::Build::new(); cfg.cargo_metadata(false) .out_dir("/") .target(&target) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index f12da29c45b..4a8c3dcebcb 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -682,7 +682,7 @@ def bootstrap(): try: with open(args.config or 'config.toml') as config: build.config_toml = config.read() - except OSError: + except (OSError, IOError): pass if '\nverbose = 2' in build.config_toml: diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 8a6c998c932..e7a5196178c 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -306,7 +306,7 @@ impl<'a> Builder<'a> { Subcommand::Bench { ref paths, .. } => (Kind::Bench, &paths[..]), Subcommand::Dist { ref paths } => (Kind::Dist, &paths[..]), Subcommand::Install { ref paths } => (Kind::Install, &paths[..]), - Subcommand::Clean => panic!(), + Subcommand::Clean { .. } => panic!(), }; let builder = Builder { @@ -531,7 +531,10 @@ impl<'a> Builder<'a> { // For other crates, however, we know that we've already got a standard // library up and running, so we can use the normal compiler to compile // build scripts in that situation. - if mode == Mode::Libstd { + // + // If LLVM support is disabled we need to use the snapshot compiler to compile + // build scripts, as the new compiler doesnt support executables. + if mode == Mode::Libstd || !self.build.config.llvm_enabled { cargo.env("RUSTC_SNAPSHOT", &self.initial_rustc) .env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_snapshot_libdir()); } else { diff --git a/src/bootstrap/cc.rs b/src/bootstrap/cc_detect.rs index c77e609d70b..08df65c7611 100644 --- a/src/bootstrap/cc.rs +++ b/src/bootstrap/cc_detect.rs @@ -23,7 +23,7 @@ //! 6. "cc" //! //! Some of this logic is implemented here, but much of it is farmed out to the -//! `gcc` crate itself, so we end up having the same fallbacks as there. +//! `cc` crate itself, so we end up having the same fallbacks as there. //! Similar logic is then used to find a C++ compiler, just some s/cc/c++/ is //! used. //! @@ -35,7 +35,7 @@ use std::process::Command; use std::iter; use build_helper::{cc2ar, output}; -use gcc; +use cc; use Build; use config::Target; @@ -45,7 +45,7 @@ pub fn find(build: &mut Build) { // For all targets we're going to need a C compiler for building some shims // and such as well as for being a linker for Rust code. for target in build.targets.iter().chain(&build.hosts).cloned().chain(iter::once(build.build)) { - let mut cfg = gcc::Build::new(); + let mut cfg = cc::Build::new(); cfg.cargo_metadata(false).opt_level(0).warnings(false).debug(false) .target(&target).host(&build.build); @@ -67,7 +67,7 @@ pub fn find(build: &mut Build) { // For all host triples we need to find a C++ compiler as well for host in build.hosts.iter().cloned().chain(iter::once(build.build)) { - let mut cfg = gcc::Build::new(); + let mut cfg = cc::Build::new(); cfg.cargo_metadata(false).opt_level(0).warnings(false).debug(false).cpp(true) .target(&host).host(&build.build); let config = build.config.target_config.get(&host); @@ -82,7 +82,7 @@ pub fn find(build: &mut Build) { } } -fn set_compiler(cfg: &mut gcc::Build, +fn set_compiler(cfg: &mut cc::Build, gnu_compiler: &str, target: Interned<String>, config: Option<&Target>, diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 21e7a052362..6e276f44668 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -254,7 +254,11 @@ impl Step for Rls { builder.add_rustc_lib_path(compiler, &mut cargo); - try_run(build, &mut cargo); + try_run_expecting( + build, + &mut cargo, + builder.build.config.toolstate.rls.passes(ToolState::Testing), + ); } } @@ -295,7 +299,11 @@ impl Step for Rustfmt { builder.add_rustc_lib_path(compiler, &mut cargo); - try_run(build, &mut cargo); + try_run_expecting( + build, + &mut cargo, + builder.build.config.toolstate.rustfmt.passes(ToolState::Testing), + ); } } diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs index 119340a0190..87f194fb7d2 100644 --- a/src/bootstrap/clean.rs +++ b/src/bootstrap/clean.rs @@ -13,7 +13,7 @@ //! Responsible for cleaning out a build directory of all old and stale //! artifacts to prepare for a fresh build. Currently doesn't remove the //! `build/cache` directory (download cache) or the `build/$target/llvm` -//! directory as we want that cached between builds. +//! directory unless the --all flag is present. use std::fs; use std::io::{self, ErrorKind}; @@ -21,24 +21,29 @@ use std::path::Path; use Build; -pub fn clean(build: &Build) { +pub fn clean(build: &Build, all: bool) { rm_rf("tmp".as_ref()); - rm_rf(&build.out.join("tmp")); - rm_rf(&build.out.join("dist")); - for host in &build.hosts { - let entries = match build.out.join(host).read_dir() { - Ok(iter) => iter, - Err(_) => continue, - }; + if all { + rm_rf(&build.out); + } else { + rm_rf(&build.out.join("tmp")); + rm_rf(&build.out.join("dist")); - for entry in entries { - let entry = t!(entry); - if entry.file_name().to_str() == Some("llvm") { - continue + for host in &build.hosts { + let entries = match build.out.join(host).read_dir() { + Ok(iter) => iter, + Err(_) => continue, + }; + + for entry in entries { + let entry = t!(entry); + if entry.file_name().to_str() == Some("llvm") { + continue + } + let path = t!(entry.path().canonicalize()); + rm_rf(&path); } - let path = t!(entry.path().canonicalize()); - rm_rf(&path); } } } diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 2438be89776..67337bf4421 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -109,6 +109,8 @@ v("musl-root-armhf", "target.arm-unknown-linux-musleabihf.musl-root", "arm-unknown-linux-musleabihf install directory") v("musl-root-armv7", "target.armv7-unknown-linux-musleabihf.musl-root", "armv7-unknown-linux-musleabihf install directory") +v("musl-root-aarch64", "target.aarch64-unknown-linux-musl.musl-root", + "aarch64-unknown-linux-musl install directory") v("qemu-armhf-rootfs", "target.arm-unknown-linux-gnueabihf.qemu-rootfs", "rootfs in qemu testing, you probably don't want to use this") v("qemu-aarch64-rootfs", "target.aarch64-unknown-linux-gnu.qemu-rootfs", diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 5188604b0a6..3d4aa0413db 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -1098,13 +1098,8 @@ impl Step for Rls { .arg("--output-dir").arg(&distdir(build)) .arg("--non-installed-overlay").arg(&overlay) .arg(format!("--package-name={}-{}", name, target)) - .arg("--legacy-manifest-dirs=rustlib,cargo"); - - if build.config.channel == "nightly" { - cmd.arg("--component-name=rls"); - } else { - cmd.arg("--component-name=rls-preview"); - } + .arg("--legacy-manifest-dirs=rustlib,cargo") + .arg("--component-name=rls-preview"); build.run(&mut cmd); distdir(build).join(format!("{}-{}.tar.gz", name, target)) @@ -1333,12 +1328,8 @@ impl Step for Extended { cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-std"), target)) .join(format!("rust-std-{}", target)), &exe.join("rust-std")); - let rls_path = if build.config.channel == "nightly" { - work.join(&format!("{}-{}", pkgname(build, "rls"), target)).join("rls") - } else { - work.join(&format!("{}-{}", pkgname(build, "rls"), target)).join("rls-preview") - }; - cp_r(&rls_path, &exe.join("rls")); + cp_r(&work.join(&format!("{}-{}", pkgname(build, "rls"), target)).join("rls-preview"), + &exe.join("rls")); cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-analysis"), target)) .join(format!("rust-analysis-{}", target)), &exe.join("rust-analysis")); diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 7546d7fd4f0..df378188b4a 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -60,7 +60,9 @@ pub enum Subcommand { paths: Vec<PathBuf>, test_args: Vec<String>, }, - Clean, + Clean { + all: bool, + }, Dist { paths: Vec<PathBuf>, }, @@ -147,6 +149,7 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`"); opts.optmulti("", "test-args", "extra arguments", "ARGS"); }, "bench" => { opts.optmulti("", "test-args", "extra arguments", "ARGS"); }, + "clean" => { opts.optflag("", "all", "clean all build artifacts"); }, _ => { }, }; @@ -250,7 +253,7 @@ Arguments: } }); - // All subcommands can have an optional "Available paths" section + // All subcommands except `clean` can have an optional "Available paths" section if matches.opt_present("verbose") { let config = Config::parse(&["build".to_string()]); let mut build = Build::new(config); @@ -258,9 +261,10 @@ Arguments: let maybe_rules_help = Builder::get_help(&build, subcommand.as_str()); extra_help.push_str(maybe_rules_help.unwrap_or_default().as_str()); - } else { - extra_help.push_str(format!("Run `./x.py {} -h -v` to see a list of available paths.", - subcommand).as_str()); + } else if subcommand.as_str() != "clean" { + extra_help.push_str(format!( + "Run `./x.py {} -h -v` to see a list of available paths.", + subcommand).as_str()); } // User passed in -h/--help? @@ -290,10 +294,13 @@ Arguments: } "clean" => { if paths.len() > 0 { - println!("\nclean takes no arguments\n"); + println!("\nclean does not take a path argument\n"); usage(1, &opts, &subcommand_help, &extra_help); } - Subcommand::Clean + + Subcommand::Clean { + all: matches.opt_present("all"), + } } "dist" => { Subcommand::Dist { diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 06c7c4c2faf..2d721f45578 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -126,7 +126,7 @@ extern crate lazy_static; extern crate serde_json; extern crate cmake; extern crate filetime; -extern crate gcc; +extern crate cc; extern crate getopts; extern crate num_cpus; extern crate toml; @@ -148,7 +148,7 @@ use build_helper::{run_silent, run_suppressed, try_run_silent, try_run_suppresse use util::{exe, libdir, OutputFolder, CiEnv}; -mod cc; +mod cc_detect; mod channel; mod check; mod clean; @@ -241,9 +241,9 @@ pub struct Build { // Runtime state filled in later on // target -> (cc, ar) - cc: HashMap<Interned<String>, (gcc::Tool, Option<PathBuf>)>, + cc: HashMap<Interned<String>, (cc::Tool, Option<PathBuf>)>, // host -> (cc, ar) - cxx: HashMap<Interned<String>, gcc::Tool>, + cxx: HashMap<Interned<String>, cc::Tool>, crates: HashMap<Interned<String>, Crate>, is_sudo: bool, ci_env: CiEnv, @@ -345,12 +345,12 @@ impl Build { job::setup(self); } - if let Subcommand::Clean = self.config.cmd { - return clean::clean(self); + if let Subcommand::Clean { all } = self.config.cmd { + return clean::clean(self, all); } self.verbose("finding compilers"); - cc::find(self); + cc_detect::find(self); self.verbose("running sanity check"); sanity::check(self); // If local-rust is the same major.minor as the current version, then force a local-rebuild @@ -619,7 +619,7 @@ impl Build { /// specified. fn cflags(&self, target: Interned<String>) -> Vec<String> { // Filter out -O and /O (the optimization flags) that we picked up from - // gcc-rs because the build scripts will determine that for themselves. + // cc-rs because the build scripts will determine that for themselves. let mut base = self.cc[&target].0.args().iter() .map(|s| s.to_string_lossy().into_owned()) .filter(|s| !s.starts_with("-O") && !s.starts_with("/O")) diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 99077d03dbe..c4e80630315 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -27,7 +27,7 @@ use std::process::Command; use build_helper::output; use cmake; -use gcc; +use cc; use Build; use util; @@ -289,7 +289,7 @@ impl Step for TestHelpers { let _folder = build.fold_output(|| "build_test_helpers"); println!("Building test helpers"); t!(fs::create_dir_all(&dst)); - let mut cfg = gcc::Build::new(); + let mut cfg = cc::Build::new(); // We may have found various cross-compilers a little differently due to our // extra configuration, so inform gcc of these compilers. Note, though, that @@ -367,7 +367,7 @@ impl Step for Openssl { if !ok { panic!("failed to download openssl source") } - let mut shasum = if target.contains("apple") { + let mut shasum = if target.contains("apple") || build.build.contains("netbsd") { let mut cmd = Command::new("shasum"); cmd.arg("-a").arg("256"); cmd @@ -387,7 +387,7 @@ impl Step for Openssl { let dst = build.openssl_install_dir(target).unwrap(); drop(fs::remove_dir_all(&obj)); drop(fs::remove_dir_all(&dst)); - build.run(Command::new("tar").arg("xf").arg(&tarball).current_dir(&out)); + build.run(Command::new("tar").arg("zxf").arg(&tarball).current_dir(&out)); let mut configure = Command::new("perl"); configure.arg(obj.join("Configure")); @@ -399,6 +399,7 @@ impl Step for Openssl { let os = match &*target { "aarch64-linux-android" => "linux-aarch64", "aarch64-unknown-linux-gnu" => "linux-aarch64", + "aarch64-unknown-linux-musl" => "linux-aarch64", "arm-linux-androideabi" => "android", "arm-unknown-linux-gnueabi" => "linux-armv4", "arm-unknown-linux-gnueabihf" => "linux-armv4", diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 54208d8bb57..8b23be69a85 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -221,8 +221,9 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake let run = |cmd: &mut Command| { cmd.output().map(|output| { String::from_utf8_lossy(&output.stdout) - .lines().next().unwrap() - .to_string() + .lines().next().unwrap_or_else(|| { + panic!("{:?} failed {:?}", cmd, output) + }).to_string() }) }; build.lldb_version = run(Command::new("lldb").arg("--version")).ok(); diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index db794f6d6c7..a05e58e6a22 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -126,6 +126,10 @@ pub fn prepare_tool_cargo( cargo.env("LIBZ_SYS_STATIC", "1"); } + // if tools are using lzma we want to force the build script to build its + // own copy + cargo.env("LZMA_API_STATIC", "1"); + cargo.env("CFG_RELEASE_CHANNEL", &build.config.channel); cargo.env("CFG_VERSION", build.rust_version()); @@ -304,6 +308,11 @@ impl Step for Rustdoc { target, "build", "src/tools/rustdoc"); + + // Most tools don't get debuginfo, but rustdoc should. + cargo.env("RUSTC_DEBUGINFO", builder.config.rust_debuginfo.to_string()) + .env("RUSTC_DEBUGINFO_LINES", builder.config.rust_debuginfo_lines.to_string()); + build.run(&mut cargo); // Cargo adds a number of paths to the dylib search path on windows, which results in // the wrong rustdoc being executed. To avoid the conflicting rustdocs, we name the "tool" @@ -449,7 +458,7 @@ impl Step for Rls { tool: "rls", mode: Mode::Librustc, path: "src/tools/rls", - expectation: BuildExpectation::None, + expectation: builder.build.config.toolstate.rls.passes(ToolState::Compiling), }) } } @@ -484,7 +493,7 @@ impl Step for Rustfmt { tool: "rustfmt", mode: Mode::Librustc, path: "src/tools/rustfmt", - expectation: BuildExpectation::None, + expectation: builder.build.config.toolstate.rustfmt.passes(ToolState::Compiling), }) } } diff --git a/src/bootstrap/toolstate.rs b/src/bootstrap/toolstate.rs index 0711c034602..8a113f6b4d2 100644 --- a/src/bootstrap/toolstate.rs +++ b/src/bootstrap/toolstate.rs @@ -46,4 +46,6 @@ impl Default for ToolState { pub struct ToolStates { pub miri: ToolState, pub clippy: ToolState, + pub rls: ToolState, + pub rustfmt: ToolState, } diff --git a/src/ci/docker/cross/Dockerfile b/src/ci/docker/cross/Dockerfile index a83bbe9c60e..05745709a07 100644 --- a/src/ci/docker/cross/Dockerfile +++ b/src/ci/docker/cross/Dockerfile @@ -14,6 +14,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ zlib1g-dev \ g++-arm-linux-gnueabi \ g++-arm-linux-gnueabihf \ + g++-aarch64-linux-gnu \ gcc-sparc64-linux-gnu \ libc6-dev-sparc64-cross \ bzip2 \ @@ -46,6 +47,7 @@ ENV TARGETS=$TARGETS,mipsel-unknown-linux-musl ENV TARGETS=$TARGETS,arm-unknown-linux-musleabi ENV TARGETS=$TARGETS,arm-unknown-linux-musleabihf ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabihf +ENV TARGETS=$TARGETS,aarch64-unknown-linux-musl ENV TARGETS=$TARGETS,sparc64-unknown-linux-gnu ENV TARGETS=$TARGETS,x86_64-unknown-redox @@ -62,7 +64,8 @@ ENV RUST_CONFIGURE_ARGS \ --target=$TARGETS \ --musl-root-arm=/usr/local/arm-linux-musleabi \ --musl-root-armhf=/usr/local/arm-linux-musleabihf \ - --musl-root-armv7=/usr/local/armv7-linux-musleabihf + --musl-root-armv7=/usr/local/armv7-linux-musleabihf \ + --musl-root-aarch64=/usr/local/aarch64-linux-musl ENV SCRIPT python2.7 ../x.py dist --target $TARGETS # sccache diff --git a/src/ci/docker/cross/build-arm-musl.sh b/src/ci/docker/cross/build-arm-musl.sh index 938e69834e4..780099e2ec1 100755 --- a/src/ci/docker/cross/build-arm-musl.sh +++ b/src/ci/docker/cross/build-arm-musl.sh @@ -65,11 +65,24 @@ CFLAGS="-march=armv7-a" \ hide_output make -j$(nproc) hide_output make install cd .. +rm -rf musl-$MUSL + +tar xf musl-$MUSL.tar.gz +cd musl-$MUSL +CC=aarch64-linux-gnu-gcc \ +CFLAGS="" \ + hide_output ./configure \ + --prefix=/usr/local/aarch64-linux-musl \ + --enable-wrapper=gcc +hide_output make -j$(nproc) +hide_output make install +cd .. rm -rf musl-$MUSL* ln -nsf ../arm-linux-musleabi/bin/musl-gcc /usr/local/bin/arm-linux-musleabi-gcc ln -nsf ../arm-linux-musleabihf/bin/musl-gcc /usr/local/bin/arm-linux-musleabihf-gcc ln -nsf ../armv7-linux-musleabihf/bin/musl-gcc /usr/local/bin/armv7-linux-musleabihf-gcc +ln -nsf ../aarch64-linux-musl/bin/musl-gcc /usr/local/bin/aarch64-unknown-linux-musl-gcc curl -L https://github.com/llvm-mirror/llvm/archive/release_39.tar.gz | tar xzf - curl -L https://github.com/llvm-mirror/libunwind/archive/release_39.tar.gz | tar xzf - @@ -116,5 +129,19 @@ cp lib/libunwind.a /usr/local/armv7-linux-musleabihf/lib cd .. rm -rf libunwind-build +mkdir libunwind-build +cd libunwind-build +cmake ../libunwind-release_39 \ + -DLLVM_PATH=/tmp/llvm-release_39 \ + -DLIBUNWIND_ENABLE_SHARED=0 \ + -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc \ + -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ \ + -DCMAKE_C_FLAGS="" \ + -DCMAKE_CXX_FLAGS="" +make -j$(nproc) +cp lib/libunwind.a /usr/local/aarch64-linux-musl/lib +cd .. +rm -rf libunwind-build + rm -rf libunwind-release_39 rm -rf llvm-release_39 diff --git a/src/ci/docker/disabled/aarch64-gnu/Dockerfile b/src/ci/docker/disabled/aarch64-gnu/Dockerfile index 9a0e4531223..fedb4094c8a 100644 --- a/src/ci/docker/disabled/aarch64-gnu/Dockerfile +++ b/src/ci/docker/disabled/aarch64-gnu/Dockerfile @@ -31,7 +31,7 @@ WORKDIR /build # The `config` config file was a previously generated config file for # the kernel. This file was generated by running `make defconfig` # followed by `make menuconfig` and then enabling the IPv6 protocol page. -COPY disabled/aarch64-gnu/config /build/.config +COPY aarch64-gnu/config /build/.config RUN curl https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.4.42.tar.xz | \ tar xJf - && \ cd /build/linux-4.4.42 && \ diff --git a/src/ci/docker/disabled/wasm32-exp/Dockerfile b/src/ci/docker/disabled/wasm32-exp/Dockerfile index 6323369421b..8653b0e8b46 100644 --- a/src/ci/docker/disabled/wasm32-exp/Dockerfile +++ b/src/ci/docker/disabled/wasm32-exp/Dockerfile @@ -17,7 +17,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ # emscripten COPY scripts/emscripten-wasm.sh /scripts/ -COPY disabled/wasm32-exp/node.sh /usr/local/bin/node +COPY wasm32-exp/node.sh /usr/local/bin/node RUN bash /scripts/emscripten-wasm.sh # cache diff --git a/src/ci/docker/dist-fuchsia/Dockerfile b/src/ci/docker/dist-fuchsia/Dockerfile index e18cb453baf..bcd95924b42 100644 --- a/src/ci/docker/dist-fuchsia/Dockerfile +++ b/src/ci/docker/dist-fuchsia/Dockerfile @@ -1,27 +1,26 @@ FROM ubuntu:16.04 -RUN apt-get update && apt-get install -y --no-install-recommends \ +RUN apt-get update && apt-get build-dep -y clang llvm && apt-get install -y \ + build-essential \ + bzip2 \ + ca-certificates \ + cmake \ + curl \ + file \ g++ \ + gdb \ + git \ + libedit-dev \ make \ ninja-build \ - file \ - curl \ - ca-certificates \ + nodejs \ python2.7-dev \ - git \ sudo \ - bzip2 \ xz-utils \ - swig \ - libedit-dev \ - libncurses5-dev \ - patch - -RUN curl -L https://cmake.org/files/v3.8/cmake-3.8.0-rc1-Linux-x86_64.tar.gz | \ - tar xzf - -C /usr/local --strip-components=1 + unzip WORKDIR /tmp -COPY dist-fuchsia/shared.sh dist-fuchsia/build-toolchain.sh dist-fuchsia/compiler-rt-dso-handle.patch /tmp/ +COPY dist-fuchsia/shared.sh dist-fuchsia/build-toolchain.sh /tmp/ RUN /tmp/build-toolchain.sh COPY scripts/sccache.sh /scripts/ @@ -39,4 +38,4 @@ ENV TARGETS=x86_64-unknown-fuchsia ENV TARGETS=$TARGETS,aarch64-unknown-fuchsia ENV RUST_CONFIGURE_ARGS --target=$TARGETS --enable-extended -ENV SCRIPT python2.7 ../x.py dist --target $TARGETS +ENV SCRIPT python2.7 ../x.py dist --target $TARGETS \ No newline at end of file diff --git a/src/ci/docker/dist-fuchsia/build-toolchain.sh b/src/ci/docker/dist-fuchsia/build-toolchain.sh index 10b285a5466..756013a235c 100755 --- a/src/ci/docker/dist-fuchsia/build-toolchain.sh +++ b/src/ci/docker/dist-fuchsia/build-toolchain.sh @@ -14,105 +14,44 @@ set -ex source shared.sh -# Download sources -SRCS=( - "https://fuchsia.googlesource.com/magenta magenta d17073dc8de344ead3b65e8cc6a12280dec38c84" - "https://llvm.googlesource.com/llvm llvm 3f58a16d8eec385e2b3ebdfbb84ff9d3bf27e025" - "https://llvm.googlesource.com/clang llvm/tools/clang 727ea63e6e82677f6e10e05e08bc7d6bdbae3111" - "https://llvm.googlesource.com/lld llvm/tools/lld a31286c1366e5e89b8872803fded13805a1a084b" - "https://llvm.googlesource.com/lldb llvm/tools/lldb 0b2384abec4cb99ad66687712e07dee4dd9d187e" - "https://llvm.googlesource.com/compiler-rt llvm/runtimes/compiler-rt 9093a35c599fe41278606a20b51095ea8bd5a081" - "https://llvm.googlesource.com/libcxx llvm/runtimes/libcxx 607e0c71ec4f7fd377ad3f6c47b08dbe89f66eaa" - "https://llvm.googlesource.com/libcxxabi llvm/runtimes/libcxxabi 0a3a1a8a5ca5ef69e0f6b7d5b9d13e63e6fd2c19" - "https://llvm.googlesource.com/libunwind llvm/runtimes/libunwind e128003563d99d9ee62247c4cee40f07d21c03e3" -) - -fetch() { - mkdir -p $2 - pushd $2 > /dev/null - git init - git remote add origin $1 - git fetch --depth=1 origin $3 - git reset --hard FETCH_HEAD - popd > /dev/null -} +ZIRCON=e9a26dbc70d631029f8ee9763103910b7e3a2fe1 -for i in "${SRCS[@]}"; do - fetch $i -done +mkdir -p zircon +pushd zircon > /dev/null -# Remove this once https://reviews.llvm.org/D28791 is resolved -cd llvm/runtimes/compiler-rt -patch -Np1 < /tmp/compiler-rt-dso-handle.patch -cd ../../.. +# Download sources +git init +git remote add origin https://fuchsia.googlesource.com/zircon +git fetch --depth=1 origin $ZIRCON +git reset --hard FETCH_HEAD -# Build toolchain -cd llvm -mkdir build -cd build -hide_output cmake -GNinja \ - -DFUCHSIA_SYSROOT=${PWD}/../../magenta/third_party/ulib/musl \ - -DLLVM_ENABLE_LTO=OFF \ - -DCLANG_BOOTSTRAP_PASSTHROUGH=LLVM_ENABLE_LTO \ - -C ../tools/clang/cmake/caches/Fuchsia.cmake \ - .. -hide_output ninja stage2-distribution -hide_output ninja stage2-install-distribution -cd ../.. +# Download toolchain +./scripts/download-toolchain +chmod -R a+rx prebuilt/downloads/clang+llvm-x86_64-linux +cp -a prebuilt/downloads/clang+llvm-x86_64-linux/. /usr/local -# Build sysroot -rm -rf llvm/runtimes/compiler-rt -./magenta/scripts/download-toolchain - -build_sysroot() { +build() { local arch="$1" case "${arch}" in - x86_64) tgt="magenta-pc-x86-64" ;; - aarch64) tgt="magenta-qemu-arm64" ;; + x86_64) tgt="zircon-pc-x86-64" ;; + aarch64) tgt="zircon-qemu-arm64" ;; esac - hide_output make -C magenta -j$(getconf _NPROCESSORS_ONLN) $tgt + hide_output make -j$(getconf _NPROCESSORS_ONLN) $tgt dst=/usr/local/${arch}-unknown-fuchsia mkdir -p $dst - cp -r magenta/build-${tgt}/sysroot/include $dst/ - cp -r magenta/build-${tgt}/sysroot/lib $dst/ - - cd llvm - mkdir build-runtimes-${arch} - cd build-runtimes-${arch} - hide_output cmake -GNinja \ - -DCMAKE_C_COMPILER=clang \ - -DCMAKE_CXX_COMPILER=clang++ \ - -DCMAKE_AR=/usr/local/bin/llvm-ar \ - -DCMAKE_RANLIB=/usr/local/bin/llvm-ranlib \ - -DCMAKE_INSTALL_PREFIX= \ - -DLLVM_MAIN_SRC_DIR=${PWD}/.. \ - -DLLVM_BINARY_DIR=${PWD}/../build \ - -DLLVM_ENABLE_WERROR=OFF \ - -DCMAKE_BUILD_TYPE=Release \ - -DLLVM_INCLUDE_TESTS=ON \ - -DCMAKE_SYSTEM_NAME=Fuchsia \ - -DCMAKE_C_COMPILER_TARGET=${arch}-fuchsia \ - -DCMAKE_CXX_COMPILER_TARGET=${arch}-fuchsia \ - -DUNIX=1 \ - -DLIBCXX_HAS_MUSL_LIBC=ON \ - -DLIBCXXABI_USE_LLVM_UNWINDER=ON \ - -DCMAKE_SYSROOT=${dst} \ - -DCMAKE_C_COMPILER_FORCED=TRUE \ - -DCMAKE_CXX_COMPILER_FORCED=TRUE \ - -DLLVM_ENABLE_LIBCXX=ON \ - -DCMAKE_EXE_LINKER_FLAGS="-nodefaultlibs -lc" \ - -DCMAKE_SHARED_LINKER_FLAGS="$(clang --target=${arch}-fuchsia -print-libgcc-file-name)" \ - ../runtimes - hide_output env DESTDIR="${dst}" ninja install - cd ../.. + cp -a build-${tgt}/sysroot/include $dst/ + cp -a build-${tgt}/sysroot/lib $dst/ } -build_sysroot "x86_64" -build_sysroot "aarch64" +# Build sysroot +for arch in x86_64 aarch64; do + build ${arch} +done -rm -rf magenta llvm +popd > /dev/null +rm -rf zircon for arch in x86_64 aarch64; do for tool in clang clang++; do diff --git a/src/ci/docker/dist-fuchsia/compiler-rt-dso-handle.patch b/src/ci/docker/dist-fuchsia/compiler-rt-dso-handle.patch deleted file mode 100644 index 0b702894bb2..00000000000 --- a/src/ci/docker/dist-fuchsia/compiler-rt-dso-handle.patch +++ /dev/null @@ -1,41 +0,0 @@ -diff --git a/lib/builtins/CMakeLists.txt b/lib/builtins/CMakeLists.txt -index fc4384af2..b442264c0 100644 ---- a/lib/builtins/CMakeLists.txt -+++ b/lib/builtins/CMakeLists.txt -@@ -194,6 +194,12 @@ if(APPLE) - atomic_thread_fence.c) - endif() - -+if(FUCHSIA) -+ set(GENERIC_SOURCES -+ ${GENERIC_SOURCES} -+ dso_handle.c) -+endif() -+ - if(NOT WIN32 OR MINGW) - set(GENERIC_SOURCES - ${GENERIC_SOURCES} -diff --git a/lib/builtins/dso_handle.c b/lib/builtins/dso_handle.c -new file mode 100644 -index 000000000..7766cd0aa ---- /dev/null -+++ b/lib/builtins/dso_handle.c -@@ -0,0 +1,18 @@ -+/* ===-- dso_handle.c - Provide __dso_handle -------------------------------=== -+ * -+ * The LLVM Compiler Infrastructure -+ * -+ * This file is dual licensed under the MIT and the University of Illinois Open -+ * Source Licenses. See LICENSE.TXT for details. -+ * -+ * ===----------------------------------------------------------------------=== -+ */ -+ -+/* __dso_handle symbol is mandated by C++ ABI with a value which is an address -+ * in one of the object's segments, and as such this symbol has to be included -+ * statically and cannot be a part of a shared library. Traditionally, it has -+ * been defined in crtbegin.o but there's no principled reason for it to be -+ * there. We defined this symbol in the builtin library which is built as a -+ * static library and always included in the final link. -+ */ -+__attribute__((visibility("hidden"))) void *const __dso_handle; diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index 7087033e117..b2560c6b95b 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -36,12 +36,14 @@ elif [ -f "$docker_dir/disabled/$image/Dockerfile" ]; then echo Cannot run disabled images on travis! exit 1 fi - retry docker \ + # retry messes with the pipe from tar to docker. Not needed on non-travis + # Transform changes the context of disabled Dockerfiles to match the enabled ones + tar --transform 's#^./disabled/#./#' -C $docker_dir -c . | docker \ build \ --rm \ -t rust-ci \ - -f "$docker_dir/disabled/$image/Dockerfile" \ - "$docker_dir" + -f "$image/Dockerfile" \ + - else echo Invalid image: $image exit 1 diff --git a/src/doc/unstable-book/src/language-features/inclusive-range-syntax.md b/src/doc/unstable-book/src/language-features/inclusive-range-syntax.md index 255445c318d..56f58803150 100644 --- a/src/doc/unstable-book/src/language-features/inclusive-range-syntax.md +++ b/src/doc/unstable-book/src/language-features/inclusive-range-syntax.md @@ -7,13 +7,13 @@ The tracking issue for this feature is: [#28237] ------------------------ To get a range that goes from 0 to 10 and includes the value 10, you -can write `0...10`: +can write `0..=10`: ```rust #![feature(inclusive_range_syntax)] fn main() { - for i in 0...10 { + for i in 0..=10 { println!("{}", i); } } diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 4b695ad7c79..3b7dbd813cf 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -72,13 +72,13 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// first: after all, isn't the point of `Arc<T>` thread safety? The key is /// this: `Arc<T>` makes it thread safe to have multiple ownership of the same /// data, but it doesn't add thread safety to its data. Consider -/// `Arc<RefCell<T>>`. `RefCell<T>` isn't [`Sync`], and if `Arc<T>` was always -/// [`Send`], `Arc<RefCell<T>>` would be as well. But then we'd have a problem: -/// `RefCell<T>` is not thread safe; it keeps track of the borrowing count using +/// `Arc<`[`RefCell<T>`]`>`. [`RefCell<T>`] isn't [`Sync`], and if `Arc<T>` was always +/// [`Send`], `Arc<`[`RefCell<T>`]`>` would be as well. But then we'd have a problem: +/// [`RefCell<T>`] is not thread safe; it keeps track of the borrowing count using /// non-atomic operations. /// /// In the end, this means that you may need to pair `Arc<T>` with some sort of -/// `std::sync` type, usually `Mutex<T>`. +/// [`std::sync`] type, usually [`Mutex<T>`][mutex]. /// /// ## Breaking cycles with `Weak` /// @@ -106,7 +106,7 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// // a and b both point to the same memory location as foo. /// ``` /// -/// The `Arc::clone(&from)` syntax is the most idiomatic because it conveys more explicitly +/// The [`Arc::clone(&from)`] syntax is the most idiomatic because it conveys more explicitly /// the meaning of the code. In the example above, this syntax makes it easier to see that /// this code is creating a new reference rather than copying the whole content of foo. /// @@ -141,6 +141,9 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// [upgrade]: struct.Weak.html#method.upgrade /// [`None`]: ../../std/option/enum.Option.html#variant.None /// [assoc]: ../../book/first-edition/method-syntax.html#associated-functions +/// [`RefCell<T>`]: ../../std/cell/struct.RefCell.html +/// [`std::sync`]: ../../std/sync/index.html +/// [`Arc::clone(&from)`]: #method.clone /// /// # Examples /// diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 2845d349ae1..d51aaa23c6a 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -98,6 +98,7 @@ #![feature(generic_param_attrs)] #![feature(i128_type)] #![feature(inclusive_range)] +#![feature(iter_rfold)] #![feature(lang_items)] #![feature(needs_allocator)] #![feature(nonzero)] diff --git a/src/liballoc/tests/btree/map.rs b/src/liballoc/tests/btree/map.rs index 2c899d96940..2393101040d 100644 --- a/src/liballoc/tests/btree/map.rs +++ b/src/liballoc/tests/btree/map.rs @@ -182,7 +182,7 @@ fn test_range_small() { fn test_range_inclusive() { let size = 500; - let map: BTreeMap<_, _> = (0...size).map(|i| (i, i)).collect(); + let map: BTreeMap<_, _> = (0..=size).map(|i| (i, i)).collect(); fn check<'a, L, R>(lhs: L, rhs: R) where L: IntoIterator<Item=(&'a i32, &'a i32)>, @@ -193,18 +193,18 @@ fn test_range_inclusive() { assert_eq!(lhs, rhs); } - check(map.range(size + 1...size + 1), vec![]); - check(map.range(size...size), vec![(&size, &size)]); - check(map.range(size...size + 1), vec![(&size, &size)]); - check(map.range(0...0), vec![(&0, &0)]); - check(map.range(0...size - 1), map.range(..size)); - check(map.range(-1...-1), vec![]); - check(map.range(-1...size), map.range(..)); - check(map.range(...size), map.range(..)); - check(map.range(...200), map.range(..201)); - check(map.range(5...8), vec![(&5, &5), (&6, &6), (&7, &7), (&8, &8)]); - check(map.range(-1...0), vec![(&0, &0)]); - check(map.range(-1...2), vec![(&0, &0), (&1, &1), (&2, &2)]); + check(map.range(size + 1..=size + 1), vec![]); + check(map.range(size..=size), vec![(&size, &size)]); + check(map.range(size..=size + 1), vec![(&size, &size)]); + check(map.range(0..=0), vec![(&0, &0)]); + check(map.range(0..=size - 1), map.range(..size)); + check(map.range(-1..=-1), vec![]); + check(map.range(-1..=size), map.range(..)); + check(map.range(..=size), map.range(..)); + check(map.range(..=200), map.range(..201)); + check(map.range(5..=8), vec![(&5, &5), (&6, &6), (&7, &7), (&8, &8)]); + check(map.range(-1..=0), vec![(&0, &0)]); + check(map.range(-1..=2), vec![(&0, &0), (&1, &1), (&2, &2)]); } #[test] @@ -212,7 +212,7 @@ fn test_range_inclusive_max_value() { let max = ::std::usize::MAX; let map: BTreeMap<_, _> = vec![(max, 0)].into_iter().collect(); - assert_eq!(map.range(max...max).collect::<Vec<_>>(), &[(&max, &0)]); + assert_eq!(map.range(max..=max).collect::<Vec<_>>(), &[(&max, &0)]); } #[test] diff --git a/src/liballoc/tests/str.rs b/src/liballoc/tests/str.rs index 9d8ca38b20e..b3178064505 100644 --- a/src/liballoc/tests/str.rs +++ b/src/liballoc/tests/str.rs @@ -361,13 +361,13 @@ fn test_slice_fail() { #[test] #[should_panic] fn test_str_slice_rangetoinclusive_max_panics() { - &"hello"[...usize::max_value()]; + &"hello"[..=usize::max_value()]; } #[test] #[should_panic] fn test_str_slice_rangeinclusive_max_panics() { - &"hello"[1...usize::max_value()]; + &"hello"[1..=usize::max_value()]; } #[test] @@ -375,7 +375,7 @@ fn test_str_slice_rangeinclusive_max_panics() { fn test_str_slicemut_rangetoinclusive_max_panics() { let mut s = "hello".to_owned(); let s: &mut str = &mut s; - &mut s[...usize::max_value()]; + &mut s[..=usize::max_value()]; } #[test] @@ -383,7 +383,7 @@ fn test_str_slicemut_rangetoinclusive_max_panics() { fn test_str_slicemut_rangeinclusive_max_panics() { let mut s = "hello".to_owned(); let s: &mut str = &mut s; - &mut s[1...usize::max_value()]; + &mut s[1..=usize::max_value()]; } #[test] @@ -391,13 +391,13 @@ fn test_str_get_maxinclusive() { let mut s = "hello".to_owned(); { let s: &str = &s; - assert_eq!(s.get(...usize::max_value()), None); - assert_eq!(s.get(1...usize::max_value()), None); + assert_eq!(s.get(..=usize::max_value()), None); + assert_eq!(s.get(1..=usize::max_value()), None); } { let s: &mut str = &mut s; - assert_eq!(s.get(...usize::max_value()), None); - assert_eq!(s.get(1...usize::max_value()), None); + assert_eq!(s.get(..=usize::max_value()), None); + assert_eq!(s.get(1..=usize::max_value()), None); } } diff --git a/src/liballoc/tests/string.rs b/src/liballoc/tests/string.rs index 6aba18ddf49..ef6f5e10a72 100644 --- a/src/liballoc/tests/string.rs +++ b/src/liballoc/tests/string.rs @@ -456,9 +456,9 @@ fn test_splice_char_boundary() { #[test] fn test_splice_inclusive_range() { let mut v = String::from("12345"); - v.splice(2...3, "789"); + v.splice(2..=3, "789"); assert_eq!(v, "127895"); - v.splice(1...2, "A"); + v.splice(1..=2, "A"); assert_eq!(v, "1A895"); } @@ -473,7 +473,7 @@ fn test_splice_out_of_bounds() { #[should_panic] fn test_splice_inclusive_out_of_bounds() { let mut s = String::from("12345"); - s.splice(5...5, "789"); + s.splice(5..=5, "789"); } #[test] diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs index 670ea8089fc..0e25da5bd30 100644 --- a/src/liballoc/tests/vec.rs +++ b/src/liballoc/tests/vec.rs @@ -537,27 +537,27 @@ fn test_drain_range() { #[test] fn test_drain_inclusive_range() { let mut v = vec!['a', 'b', 'c', 'd', 'e']; - for _ in v.drain(1...3) { + for _ in v.drain(1..=3) { } assert_eq!(v, &['a', 'e']); - let mut v: Vec<_> = (0...5).map(|x| x.to_string()).collect(); - for _ in v.drain(1...5) { + let mut v: Vec<_> = (0..=5).map(|x| x.to_string()).collect(); + for _ in v.drain(1..=5) { } assert_eq!(v, &["0".to_string()]); - let mut v: Vec<String> = (0...5).map(|x| x.to_string()).collect(); - for _ in v.drain(0...5) { + let mut v: Vec<String> = (0..=5).map(|x| x.to_string()).collect(); + for _ in v.drain(0..=5) { } assert_eq!(v, Vec::<String>::new()); - let mut v: Vec<_> = (0...5).map(|x| x.to_string()).collect(); - for _ in v.drain(0...3) { + let mut v: Vec<_> = (0..=5).map(|x| x.to_string()).collect(); + for _ in v.drain(0..=3) { } assert_eq!(v, &["4".to_string(), "5".to_string()]); - let mut v: Vec<_> = (0...1).map(|x| x.to_string()).collect(); - for _ in v.drain(...0) { + let mut v: Vec<_> = (0..=1).map(|x| x.to_string()).collect(); + for _ in v.drain(..=0) { } assert_eq!(v, &["1".to_string()]); } @@ -572,7 +572,7 @@ fn test_drain_max_vec_size() { let mut v = Vec::<()>::with_capacity(usize::max_value()); unsafe { v.set_len(usize::max_value()); } - for _ in v.drain(usize::max_value() - 1...usize::max_value() - 1) { + for _ in v.drain(usize::max_value() - 1..=usize::max_value() - 1) { } assert_eq!(v.len(), usize::max_value() - 1); } @@ -581,7 +581,7 @@ fn test_drain_max_vec_size() { #[should_panic] fn test_drain_inclusive_out_of_bounds() { let mut v = vec![1, 2, 3, 4, 5]; - v.drain(5...5); + v.drain(5..=5); } #[test] @@ -598,10 +598,10 @@ fn test_splice() { fn test_splice_inclusive_range() { let mut v = vec![1, 2, 3, 4, 5]; let a = [10, 11, 12]; - let t1: Vec<_> = v.splice(2...3, a.iter().cloned()).collect(); + let t1: Vec<_> = v.splice(2..=3, a.iter().cloned()).collect(); assert_eq!(v, &[1, 2, 10, 11, 12, 5]); assert_eq!(t1, &[3, 4]); - let t2: Vec<_> = v.splice(1...2, Some(20)).collect(); + let t2: Vec<_> = v.splice(1..=2, Some(20)).collect(); assert_eq!(v, &[1, 20, 11, 12, 5]); assert_eq!(t2, &[2, 10]); } @@ -619,7 +619,7 @@ fn test_splice_out_of_bounds() { fn test_splice_inclusive_out_of_bounds() { let mut v = vec![1, 2, 3, 4, 5]; let a = [10, 11, 12]; - v.splice(5...5, a.iter().cloned()); + v.splice(5..=5, a.iter().cloned()); } #[test] diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 7dd8895c1ae..725d3e15f4a 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -1950,7 +1950,7 @@ impl<T> Vec<T> { /// assert_eq!(u, &[1, 2]); /// ``` #[inline] - #[stable(feature = "vec_splice", since = "1.22.0")] + #[stable(feature = "vec_splice", since = "1.21.0")] pub fn splice<R, I>(&mut self, range: R, replace_with: I) -> Splice<I::IntoIter> where R: RangeArgument<usize>, I: IntoIterator<Item=T> { @@ -2553,13 +2553,13 @@ impl<'a, T> InPlace<T> for PlaceBack<'a, T> { /// [`splice()`]: struct.Vec.html#method.splice /// [`Vec`]: struct.Vec.html #[derive(Debug)] -#[stable(feature = "vec_splice", since = "1.22.0")] +#[stable(feature = "vec_splice", since = "1.21.0")] pub struct Splice<'a, I: Iterator + 'a> { drain: Drain<'a, I::Item>, replace_with: I, } -#[stable(feature = "vec_splice", since = "1.22.0")] +#[stable(feature = "vec_splice", since = "1.21.0")] impl<'a, I: Iterator> Iterator for Splice<'a, I> { type Item = I::Item; @@ -2572,18 +2572,18 @@ impl<'a, I: Iterator> Iterator for Splice<'a, I> { } } -#[stable(feature = "vec_splice", since = "1.22.0")] +#[stable(feature = "vec_splice", since = "1.21.0")] impl<'a, I: Iterator> DoubleEndedIterator for Splice<'a, I> { fn next_back(&mut self) -> Option<Self::Item> { self.drain.next_back() } } -#[stable(feature = "vec_splice", since = "1.22.0")] +#[stable(feature = "vec_splice", since = "1.21.0")] impl<'a, I: Iterator> ExactSizeIterator for Splice<'a, I> {} -#[stable(feature = "vec_splice", since = "1.22.0")] +#[stable(feature = "vec_splice", since = "1.21.0")] impl<'a, I: Iterator> Drop for Splice<'a, I> { fn drop(&mut self) { // exhaust drain first diff --git a/src/liballoc/vec_deque.rs b/src/liballoc/vec_deque.rs index 00def2a1eac..6d64e9e303f 100644 --- a/src/liballoc/vec_deque.rs +++ b/src/liballoc/vec_deque.rs @@ -558,7 +558,7 @@ impl<T> VecDeque<T> { .and_then(|needed_cap| needed_cap.checked_next_power_of_two()) .expect("capacity overflow"); - if new_cap > self.capacity() { + if new_cap > old_cap { self.buf.reserve_exact(used_cap, new_cap - used_cap); unsafe { self.handle_cap_increase(old_cap); @@ -1973,6 +1973,14 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> { self.head = wrap_index(self.head.wrapping_sub(1), self.ring.len()); unsafe { Some(self.ring.get_unchecked(self.head)) } } + + fn rfold<Acc, F>(self, mut accum: Acc, mut f: F) -> Acc + where F: FnMut(Acc, Self::Item) -> Acc + { + let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail); + accum = back.iter().rfold(accum, &mut f); + front.iter().rfold(accum, &mut f) + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -2058,6 +2066,14 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { Some(&mut *(elem as *mut _)) } } + + fn rfold<Acc, F>(self, mut accum: Acc, mut f: F) -> Acc + where F: FnMut(Acc, Self::Item) -> Acc + { + let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail); + accum = back.iter_mut().rfold(accum, &mut f); + front.iter_mut().rfold(accum, &mut f) + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/liballoc_jemalloc/Cargo.toml b/src/liballoc_jemalloc/Cargo.toml index 94700cf4475..4042c4d2d4e 100644 --- a/src/liballoc_jemalloc/Cargo.toml +++ b/src/liballoc_jemalloc/Cargo.toml @@ -19,7 +19,7 @@ libc = { path = "../rustc/libc_shim" } [build-dependencies] build_helper = { path = "../build_helper" } -gcc = "0.3.50" +cc = "1.0" [features] debug = [] diff --git a/src/liballoc_jemalloc/build.rs b/src/liballoc_jemalloc/build.rs index d89d3bcdb62..7dd85ddcc79 100644 --- a/src/liballoc_jemalloc/build.rs +++ b/src/liballoc_jemalloc/build.rs @@ -11,7 +11,7 @@ #![deny(warnings)] extern crate build_helper; -extern crate gcc; +extern crate cc; use std::env; use std::path::PathBuf; @@ -63,7 +63,7 @@ fn main() { _ => return, }; - let compiler = gcc::Build::new().get_compiler(); + let compiler = cc::Build::new().get_compiler(); // only msvc returns None for ar so unwrap is okay let ar = build_helper::cc2ar(compiler.path(), &target).unwrap(); let cflags = compiler.args() @@ -150,7 +150,7 @@ fn main() { // sure the symbols are available. if target.contains("androideabi") { println!("cargo:rerun-if-changed=pthread_atfork_dummy.c"); - gcc::Build::new() + cc::Build::new() .flag("-fvisibility=hidden") .file("pthread_atfork_dummy.c") .compile("libpthread_atfork_dummy.a"); diff --git a/src/libcore/benches/iter.rs b/src/libcore/benches/iter.rs index 827c6354c60..1f16f5b1df3 100644 --- a/src/libcore/benches/iter.rs +++ b/src/libcore/benches/iter.rs @@ -147,40 +147,131 @@ fn bench_for_each_chain_ref_fold(b: &mut Bencher) { }); } -#[bench] -fn bench_flat_map_sum(b: &mut Bencher) { - b.iter(|| -> i64 { - (0i64..1000).flat_map(|x| x..x+1000) - .map(black_box) - .sum() - }); + +/// Helper to benchmark `sum` for iterators taken by value which +/// can optimize `fold`, and by reference which cannot. +macro_rules! bench_sums { + ($bench_sum:ident, $bench_ref_sum:ident, $iter:expr) => { + #[bench] + fn $bench_sum(b: &mut Bencher) { + b.iter(|| -> i64 { + $iter.map(black_box).sum() + }); + } + + #[bench] + fn $bench_ref_sum(b: &mut Bencher) { + b.iter(|| -> i64 { + $iter.map(black_box).by_ref().sum() + }); + } + } } -#[bench] -fn bench_flat_map_ref_sum(b: &mut Bencher) { - b.iter(|| -> i64 { - (0i64..1000).flat_map(|x| x..x+1000) - .map(black_box) - .by_ref() - .sum() - }); +bench_sums! { + bench_flat_map_sum, + bench_flat_map_ref_sum, + (0i64..1000).flat_map(|x| x..x+1000) } -#[bench] -fn bench_flat_map_chain_sum(b: &mut Bencher) { - b.iter(|| -> i64 { - (0i64..1000000).flat_map(|x| once(x).chain(once(x))) - .map(black_box) - .sum() - }); +bench_sums! { + bench_flat_map_chain_sum, + bench_flat_map_chain_ref_sum, + (0i64..1000000).flat_map(|x| once(x).chain(once(x))) } -#[bench] -fn bench_flat_map_chain_ref_sum(b: &mut Bencher) { - b.iter(|| -> i64 { - (0i64..1000000).flat_map(|x| once(x).chain(once(x))) - .map(black_box) - .by_ref() - .sum() - }); +bench_sums! { + bench_enumerate_sum, + bench_enumerate_ref_sum, + (0i64..1000000).enumerate().map(|(i, x)| x * i as i64) +} + +bench_sums! { + bench_enumerate_chain_sum, + bench_enumerate_chain_ref_sum, + (0i64..1000000).chain(0..1000000).enumerate().map(|(i, x)| x * i as i64) +} + +bench_sums! { + bench_filter_sum, + bench_filter_ref_sum, + (0i64..1000000).filter(|x| x % 2 == 0) +} + +bench_sums! { + bench_filter_chain_sum, + bench_filter_chain_ref_sum, + (0i64..1000000).chain(0..1000000).filter(|x| x % 2 == 0) +} + +bench_sums! { + bench_filter_map_sum, + bench_filter_map_ref_sum, + (0i64..1000000).filter_map(|x| x.checked_mul(x)) +} + +bench_sums! { + bench_filter_map_chain_sum, + bench_filter_map_chain_ref_sum, + (0i64..1000000).chain(0..1000000).filter_map(|x| x.checked_mul(x)) +} + +bench_sums! { + bench_fuse_sum, + bench_fuse_ref_sum, + (0i64..1000000).fuse() +} + +bench_sums! { + bench_fuse_chain_sum, + bench_fuse_chain_ref_sum, + (0i64..1000000).chain(0..1000000).fuse() +} + +bench_sums! { + bench_inspect_sum, + bench_inspect_ref_sum, + (0i64..1000000).inspect(|_| {}) +} + +bench_sums! { + bench_inspect_chain_sum, + bench_inspect_chain_ref_sum, + (0i64..1000000).chain(0..1000000).inspect(|_| {}) +} + +bench_sums! { + bench_peekable_sum, + bench_peekable_ref_sum, + (0i64..1000000).peekable() +} + +bench_sums! { + bench_peekable_chain_sum, + bench_peekable_chain_ref_sum, + (0i64..1000000).chain(0..1000000).peekable() +} + +bench_sums! { + bench_skip_sum, + bench_skip_ref_sum, + (0i64..1000000).skip(1000) +} + +bench_sums! { + bench_skip_chain_sum, + bench_skip_chain_ref_sum, + (0i64..1000000).chain(0..1000000).skip(1000) +} + +bench_sums! { + bench_skip_while_sum, + bench_skip_while_ref_sum, + (0i64..1000000).skip_while(|&x| x < 1000) +} + +bench_sums! { + bench_skip_while_chain_sum, + bench_skip_while_chain_ref_sum, + (0i64..1000000).chain(0..1000000).skip_while(|&x| x < 1000) } diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 6f86f8caad0..e012cbd76ff 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -456,7 +456,7 @@ pub trait Ord: Eq + PartialOrd<Self> { /// assert_eq!(2, 1.max(2)); /// assert_eq!(2, 2.max(2)); /// ``` - #[stable(feature = "ord_max_min", since = "1.22.0")] + #[stable(feature = "ord_max_min", since = "1.21.0")] fn max(self, other: Self) -> Self where Self: Sized { if other >= self { other } else { self } @@ -472,7 +472,7 @@ pub trait Ord: Eq + PartialOrd<Self> { /// assert_eq!(1, 1.min(2)); /// assert_eq!(2, 2.min(2)); /// ``` - #[stable(feature = "ord_max_min", since = "1.22.0")] + #[stable(feature = "ord_max_min", since = "1.21.0")] fn min(self, other: Self) -> Self where Self: Sized { if self <= other { self } else { other } diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index 6f3c3863fae..e815d72d366 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -48,8 +48,25 @@ #![stable(feature = "rust1", since = "1.0.0")] -use str::FromStr; +use fmt; +/// A type used as the error type for implementations of fallible conversion +/// traits in cases where conversions cannot actually fail. +/// +/// Because `Infallible` has no variants, a value of this type can never exist. +/// It is used only to satisfy trait signatures that expect an error type, and +/// signals to both the compiler and the user that the error case is impossible. +#[unstable(feature = "try_from", issue = "33417")] +#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub enum Infallible {} + +#[unstable(feature = "try_from", issue = "33417")] +impl fmt::Display for Infallible { + fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result { + match *self { + } + } +} /// A cheap reference-to-reference conversion. Used to convert a value to a /// reference value within generic code. /// @@ -417,6 +434,17 @@ impl<T, U> TryInto<U> for T where U: TryFrom<T> } } +// Infallible conversions are semantically equivalent to fallible conversions +// with an uninhabited error type. +#[unstable(feature = "try_from", issue = "33417")] +impl<T, U> TryFrom<U> for T where T: From<U> { + type Error = Infallible; + + fn try_from(value: U) -> Result<Self, Self::Error> { + Ok(T::from(value)) + } +} + //////////////////////////////////////////////////////////////////////////////// // CONCRETE IMPLS //////////////////////////////////////////////////////////////////////////////// @@ -442,14 +470,3 @@ impl AsRef<str> for str { self } } - -// FromStr implies TryFrom<&str> -#[unstable(feature = "try_from", issue = "33417")] -impl<'a, T> TryFrom<&'a str> for T where T: FromStr -{ - type Error = <T as FromStr>::Err; - - fn try_from(s: &'a str) -> Result<T, Self::Error> { - FromStr::from_str(s) - } -} diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index cf6262bda97..6c251b9eb09 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -488,13 +488,14 @@ impl<'a> Display for Arguments<'a> { /// The origin is: Point { x: 0, y: 0 } /// ``` /// -/// There are a number of `debug_*` methods on `Formatter` to help you with manual +/// There are a number of `debug_*` methods on [`Formatter`] to help you with manual /// implementations, such as [`debug_struct`][debug_struct]. /// /// `Debug` implementations using either `derive` or the debug builder API -/// on `Formatter` support pretty printing using the alternate flag: `{:#?}`. +/// on [`Formatter`] support pretty printing using the alternate flag: `{:#?}`. /// /// [debug_struct]: ../../std/fmt/struct.Formatter.html#method.debug_struct +/// [`Formatter`]: ../../std/fmt/struct.Formatter.html /// /// Pretty printing with `#?`: /// @@ -1321,8 +1322,11 @@ impl<'a> Formatter<'a> { self.flags & (1 << FlagV1::SignAwareZeroPad as u32) != 0 } - /// Creates a `DebugStruct` builder designed to assist with creation of - /// `fmt::Debug` implementations for structs. + /// Creates a [`DebugStruct`] builder designed to assist with creation of + /// [`fmt::Debug`] implementations for structs. + /// + /// [`DebugStruct`]: ../../std/fmt/struct.DebugStruct.html + /// [`fmt::Debug`]: ../../std/fmt/trait.Debug.html /// /// # Examples /// @@ -1700,8 +1704,18 @@ impl<T: ?Sized + Debug> Debug for RefCell<T> { .finish() } Err(_) => { + // The RefCell is mutably borrowed so we can't look at its value + // here. Show a placeholder instead. + struct BorrowedPlaceholder; + + impl Debug for BorrowedPlaceholder { + fn fmt(&self, f: &mut Formatter) -> Result { + f.write_str("<borrowed>") + } + } + f.debug_struct("RefCell") - .field("value", &"<borrowed>") + .field("value", &BorrowedPlaceholder) .finish() } } diff --git a/src/libcore/internal_macros.rs b/src/libcore/internal_macros.rs index 9a7914064fd..cb215a38e53 100644 --- a/src/libcore/internal_macros.rs +++ b/src/libcore/internal_macros.rs @@ -68,3 +68,22 @@ macro_rules! forward_ref_binop { } } } + +// implements "T op= &U", based on "T op= U" +// where U is expected to be `Copy`able +macro_rules! forward_ref_op_assign { + (impl $imp:ident, $method:ident for $t:ty, $u:ty) => { + forward_ref_op_assign!(impl $imp, $method for $t, $u, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")]); + }; + (impl $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => { + #[$attr] + impl<'a> $imp<&'a $u> for $t { + #[inline] + fn $method(&mut self, other: &'a $u) { + $imp::$method(self, *other); + } + } + } +} + diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index edafd0ce2c2..e9e31065cf8 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -518,7 +518,7 @@ pub trait Iterator { /// .for_each(|(i, x)| println!("{}:{}", i, x)); /// ``` #[inline] - #[stable(feature = "iterator_for_each", since = "1.22.0")] + #[stable(feature = "iterator_for_each", since = "1.21.0")] fn for_each<F>(self, mut f: F) where Self: Sized, F: FnMut(Self::Item), { @@ -1337,7 +1337,7 @@ pub trait Iterator { (left, right) } - /// An iterator adaptor that applies a function, producing a single, final value. + /// An iterator method that applies a function, producing a single, final value. /// /// `fold()` takes two arguments: an initial value, and a closure with two /// arguments: an 'accumulator', and an element. The closure returns the value that diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index a596ffd6ae8..8d2521b053e 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -359,6 +359,12 @@ impl<I> Iterator for Rev<I> where I: DoubleEndedIterator { #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() } + fn fold<Acc, F>(self, init: Acc, f: F) -> Acc + where F: FnMut(Acc, Self::Item) -> Acc, + { + self.iter.rfold(init, f) + } + #[inline] fn find<P>(&mut self, predicate: P) -> Option<Self::Item> where P: FnMut(&Self::Item) -> bool @@ -379,6 +385,12 @@ impl<I> DoubleEndedIterator for Rev<I> where I: DoubleEndedIterator { #[inline] fn next_back(&mut self) -> Option<<I as Iterator>::Item> { self.iter.next() } + fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc + where F: FnMut(Acc, Self::Item) -> Acc, + { + self.iter.fold(init, f) + } + fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item> where P: FnMut(&Self::Item) -> bool { @@ -449,6 +461,12 @@ impl<'a, I, T: 'a> DoubleEndedIterator for Cloned<I> fn next_back(&mut self) -> Option<T> { self.it.next_back().cloned() } + + fn rfold<Acc, F>(self, init: Acc, mut f: F) -> Acc + where F: FnMut(Acc, Self::Item) -> Acc, + { + self.it.rfold(init, move |acc, elt| f(acc, elt.clone())) + } } #[stable(feature = "iter_cloned", since = "1.1.0")] @@ -470,7 +488,7 @@ impl<'a, I, T: 'a> FusedIterator for Cloned<I> {} #[doc(hidden)] -unsafe impl<'a, I, T: 'a> TrustedRandomAccess for Cloned<I> +default unsafe impl<'a, I, T: 'a> TrustedRandomAccess for Cloned<I> where I: TrustedRandomAccess<Item=&'a T>, T: Clone { unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item { @@ -481,6 +499,18 @@ unsafe impl<'a, I, T: 'a> TrustedRandomAccess for Cloned<I> fn may_have_side_effect() -> bool { true } } +#[doc(hidden)] +unsafe impl<'a, I, T: 'a> TrustedRandomAccess for Cloned<I> + where I: TrustedRandomAccess<Item=&'a T>, T: Copy +{ + unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item { + *self.it.get_unchecked(i) + } + + #[inline] + fn may_have_side_effect() -> bool { false } +} + #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl<'a, I, T: 'a> TrustedLen for Cloned<I> where I: TrustedLen<Item=&'a T>, @@ -528,7 +558,7 @@ impl<I> Iterator for Cycle<I> where I: Clone + Iterator { #[unstable(feature = "fused", issue = "35602")] impl<I> FusedIterator for Cycle<I> where I: Clone + Iterator {} -/// An adapter for stepping iterators by a custom amount. +/// An iterator for stepping iterators by a custom amount. /// /// This `struct` is created by the [`step_by`] method on [`Iterator`]. See /// its documentation for more. @@ -761,6 +791,26 @@ impl<A, B> DoubleEndedIterator for Chain<A, B> where ChainState::Back => self.b.next_back(), } } + + fn rfold<Acc, F>(self, init: Acc, mut f: F) -> Acc + where F: FnMut(Acc, Self::Item) -> Acc, + { + let mut accum = init; + match self.state { + ChainState::Both | ChainState::Back => { + accum = self.b.rfold(accum, &mut f); + } + _ => { } + } + match self.state { + ChainState::Both | ChainState::Front => { + accum = self.a.rfold(accum, &mut f); + } + _ => { } + } + accum + } + } // Note: *both* must be fused to handle double-ended iterators. @@ -1094,6 +1144,13 @@ impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for Map<I, F> where fn next_back(&mut self) -> Option<B> { self.iter.next_back().map(&mut self.f) } + + fn rfold<Acc, G>(self, init: Acc, mut g: G) -> Acc + where G: FnMut(Acc, Self::Item) -> Acc, + { + let mut f = self.f; + self.iter.rfold(init, move |acc, elt| g(acc, f(elt))) + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1193,6 +1250,18 @@ impl<I: Iterator, P> Iterator for Filter<I, P> where P: FnMut(&I::Item) -> bool } count } + + #[inline] + fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + let mut predicate = self.predicate; + self.iter.fold(init, move |acc, item| if predicate(&item) { + fold(acc, item) + } else { + acc + }) + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1208,6 +1277,18 @@ impl<I: DoubleEndedIterator, P> DoubleEndedIterator for Filter<I, P> } None } + + #[inline] + fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + let mut predicate = self.predicate; + self.iter.rfold(init, move |acc, item| if predicate(&item) { + fold(acc, item) + } else { + acc + }) + } } #[unstable(feature = "fused", issue = "35602")] @@ -1259,6 +1340,17 @@ impl<B, I: Iterator, F> Iterator for FilterMap<I, F> let (_, upper) = self.iter.size_hint(); (0, upper) // can't know a lower bound, due to the predicate } + + #[inline] + fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + let mut f = self.f; + self.iter.fold(init, move |acc, item| match f(item) { + Some(x) => fold(acc, x), + None => acc, + }) + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1274,6 +1366,17 @@ impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for FilterMap<I, F> } None } + + #[inline] + fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + let mut f = self.f; + self.iter.rfold(init, move |acc, item| match f(item) { + Some(x) => fold(acc, x), + None => acc, + }) + } } #[unstable(feature = "fused", issue = "35602")] @@ -1338,6 +1441,19 @@ impl<I> Iterator for Enumerate<I> where I: Iterator { fn count(self) -> usize { self.iter.count() } + + #[inline] + #[rustc_inherit_overflow_checks] + fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + let mut count = self.count; + self.iter.fold(init, move |acc, item| { + let acc = fold(acc, (count, item)); + count += 1; + acc + }) + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1353,6 +1469,19 @@ impl<I> DoubleEndedIterator for Enumerate<I> where (self.count + len, a) }) } + + #[inline] + fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + // Can safely add and subtract the count, as `ExactSizeIterator` promises + // that the number of elements fits into a `usize`. + let mut count = self.count + self.iter.len(); + self.iter.rfold(init, move |acc, item| { + count -= 1; + fold(acc, (count, item)) + }) + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1464,6 +1593,18 @@ impl<I: Iterator> Iterator for Peekable<I> { let hi = hi.and_then(|x| x.checked_add(peek_len)); (lo, hi) } + + #[inline] + fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + let acc = match self.peeked { + Some(None) => return init, + Some(Some(v)) => fold(init, v), + None => init, + }; + self.iter.fold(acc, fold) + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1572,6 +1713,19 @@ impl<I: Iterator, P> Iterator for SkipWhile<I, P> let (_, upper) = self.iter.size_hint(); (0, upper) // can't know a lower bound, due to the predicate } + + #[inline] + fn fold<Acc, Fold>(mut self, mut init: Acc, mut fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + if !self.flag { + match self.next() { + Some(v) => init = fold(init, v), + None => return init, + } + } + self.iter.fold(init, fold) + } } #[unstable(feature = "fused", issue = "35602")] @@ -1712,6 +1866,19 @@ impl<I> Iterator for Skip<I> where I: Iterator { (lower, upper) } + + #[inline] + fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + if self.n > 0 { + // nth(n) skips n+1 + if self.iter.nth(self.n - 1).is_none() { + return init; + } + } + self.iter.fold(init, fold) + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1934,6 +2101,16 @@ impl<I: DoubleEndedIterator, U, F> DoubleEndedIterator for FlatMap<I, U, F> wher } } } + + #[inline] + fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.frontiter.into_iter() + .chain(self.iter.map(self.f).map(U::into_iter)) + .chain(self.backiter) + .rfold(init, |acc, iter| iter.rfold(acc, &mut fold)) + } } #[unstable(feature = "fused", issue = "35602")] @@ -2011,6 +2188,17 @@ impl<I> Iterator for Fuse<I> where I: Iterator { self.iter.size_hint() } } + + #[inline] + default fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + if self.done { + init + } else { + self.iter.fold(init, fold) + } + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -2025,6 +2213,17 @@ impl<I> DoubleEndedIterator for Fuse<I> where I: DoubleEndedIterator { next } } + + #[inline] + default fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + if self.done { + init + } else { + self.iter.rfold(init, fold) + } + } } unsafe impl<I> TrustedRandomAccess for Fuse<I> @@ -2065,6 +2264,13 @@ impl<I> Iterator for Fuse<I> where I: FusedIterator { fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() } + + #[inline] + fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.iter.fold(init, fold) + } } #[unstable(feature = "fused", reason = "recently added", issue = "35602")] @@ -2075,6 +2281,13 @@ impl<I> DoubleEndedIterator for Fuse<I> fn next_back(&mut self) -> Option<<I as Iterator>::Item> { self.iter.next_back() } + + #[inline] + fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.iter.rfold(init, fold) + } } @@ -2139,6 +2352,14 @@ impl<I: Iterator, F> Iterator for Inspect<I, F> where F: FnMut(&I::Item) { fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() } + + #[inline] + fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + let mut f = self.f; + self.iter.fold(init, move |acc, item| { f(&item); fold(acc, item) }) + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -2150,6 +2371,14 @@ impl<I: DoubleEndedIterator, F> DoubleEndedIterator for Inspect<I, F> let next = self.iter.next_back(); self.do_inspect(next) } + + #[inline] + fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + let mut f = self.f; + self.iter.rfold(init, move |acc, item| { f(&item); fold(acc, item) }) + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 73d518b570a..e9aee4a4676 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -89,6 +89,7 @@ macro_rules! step_impl_unsigned { } #[inline] + #[allow(unreachable_patterns)] fn add_usize(&self, n: usize) -> Option<Self> { match <$t>::try_from(n) { Ok(n_as_t) => self.checked_add(n_as_t), @@ -120,6 +121,7 @@ macro_rules! step_impl_signed { } #[inline] + #[allow(unreachable_patterns)] fn add_usize(&self, n: usize) -> Option<Self> { match <$unsigned>::try_from(n) { Ok(n_as_unsigned) => { diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index 7ef50396c82..28236d193c3 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -415,6 +415,70 @@ pub trait DoubleEndedIterator: Iterator { #[stable(feature = "rust1", since = "1.0.0")] fn next_back(&mut self) -> Option<Self::Item>; + /// An iterator method that reduces the iterator's elements to a single, + /// final value, starting from the back. + /// + /// This is the reverse version of [`fold()`]: it takes elements starting from + /// the back of the iterator. + /// + /// `rfold()` takes two arguments: an initial value, and a closure with two + /// arguments: an 'accumulator', and an element. The closure returns the value that + /// the accumulator should have for the next iteration. + /// + /// The initial value is the value the accumulator will have on the first + /// call. + /// + /// After applying this closure to every element of the iterator, `rfold()` + /// returns the accumulator. + /// + /// This operation is sometimes called 'reduce' or 'inject'. + /// + /// Folding is useful whenever you have a collection of something, and want + /// to produce a single value from it. + /// + /// [`fold()`]: trait.Iterator.html#method.fold + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(iter_rfold)] + /// let a = [1, 2, 3]; + /// + /// // the sum of all of the elements of a + /// let sum = a.iter() + /// .rfold(0, |acc, &x| acc + x); + /// + /// assert_eq!(sum, 6); + /// ``` + /// + /// This example builds a string, starting with an initial value + /// and continuing with each element from the back until the front: + /// + /// ``` + /// #![feature(iter_rfold)] + /// let numbers = [1, 2, 3, 4, 5]; + /// + /// let zero = "0".to_string(); + /// + /// let result = numbers.iter().rfold(zero, |acc, &x| { + /// format!("({} + {})", x, acc) + /// }); + /// + /// assert_eq!(result, "(1 + (2 + (3 + (4 + (5 + 0)))))"); + /// ``` + #[inline] + #[unstable(feature = "iter_rfold", issue = "44705")] + fn rfold<B, F>(mut self, mut accum: B, mut f: F) -> B where + Self: Sized, F: FnMut(B, Self::Item) -> B, + { + while let Some(x) = self.next_back() { + accum = f(accum, x); + } + accum + } + /// Searches for an element of an iterator from the right that satisfies a predicate. /// /// `rfind()` takes a closure that returns `true` or `false`. It applies diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index e8fd729b638..f56a9a40332 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -122,7 +122,7 @@ pub trait Sized { /// [RFC982]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md /// [nomicon-coerce]: ../../nomicon/coercions.html #[unstable(feature = "unsize", issue = "27732")] -#[lang="unsize"] +#[lang = "unsize"] pub trait Unsize<T: ?Sized> { // Empty. } diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 34994dc3b70..c869054cee8 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -177,15 +177,59 @@ pub fn forget<T>(t: T) { /// Returns the size of a type in bytes. /// -/// More specifically, this is the offset in bytes between successive -/// items of the same type, including alignment padding. +/// More specifically, this is the offset in bytes between successive elements +/// in an array with that item type including alignment padding. Thus, for any +/// type `T` and length `n`, `[T; n]` has a size of `n * size_of::<T>()`. +/// +/// In general, the size of a type is not stable across compilations, but +/// specific types such as primitives are. +/// +/// The following table gives the size for primitives. +/// +/// Type | size_of::\<Type>() +/// ---- | --------------- +/// () | 0 +/// u8 | 1 +/// u16 | 2 +/// u32 | 4 +/// u64 | 8 +/// i8 | 1 +/// i16 | 2 +/// i32 | 4 +/// i64 | 8 +/// f32 | 4 +/// f64 | 8 +/// char | 4 +/// +/// Furthermore, `usize` and `isize` have the same size. +/// +/// The types `*const T`, `&T`, `Box<T>`, `Option<&T>`, and `Option<Box<T>>` all have +/// the same size. If `T` is Sized, all of those types have the same size as `usize`. +/// +/// The mutability of a pointer does not change its size. As such, `&T` and `&mut T` +/// have the same size. Likewise for `*const T` and `*mut T`. /// /// # Examples /// /// ``` /// use std::mem; /// +/// // Some primitives /// assert_eq!(4, mem::size_of::<i32>()); +/// assert_eq!(8, mem::size_of::<f64>()); +/// assert_eq!(0, mem::size_of::<()>()); +/// +/// // Some arrays +/// assert_eq!(8, mem::size_of::<[i32; 2]>()); +/// assert_eq!(12, mem::size_of::<[i32; 3]>()); +/// assert_eq!(0, mem::size_of::<[i32; 0]>()); +/// +/// +/// // Pointer size equality +/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::<*const i32>()); +/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::<Box<i32>>()); +/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::<Option<&i32>>()); +/// assert_eq!(mem::size_of::<Box<i32>>(), mem::size_of::<Option<Box<i32>>>()); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -358,7 +402,7 @@ pub fn align_of_val<T: ?Sized>(val: &T) -> usize { /// } /// ``` #[inline] -#[stable(feature = "needs_drop", since = "1.22.0")] +#[stable(feature = "needs_drop", since = "1.21.0")] pub fn needs_drop<T>() -> bool { unsafe { intrinsics::needs_drop::<T>() } } diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index bf31deae7a6..85be8a08728 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -12,7 +12,7 @@ #![stable(feature = "rust1", since = "1.0.0")] -use convert::TryFrom; +use convert::{Infallible, TryFrom}; use fmt; use intrinsics; use str::FromStr; @@ -2507,16 +2507,24 @@ impl fmt::Display for TryFromIntError { } } +#[unstable(feature = "try_from", issue = "33417")] +impl From<Infallible> for TryFromIntError { + fn from(infallible: Infallible) -> TryFromIntError { + match infallible { + } + } +} + // no possible bounds violation macro_rules! try_from_unbounded { ($source:ty, $($target:ty),*) => {$( #[unstable(feature = "try_from", issue = "33417")] impl TryFrom<$source> for $target { - type Error = TryFromIntError; + type Error = Infallible; #[inline] - fn try_from(u: $source) -> Result<$target, TryFromIntError> { - Ok(u as $target) + fn try_from(value: $source) -> Result<Self, Self::Error> { + Ok(value as $target) } } )*} @@ -2588,31 +2596,17 @@ macro_rules! rev { } /// intra-sign conversions -try_from_unbounded!(u8, u8, u16, u32, u64, u128); -try_from_unbounded!(u16, u16, u32, u64, u128); -try_from_unbounded!(u32, u32, u64, u128); -try_from_unbounded!(u64, u64, u128); -try_from_unbounded!(u128, u128); try_from_upper_bounded!(u16, u8); try_from_upper_bounded!(u32, u16, u8); try_from_upper_bounded!(u64, u32, u16, u8); try_from_upper_bounded!(u128, u64, u32, u16, u8); -try_from_unbounded!(i8, i8, i16, i32, i64, i128); -try_from_unbounded!(i16, i16, i32, i64, i128); -try_from_unbounded!(i32, i32, i64, i128); -try_from_unbounded!(i64, i64, i128); -try_from_unbounded!(i128, i128); try_from_both_bounded!(i16, i8); try_from_both_bounded!(i32, i16, i8); try_from_both_bounded!(i64, i32, i16, i8); try_from_both_bounded!(i128, i64, i32, i16, i8); // unsigned-to-signed -try_from_unbounded!(u8, i16, i32, i64, i128); -try_from_unbounded!(u16, i32, i64, i128); -try_from_unbounded!(u32, i64, i128); -try_from_unbounded!(u64, i128); try_from_upper_bounded!(u8, i8); try_from_upper_bounded!(u16, i8, i16); try_from_upper_bounded!(u32, i8, i16, i32); @@ -2631,15 +2625,13 @@ try_from_both_bounded!(i64, u32, u16, u8); try_from_both_bounded!(i128, u64, u32, u16, u8); // usize/isize -try_from_unbounded!(usize, usize); try_from_upper_bounded!(usize, isize); try_from_lower_bounded!(isize, usize); -try_from_unbounded!(isize, isize); #[cfg(target_pointer_width = "16")] mod ptr_try_from_impls { use super::TryFromIntError; - use convert::TryFrom; + use convert::{Infallible, TryFrom}; try_from_upper_bounded!(usize, u8); try_from_unbounded!(usize, u16, u32, u64, u128); @@ -2651,21 +2643,21 @@ mod ptr_try_from_impls { try_from_both_bounded!(isize, i8); try_from_unbounded!(isize, i16, i32, i64, i128); - rev!(try_from_unbounded, usize, u8, u16); + rev!(try_from_unbounded, usize, u16); rev!(try_from_upper_bounded, usize, u32, u64, u128); rev!(try_from_lower_bounded, usize, i8, i16); rev!(try_from_both_bounded, usize, i32, i64, i128); rev!(try_from_unbounded, isize, u8); rev!(try_from_upper_bounded, isize, u16, u32, u64, u128); - rev!(try_from_unbounded, isize, i8, i16); + rev!(try_from_unbounded, isize, i16); rev!(try_from_both_bounded, isize, i32, i64, i128); } #[cfg(target_pointer_width = "32")] mod ptr_try_from_impls { use super::TryFromIntError; - use convert::TryFrom; + use convert::{Infallible, TryFrom}; try_from_upper_bounded!(usize, u8, u16); try_from_unbounded!(usize, u32, u64, u128); @@ -2677,21 +2669,21 @@ mod ptr_try_from_impls { try_from_both_bounded!(isize, i8, i16); try_from_unbounded!(isize, i32, i64, i128); - rev!(try_from_unbounded, usize, u8, u16, u32); + rev!(try_from_unbounded, usize, u16, u32); rev!(try_from_upper_bounded, usize, u64, u128); rev!(try_from_lower_bounded, usize, i8, i16, i32); rev!(try_from_both_bounded, usize, i64, i128); rev!(try_from_unbounded, isize, u8, u16); rev!(try_from_upper_bounded, isize, u32, u64, u128); - rev!(try_from_unbounded, isize, i8, i16, i32); + rev!(try_from_unbounded, isize, i16, i32); rev!(try_from_both_bounded, isize, i64, i128); } #[cfg(target_pointer_width = "64")] mod ptr_try_from_impls { use super::TryFromIntError; - use convert::TryFrom; + use convert::{Infallible, TryFrom}; try_from_upper_bounded!(usize, u8, u16, u32); try_from_unbounded!(usize, u64, u128); @@ -2703,14 +2695,14 @@ mod ptr_try_from_impls { try_from_both_bounded!(isize, i8, i16, i32); try_from_unbounded!(isize, i64, i128); - rev!(try_from_unbounded, usize, u8, u16, u32, u64); + rev!(try_from_unbounded, usize, u16, u32, u64); rev!(try_from_upper_bounded, usize, u128); rev!(try_from_lower_bounded, usize, i8, i16, i32, i64); rev!(try_from_both_bounded, usize, i128); rev!(try_from_unbounded, isize, u8, u16, u32); rev!(try_from_upper_bounded, isize, u64, u128); - rev!(try_from_unbounded, isize, i8, i16, i32, i64); + rev!(try_from_unbounded, isize, i16, i32, i64); rev!(try_from_both_bounded, isize, i128); } diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs index acdf685e850..ae1b0b3ce11 100644 --- a/src/libcore/num/wrapping.rs +++ b/src/libcore/num/wrapping.rs @@ -36,6 +36,7 @@ macro_rules! sh_impl_signed { *self = *self << other; } } + forward_ref_op_assign! { impl ShlAssign, shl_assign for Wrapping<$t>, $f } #[stable(feature = "rust1", since = "1.0.0")] impl Shr<$f> for Wrapping<$t> { @@ -58,6 +59,7 @@ macro_rules! sh_impl_signed { *self = *self >> other; } } + forward_ref_op_assign! { impl ShrAssign, shr_assign for Wrapping<$t>, $f } ) } @@ -80,6 +82,7 @@ macro_rules! sh_impl_unsigned { *self = *self << other; } } + forward_ref_op_assign! { impl ShlAssign, shl_assign for Wrapping<$t>, $f } #[stable(feature = "rust1", since = "1.0.0")] impl Shr<$f> for Wrapping<$t> { @@ -98,6 +101,7 @@ macro_rules! sh_impl_unsigned { *self = *self >> other; } } + forward_ref_op_assign! { impl ShrAssign, shr_assign for Wrapping<$t>, $f } ) } @@ -142,6 +146,7 @@ macro_rules! wrapping_impl { *self = *self + other; } } + forward_ref_op_assign! { impl AddAssign, add_assign for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "rust1", since = "1.0.0")] impl Sub for Wrapping<$t> { @@ -162,6 +167,7 @@ macro_rules! wrapping_impl { *self = *self - other; } } + forward_ref_op_assign! { impl SubAssign, sub_assign for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "rust1", since = "1.0.0")] impl Mul for Wrapping<$t> { @@ -182,6 +188,7 @@ macro_rules! wrapping_impl { *self = *self * other; } } + forward_ref_op_assign! { impl MulAssign, mul_assign for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "wrapping_div", since = "1.3.0")] impl Div for Wrapping<$t> { @@ -202,6 +209,7 @@ macro_rules! wrapping_impl { *self = *self / other; } } + forward_ref_op_assign! { impl DivAssign, div_assign for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "wrapping_impls", since = "1.7.0")] impl Rem for Wrapping<$t> { @@ -222,6 +230,7 @@ macro_rules! wrapping_impl { *self = *self % other; } } + forward_ref_op_assign! { impl RemAssign, rem_assign for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "rust1", since = "1.0.0")] impl Not for Wrapping<$t> { @@ -254,6 +263,7 @@ macro_rules! wrapping_impl { *self = *self ^ other; } } + forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "rust1", since = "1.0.0")] impl BitOr for Wrapping<$t> { @@ -274,6 +284,7 @@ macro_rules! wrapping_impl { *self = *self | other; } } + forward_ref_op_assign! { impl BitOrAssign, bitor_assign for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "rust1", since = "1.0.0")] impl BitAnd for Wrapping<$t> { @@ -294,6 +305,7 @@ macro_rules! wrapping_impl { *self = *self & other; } } + forward_ref_op_assign! { impl BitAndAssign, bitand_assign for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "wrapping_neg", since = "1.10.0")] impl Neg for Wrapping<$t> { diff --git a/src/libcore/ops/arith.rs b/src/libcore/ops/arith.rs index 62007caedd3..8b3d662a6db 100644 --- a/src/libcore/ops/arith.rs +++ b/src/libcore/ops/arith.rs @@ -662,6 +662,8 @@ macro_rules! add_assign_impl { #[rustc_inherit_overflow_checks] fn add_assign(&mut self, other: $t) { *self += other } } + + forward_ref_op_assign! { impl AddAssign, add_assign for $t, $t } )+) } @@ -713,6 +715,8 @@ macro_rules! sub_assign_impl { #[rustc_inherit_overflow_checks] fn sub_assign(&mut self, other: $t) { *self -= other } } + + forward_ref_op_assign! { impl SubAssign, sub_assign for $t, $t } )+) } @@ -755,6 +759,8 @@ macro_rules! mul_assign_impl { #[rustc_inherit_overflow_checks] fn mul_assign(&mut self, other: $t) { *self *= other } } + + forward_ref_op_assign! { impl MulAssign, mul_assign for $t, $t } )+) } @@ -796,6 +802,8 @@ macro_rules! div_assign_impl { #[inline] fn div_assign(&mut self, other: $t) { *self /= other } } + + forward_ref_op_assign! { impl DivAssign, div_assign for $t, $t } )+) } @@ -841,6 +849,8 @@ macro_rules! rem_assign_impl { #[inline] fn rem_assign(&mut self, other: $t) { *self %= other } } + + forward_ref_op_assign! { impl RemAssign, rem_assign for $t, $t } )+) } diff --git a/src/libcore/ops/bit.rs b/src/libcore/ops/bit.rs index 0bc5e554cb3..7ac5fc4debf 100644 --- a/src/libcore/ops/bit.rs +++ b/src/libcore/ops/bit.rs @@ -593,6 +593,8 @@ macro_rules! bitand_assign_impl { #[inline] fn bitand_assign(&mut self, other: $t) { *self &= other } } + + forward_ref_op_assign! { impl BitAndAssign, bitand_assign for $t, $t } )+) } @@ -638,6 +640,8 @@ macro_rules! bitor_assign_impl { #[inline] fn bitor_assign(&mut self, other: $t) { *self |= other } } + + forward_ref_op_assign! { impl BitOrAssign, bitor_assign for $t, $t } )+) } @@ -683,6 +687,8 @@ macro_rules! bitxor_assign_impl { #[inline] fn bitxor_assign(&mut self, other: $t) { *self ^= other } } + + forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for $t, $t } )+) } @@ -729,6 +735,8 @@ macro_rules! shl_assign_impl { *self <<= other } } + + forward_ref_op_assign! { impl ShlAssign, shl_assign for $t, $f } ) } @@ -793,6 +801,8 @@ macro_rules! shr_assign_impl { *self >>= other } } + + forward_ref_op_assign! { impl ShrAssign, shr_assign for $t, $f } ) } diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs index 463a50491a8..3f573f7c7eb 100644 --- a/src/libcore/ops/range.rs +++ b/src/libcore/ops/range.rs @@ -241,9 +241,9 @@ impl<Idx: PartialOrd<Idx>> RangeTo<Idx> { } } -/// An range bounded inclusively below and above (`start...end`). +/// An range bounded inclusively below and above (`start..=end`). /// -/// The `RangeInclusive` `start...end` contains all values with `x >= start` +/// The `RangeInclusive` `start..=end` contains all values with `x >= start` /// and `x <= end`. /// /// # Examples @@ -251,12 +251,12 @@ impl<Idx: PartialOrd<Idx>> RangeTo<Idx> { /// ``` /// #![feature(inclusive_range,inclusive_range_syntax)] /// -/// assert_eq!((3...5), std::ops::RangeInclusive { start: 3, end: 5 }); -/// assert_eq!(3 + 4 + 5, (3...5).sum()); +/// assert_eq!((3..=5), std::ops::RangeInclusive { start: 3, end: 5 }); +/// assert_eq!(3 + 4 + 5, (3..=5).sum()); /// /// let arr = [0, 1, 2, 3]; -/// assert_eq!(arr[ ...2], [0,1,2 ]); -/// assert_eq!(arr[1...2], [ 1,2 ]); // RangeInclusive +/// assert_eq!(arr[ ..=2], [0,1,2 ]); +/// assert_eq!(arr[1..=2], [ 1,2 ]); // RangeInclusive /// ``` #[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] @@ -276,7 +276,7 @@ pub struct RangeInclusive<Idx> { #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "{:?}...{:?}", self.start, self.end) + write!(fmt, "{:?}..={:?}", self.start, self.end) } } @@ -289,32 +289,32 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> { /// ``` /// #![feature(range_contains,inclusive_range_syntax)] /// - /// assert!(!(3...5).contains(2)); - /// assert!( (3...5).contains(3)); - /// assert!( (3...5).contains(4)); - /// assert!( (3...5).contains(5)); - /// assert!(!(3...5).contains(6)); + /// assert!(!(3..=5).contains(2)); + /// assert!( (3..=5).contains(3)); + /// assert!( (3..=5).contains(4)); + /// assert!( (3..=5).contains(5)); + /// assert!(!(3..=5).contains(6)); /// - /// assert!( (3...3).contains(3)); - /// assert!(!(3...2).contains(3)); + /// assert!( (3..=3).contains(3)); + /// assert!(!(3..=2).contains(3)); /// ``` pub fn contains(&self, item: Idx) -> bool { self.start <= item && item <= self.end } } -/// A range only bounded inclusively above (`...end`). +/// A range only bounded inclusively above (`..=end`). /// -/// The `RangeToInclusive` `...end` contains all values with `x <= end`. +/// The `RangeToInclusive` `..=end` contains all values with `x <= end`. /// It cannot serve as an [`Iterator`] because it doesn't have a starting point. /// /// # Examples /// -/// The `...end` syntax is a `RangeToInclusive`: +/// The `..=end` syntax is a `RangeToInclusive`: /// /// ``` /// #![feature(inclusive_range,inclusive_range_syntax)] -/// assert_eq!((...5), std::ops::RangeToInclusive{ end: 5 }); +/// assert_eq!((..=5), std::ops::RangeToInclusive{ end: 5 }); /// ``` /// /// It does not have an [`IntoIterator`] implementation, so you can't use it in a @@ -325,7 +325,7 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> { /// /// // error[E0277]: the trait bound `std::ops::RangeToInclusive<{integer}>: /// // std::iter::Iterator` is not satisfied -/// for i in ...5 { +/// for i in ..=5 { /// // ... /// } /// ``` @@ -337,8 +337,8 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> { /// #![feature(inclusive_range_syntax)] /// /// let arr = [0, 1, 2, 3]; -/// assert_eq!(arr[ ...2], [0,1,2 ]); // RangeToInclusive -/// assert_eq!(arr[1...2], [ 1,2 ]); +/// assert_eq!(arr[ ..=2], [0,1,2 ]); // RangeToInclusive +/// assert_eq!(arr[1..=2], [ 1,2 ]); /// ``` /// /// [`IntoIterator`]: ../iter/trait.Iterator.html @@ -357,7 +357,7 @@ pub struct RangeToInclusive<Idx> { #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] impl<Idx: fmt::Debug> fmt::Debug for RangeToInclusive<Idx> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "...{:?}", self.end) + write!(fmt, "..={:?}", self.end) } } @@ -370,9 +370,9 @@ impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> { /// ``` /// #![feature(range_contains,inclusive_range_syntax)] /// - /// assert!( (...5).contains(-1_000_000_000)); - /// assert!( (...5).contains(5)); - /// assert!(!(...5).contains(6)); + /// assert!( (..=5).contains(-1_000_000_000)); + /// assert!( (..=5).contains(5)); + /// assert!(!(..=5).contains(6)); /// ``` pub fn contains(&self, item: Idx) -> bool { (item <= self.end) diff --git a/src/libcore/ops/unsize.rs b/src/libcore/ops/unsize.rs index 58da290cfb6..cd896859b16 100644 --- a/src/libcore/ops/unsize.rs +++ b/src/libcore/ops/unsize.rs @@ -42,7 +42,7 @@ use marker::Unsize; /// [unsize]: ../marker/trait.Unsize.html /// [nomicon-coerce]: ../../nomicon/coercions.html #[unstable(feature = "coerce_unsized", issue = "27732")] -#[lang="coerce_unsized"] +#[lang = "coerce_unsized"] pub trait CoerceUnsized<T> { // Empty. } diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 138e04c7737..980ea551f08 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -146,7 +146,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use iter::{FromIterator, FusedIterator, TrustedLen}; -use mem; +use {mem, ops}; // Note that this is not a lang item per se, but it has a hidden dependency on // `Iterator`, which is one. The compiler assumes that the `next` method of @@ -1123,3 +1123,29 @@ impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> { } } } + +/// The error type that results from applying the try operator (`?`) to a `None` value. If you wish +/// to allow `x?` (where `x` is an `Option<T>`) to be converted into your error type, you can +/// implement `impl From<NoneError>` for `YourErrorType`. In that case, `x?` within a function that +/// returns `Result<_, YourErrorType>` will translate a `None` value into an `Err` result. +#[unstable(feature = "try_trait", issue = "42327")] +#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] +pub struct NoneError; + +#[unstable(feature = "try_trait", issue = "42327")] +impl<T> ops::Try for Option<T> { + type Ok = T; + type Error = NoneError; + + fn into_result(self) -> Result<T, NoneError> { + self.ok_or(NoneError) + } + + fn from_ok(v: T) -> Self { + Some(v) + } + + fn from_error(_: NoneError) -> Self { + None + } +} diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 4041a3760e5..34d31044653 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -56,7 +56,7 @@ pub use intrinsics::write_bytes; /// This has all the same safety problems as `ptr::read` with respect to /// invalid pointers, types, and double drops. #[stable(feature = "drop_in_place", since = "1.8.0")] -#[lang="drop_in_place"] +#[lang = "drop_in_place"] #[allow(unconditional_recursion)] pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) { // Code here does not matter - this is replaced by the diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index dacc014955a..ae243f3f246 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -16,6 +16,9 @@ #![stable(feature = "rust1", since = "1.0.0")] +// FIXME: after next stage0, change RangeInclusive { ... } back to ..= +use ops::RangeInclusive; + // How this module is organized. // // The library infrastructure for slices is fairly messy. There's @@ -1044,32 +1047,32 @@ impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> { #[inline] fn get(self, slice: &[T]) -> Option<&[T]> { - (0...self.end).get(slice) + (RangeInclusive { start: 0, end: self.end }).get(slice) } #[inline] fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> { - (0...self.end).get_mut(slice) + (RangeInclusive { start: 0, end: self.end }).get_mut(slice) } #[inline] unsafe fn get_unchecked(self, slice: &[T]) -> &[T] { - (0...self.end).get_unchecked(slice) + (RangeInclusive { start: 0, end: self.end }).get_unchecked(slice) } #[inline] unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] { - (0...self.end).get_unchecked_mut(slice) + (RangeInclusive { start: 0, end: self.end }).get_unchecked_mut(slice) } #[inline] fn index(self, slice: &[T]) -> &[T] { - (0...self.end).index(slice) + (RangeInclusive { start: 0, end: self.end }).index(slice) } #[inline] fn index_mut(self, slice: &mut [T]) -> &mut [T] { - (0...self.end).index_mut(slice) + (RangeInclusive { start: 0, end: self.end }).index_mut(slice) } } diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index c24cdb30bad..0af9fcf0a3d 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -18,9 +18,9 @@ use self::pattern::Pattern; use self::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher}; use char; -use convert::TryFrom; use fmt; -use iter::{Map, Cloned, FusedIterator}; +use iter::{Map, Cloned, FusedIterator, TrustedLen}; +use iter_private::TrustedRandomAccess; use slice::{self, SliceIndex}; use mem; @@ -818,6 +818,17 @@ impl<'a> ExactSizeIterator for Bytes<'a> { #[unstable(feature = "fused", issue = "35602")] impl<'a> FusedIterator for Bytes<'a> {} +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl<'a> TrustedLen for Bytes<'a> {} + +#[doc(hidden)] +unsafe impl<'a> TrustedRandomAccess for Bytes<'a> { + unsafe fn get_unchecked(&mut self, i: usize) -> u8 { + self.0.get_unchecked(i) + } + fn may_have_side_effect() -> bool { false } +} + /// This macro generates a Clone impl for string pattern API /// wrapper types of the form X<'a, P> macro_rules! derive_pattern_clone { @@ -1399,9 +1410,6 @@ Section: Comparing strings */ /// Bytewise slice equality -/// NOTE: This function is (ab)used in rustc::middle::trans::_match -/// to compare &[u8] byte slices that are not necessarily valid UTF-8. -#[lang = "str_eq"] #[inline] fn eq_slice(a: &str, b: &str) -> bool { a.as_bytes() == b.as_bytes() @@ -2189,7 +2197,7 @@ pub trait StrExt { #[stable(feature = "core", since = "1.6.0")] fn is_empty(&self) -> bool; #[stable(feature = "core", since = "1.6.0")] - fn parse<'a, T: TryFrom<&'a str>>(&'a self) -> Result<T, T::Error>; + fn parse<T: FromStr>(&self) -> Result<T, T::Err>; } // truncate `&str` to length at most equal to `max` @@ -2509,9 +2517,7 @@ impl StrExt for str { fn is_empty(&self) -> bool { self.len() == 0 } #[inline] - fn parse<'a, T>(&'a self) -> Result<T, T::Error> where T: TryFrom<&'a str> { - T::try_from(self) - } + fn parse<T: FromStr>(&self) -> Result<T, T::Err> { FromStr::from_str(self) } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 3dd08e69710..465d31b5f49 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -926,10 +926,24 @@ macro_rules! atomic_int { $stable_cxchg:meta, $stable_debug:meta, $stable_access:meta, + $s_int_type:expr, $int_ref:expr, $int_type:ident $atomic_type:ident $atomic_init:ident) => { /// An integer type which can be safely shared between threads. /// - /// This type has the same in-memory representation as the underlying integer type. + /// This type has the same in-memory representation as the underlying + /// integer type, [` + #[doc = $s_int_type] + /// `]( + #[doc = $int_ref] + /// ). For more about the differences between atomic types and + /// non-atomic types, please see the [module-level documentation]. + /// + /// Please note that examples are shared between atomic variants of + /// primitive integer types, so it's normal that they are all + /// demonstrating [`AtomicIsize`]. + /// + /// [module-level documentation]: index.html + /// [`AtomicIsize`]: struct.AtomicIsize.html #[$stable] pub struct $atomic_type { v: UnsafeCell<$int_type>, @@ -1339,6 +1353,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + "i8", "../../../std/primitive.i8.html", i8 AtomicI8 ATOMIC_I8_INIT } #[cfg(target_has_atomic = "8")] @@ -1348,6 +1363,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + "u8", "../../../std/primitive.u8.html", u8 AtomicU8 ATOMIC_U8_INIT } #[cfg(target_has_atomic = "16")] @@ -1357,6 +1373,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + "i16", "../../../std/primitive.i16.html", i16 AtomicI16 ATOMIC_I16_INIT } #[cfg(target_has_atomic = "16")] @@ -1366,6 +1383,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + "u16", "../../../std/primitive.u16.html", u16 AtomicU16 ATOMIC_U16_INIT } #[cfg(target_has_atomic = "32")] @@ -1375,6 +1393,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + "i32", "../../../std/primitive.i32.html", i32 AtomicI32 ATOMIC_I32_INIT } #[cfg(target_has_atomic = "32")] @@ -1384,6 +1403,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + "u32", "../../../std/primitive.u32.html", u32 AtomicU32 ATOMIC_U32_INIT } #[cfg(target_has_atomic = "64")] @@ -1393,6 +1413,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + "i64", "../../../std/primitive.i64.html", i64 AtomicI64 ATOMIC_I64_INIT } #[cfg(target_has_atomic = "64")] @@ -1402,6 +1423,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + "u64", "../../../std/primitive.u64.html", u64 AtomicU64 ATOMIC_U64_INIT } #[cfg(target_has_atomic = "ptr")] @@ -1411,6 +1433,7 @@ atomic_int!{ stable(feature = "extended_compare_and_swap", since = "1.10.0"), stable(feature = "atomic_debug", since = "1.3.0"), stable(feature = "atomic_access", since = "1.15.0"), + "isize", "../../../std/primitive.isize.html", isize AtomicIsize ATOMIC_ISIZE_INIT } #[cfg(target_has_atomic = "ptr")] @@ -1420,6 +1443,7 @@ atomic_int!{ stable(feature = "extended_compare_and_swap", since = "1.10.0"), stable(feature = "atomic_debug", since = "1.3.0"), stable(feature = "atomic_access", since = "1.15.0"), + "usize", "../../../std/primitive.usize.html", usize AtomicUsize ATOMIC_USIZE_INIT } @@ -1752,7 +1776,7 @@ pub fn fence(order: Ordering) { /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed /// [memory barriers]: https://www.kernel.org/doc/Documentation/memory-barriers.txt #[inline] -#[stable(feature = "compiler_fences", since = "1.22.0")] +#[stable(feature = "compiler_fences", since = "1.21.0")] pub fn compiler_fence(order: Ordering) { unsafe { match order { diff --git a/src/libcore/tests/char.rs b/src/libcore/tests/char.rs index 7c3b90c8153..4e10ceac878 100644 --- a/src/libcore/tests/char.rs +++ b/src/libcore/tests/char.rs @@ -32,7 +32,6 @@ fn test_convert() { #[test] fn test_from_str() { assert_eq!(char::from_str("a").unwrap(), 'a'); - assert_eq!(char::try_from("a").unwrap(), 'a'); assert_eq!(char::from_str("\0").unwrap(), '\0'); assert_eq!(char::from_str("\u{D7FF}").unwrap(), '\u{d7FF}'); assert!(char::from_str("").is_err()); diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 59ae30de452..f8c6fc5c8fa 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -249,6 +249,25 @@ fn test_filter_map() { } #[test] +fn test_filter_map_fold() { + let xs = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let ys = [0*0, 2*2, 4*4, 6*6, 8*8]; + let it = xs.iter().filter_map(|&x| if x % 2 == 0 { Some(x*x) } else { None }); + let i = it.fold(0, |i, x| { + assert_eq!(x, ys[i]); + i + 1 + }); + assert_eq!(i, ys.len()); + + let it = xs.iter().filter_map(|&x| if x % 2 == 0 { Some(x*x) } else { None }); + let i = it.rfold(ys.len(), |i, x| { + assert_eq!(x, ys[i - 1]); + i - 1 + }); + assert_eq!(i, 0); +} + +#[test] fn test_iterator_enumerate() { let xs = [0, 1, 2, 3, 4, 5]; let it = xs.iter().enumerate(); @@ -282,7 +301,31 @@ fn test_iterator_enumerate_nth() { #[test] fn test_iterator_enumerate_count() { let xs = [0, 1, 2, 3, 4, 5]; - assert_eq!(xs.iter().count(), 6); + assert_eq!(xs.iter().enumerate().count(), 6); +} + +#[test] +fn test_iterator_enumerate_fold() { + let xs = [0, 1, 2, 3, 4, 5]; + let mut it = xs.iter().enumerate(); + // steal a couple to get an interesting offset + assert_eq!(it.next(), Some((0, &0))); + assert_eq!(it.next(), Some((1, &1))); + let i = it.fold(2, |i, (j, &x)| { + assert_eq!(i, j); + assert_eq!(x, xs[j]); + i + 1 + }); + assert_eq!(i, xs.len()); + + let mut it = xs.iter().enumerate(); + assert_eq!(it.next(), Some((0, &0))); + let i = it.rfold(xs.len() - 1, |i, (j, &x)| { + assert_eq!(i, j); + assert_eq!(x, xs[j]); + i - 1 + }); + assert_eq!(i, 0); } #[test] @@ -292,6 +335,25 @@ fn test_iterator_filter_count() { } #[test] +fn test_iterator_filter_fold() { + let xs = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let ys = [0, 2, 4, 6, 8]; + let it = xs.iter().filter(|&&x| x % 2 == 0); + let i = it.fold(0, |i, &x| { + assert_eq!(x, ys[i]); + i + 1 + }); + assert_eq!(i, ys.len()); + + let it = xs.iter().filter(|&&x| x % 2 == 0); + let i = it.rfold(ys.len(), |i, &x| { + assert_eq!(x, ys[i - 1]); + i - 1 + }); + assert_eq!(i, 0); +} + +#[test] fn test_iterator_peekable() { let xs = vec![0, 1, 2, 3, 4, 5]; let mut it = xs.iter().cloned().peekable(); @@ -381,6 +443,18 @@ fn test_iterator_peekable_last() { assert_eq!(it.last(), None); } +#[test] +fn test_iterator_peekable_fold() { + let xs = [0, 1, 2, 3, 4, 5]; + let mut it = xs.iter().peekable(); + assert_eq!(it.peek(), Some(&&0)); + let i = it.fold(0, |i, &x| { + assert_eq!(x, xs[i]); + i + 1 + }); + assert_eq!(i, xs.len()); +} + /// This is an iterator that follows the Iterator contract, /// but it is not fused. After having returned None once, it will start /// producing elements if .next() is called again. @@ -471,6 +545,26 @@ fn test_iterator_skip_while() { } #[test] +fn test_iterator_skip_while_fold() { + let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19]; + let ys = [15, 16, 17, 19]; + let it = xs.iter().skip_while(|&x| *x < 15); + let i = it.fold(0, |i, &x| { + assert_eq!(x, ys[i]); + i + 1 + }); + assert_eq!(i, ys.len()); + + let mut it = xs.iter().skip_while(|&x| *x < 15); + assert_eq!(it.next(), Some(&ys[0])); // process skips before folding + let i = it.fold(1, |i, &x| { + assert_eq!(x, ys[i]); + i + 1 + }); + assert_eq!(i, ys.len()); +} + +#[test] fn test_iterator_skip() { let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30]; let ys = [13, 15, 16, 17, 19, 20, 30]; @@ -567,6 +661,26 @@ fn test_iterator_skip_last() { } #[test] +fn test_iterator_skip_fold() { + let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30]; + let ys = [13, 15, 16, 17, 19, 20, 30]; + let it = xs.iter().skip(5); + let i = it.fold(0, |i, &x| { + assert_eq!(x, ys[i]); + i + 1 + }); + assert_eq!(i, ys.len()); + + let mut it = xs.iter().skip(5); + assert_eq!(it.next(), Some(&ys[0])); // process skips before folding + let i = it.fold(1, |i, &x| { + assert_eq!(x, ys[i]); + i + 1 + }); + assert_eq!(i, ys.len()); +} + +#[test] fn test_iterator_take() { let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19]; let ys = [0, 1, 2, 3, 5]; @@ -661,13 +775,22 @@ fn test_iterator_flat_map_fold() { let xs = [0, 3, 6]; let ys = [1, 2, 3, 4, 5, 6, 7]; let mut it = xs.iter().flat_map(|&x| x..x+3); - it.next(); - it.next_back(); + assert_eq!(it.next(), Some(0)); + assert_eq!(it.next_back(), Some(8)); let i = it.fold(0, |i, x| { assert_eq!(x, ys[i]); i + 1 }); assert_eq!(i, ys.len()); + + let mut it = xs.iter().flat_map(|&x| x..x+3); + assert_eq!(it.next(), Some(0)); + assert_eq!(it.next_back(), Some(8)); + let i = it.rfold(ys.len(), |i, x| { + assert_eq!(x, ys[i - 1]); + i - 1 + }); + assert_eq!(i, 0); } #[test] @@ -685,6 +808,32 @@ fn test_inspect() { } #[test] +fn test_inspect_fold() { + let xs = [1, 2, 3, 4]; + let mut n = 0; + { + let it = xs.iter().inspect(|_| n += 1); + let i = it.fold(0, |i, &x| { + assert_eq!(x, xs[i]); + i + 1 + }); + assert_eq!(i, xs.len()); + } + assert_eq!(n, xs.len()); + + let mut n = 0; + { + let it = xs.iter().inspect(|_| n += 1); + let i = it.rfold(xs.len(), |i, &x| { + assert_eq!(x, xs[i - 1]); + i - 1 + }); + assert_eq!(i, 0); + } + assert_eq!(n, xs.len()); +} + +#[test] fn test_cycle() { let cycle_len = 3; let it = (0..).step_by(1).take(cycle_len).cycle(); @@ -1094,21 +1243,21 @@ fn test_range() { #[test] fn test_range_inclusive_exhaustion() { - let mut r = 10...10; + let mut r = 10..=10; assert_eq!(r.next(), Some(10)); - assert_eq!(r, 1...0); + assert_eq!(r, 1..=0); - let mut r = 10...10; + let mut r = 10..=10; assert_eq!(r.next_back(), Some(10)); - assert_eq!(r, 1...0); + assert_eq!(r, 1..=0); - let mut r = 10...12; + let mut r = 10..=12; assert_eq!(r.nth(2), Some(12)); - assert_eq!(r, 1...0); + assert_eq!(r, 1..=0); - let mut r = 10...12; + let mut r = 10..=12; assert_eq!(r.nth(5), None); - assert_eq!(r, 1...0); + assert_eq!(r, 1..=0); } @@ -1145,20 +1294,20 @@ fn test_range_from_nth() { #[test] fn test_range_inclusive_nth() { - assert_eq!((10...15).nth(0), Some(10)); - assert_eq!((10...15).nth(1), Some(11)); - assert_eq!((10...15).nth(5), Some(15)); - assert_eq!((10...15).nth(6), None); + assert_eq!((10..=15).nth(0), Some(10)); + assert_eq!((10..=15).nth(1), Some(11)); + assert_eq!((10..=15).nth(5), Some(15)); + assert_eq!((10..=15).nth(6), None); - let mut r = 10_u8...20; + let mut r = 10_u8..=20; assert_eq!(r.nth(2), Some(12)); - assert_eq!(r, 13...20); + assert_eq!(r, 13..=20); assert_eq!(r.nth(2), Some(15)); - assert_eq!(r, 16...20); + assert_eq!(r, 16..=20); assert_eq!(r.is_empty(), false); assert_eq!(r.nth(10), None); assert_eq!(r.is_empty(), true); - assert_eq!(r, 1...0); // We may not want to document/promise this detail + assert_eq!(r, 1..=0); // We may not want to document/promise this detail } #[test] @@ -1242,6 +1391,31 @@ fn test_fuse_count() { } #[test] +fn test_fuse_fold() { + let xs = [0, 1, 2]; + let it = xs.iter(); // `FusedIterator` + let i = it.fuse().fold(0, |i, &x| { + assert_eq!(x, xs[i]); + i + 1 + }); + assert_eq!(i, xs.len()); + + let it = xs.iter(); // `FusedIterator` + let i = it.fuse().rfold(xs.len(), |i, &x| { + assert_eq!(x, xs[i - 1]); + i - 1 + }); + assert_eq!(i, 0); + + let it = xs.iter().scan((), |_, &x| Some(x)); // `!FusedIterator` + let i = it.fuse().fold(0, |i, x| { + assert_eq!(x, xs[i]); + i + 1 + }); + assert_eq!(i, xs.len()); +} + +#[test] fn test_once() { let mut it = once(42); assert_eq!(it.next(), Some(42)); diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 47995597a0a..afc5de7b0ee 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -25,6 +25,7 @@ #![feature(inclusive_range)] #![feature(inclusive_range_syntax)] #![feature(iter_rfind)] +#![feature(iter_rfold)] #![feature(nonzero)] #![feature(rand)] #![feature(raw)] @@ -38,6 +39,7 @@ #![feature(test)] #![feature(trusted_len)] #![feature(try_from)] +#![feature(try_trait)] #![feature(unique)] #![feature(const_atomic_bool_new)] diff --git a/src/libcore/tests/num/mod.rs b/src/libcore/tests/num/mod.rs index 400d53ce51a..7eb5ff98857 100644 --- a/src/libcore/tests/num/mod.rs +++ b/src/libcore/tests/num/mod.rs @@ -8,10 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::convert::TryFrom; +use core::convert::{TryFrom, TryInto}; use core::cmp::PartialEq; use core::fmt::Debug; use core::marker::Copy; +use core::num::TryFromIntError; use core::ops::{Add, Sub, Mul, Div, Rem}; use core::option::Option; use core::option::Option::{Some, None}; @@ -134,6 +135,13 @@ fn test_empty() { assert_eq!("".parse::<u8>().ok(), None); } +#[test] +fn test_infallible_try_from_int_error() { + let func = |x: i8| -> Result<i32, TryFromIntError> { Ok(x.try_into()?) }; + + assert!(func(0).is_ok()); +} + macro_rules! test_impl_from { ($fn_name: ident, $Small: ty, $Large: ty) => { #[test] diff --git a/src/libcore/tests/option.rs b/src/libcore/tests/option.rs index 6bac55575fb..22109e28edd 100644 --- a/src/libcore/tests/option.rs +++ b/src/libcore/tests/option.rs @@ -270,3 +270,30 @@ fn test_cloned() { assert_eq!(opt_ref_ref.clone().cloned(), Some(&val)); assert_eq!(opt_ref_ref.cloned().cloned(), Some(1)); } + +#[test] +fn test_try() { + fn try_option_some() -> Option<u8> { + let val = Some(1)?; + Some(val) + } + assert_eq!(try_option_some(), Some(1)); + + fn try_option_none() -> Option<u8> { + let val = None?; + Some(val) + } + assert_eq!(try_option_none(), None); + + fn try_option_ok() -> Result<u8, NoneError> { + let val = Some(1)?; + Ok(val) + } + assert_eq!(try_option_ok(), Ok(1)); + + fn try_option_err() -> Result<u8, NoneError> { + let val = None?; + Ok(val) + } + assert_eq!(try_option_err(), Err(NoneError)); +} diff --git a/src/libcore/tests/result.rs b/src/libcore/tests/result.rs index 4c5f19dee12..ce41bde8342 100644 --- a/src/libcore/tests/result.rs +++ b/src/libcore/tests/result.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::option::*; + fn op1() -> Result<isize, &'static str> { Ok(666) } fn op2() -> Result<isize, &'static str> { Err("sadface") } @@ -202,3 +204,30 @@ pub fn test_unwrap_or_default() { assert_eq!(op1().unwrap_or_default(), 666); assert_eq!(op2().unwrap_or_default(), 0); } + +#[test] +fn test_try() { + fn try_result_some() -> Option<u8> { + let val = Ok(1)?; + Some(val) + } + assert_eq!(try_result_some(), Some(1)); + + fn try_result_none() -> Option<u8> { + let val = Err(NoneError)?; + Some(val) + } + assert_eq!(try_result_none(), None); + + fn try_result_ok() -> Result<u8, u8> { + let val = Ok(1)?; + Ok(val) + } + assert_eq!(try_result_ok(), Ok(1)); + + fn try_result_err() -> Result<u8, u8> { + let val = Err(1)?; + Ok(val) + } + assert_eq!(try_result_err(), Err(1)); +} diff --git a/src/liblibc b/src/liblibc -Subproject 95848f9622deccc9cbadcd5d3a4faef01a90ead +Subproject 44e4018e1a37716286ec98cb5b7dd7d33ecaf94 diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index 07e933985a0..2c540c8de8f 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -509,6 +509,7 @@ impl TokenTree { Dot => op!('.'), DotDot => joint!('.', Dot), DotDotDot => joint!('.', DotDot), + DotDotEq => joint!('.', DotEq), Comma => op!(','), Semi => op!(';'), Colon => op!(':'), @@ -531,6 +532,7 @@ impl TokenTree { }) } + DotEq => unreachable!(), OpenDelim(..) | CloseDelim(..) => unreachable!(), Whitespace | Comment | Shebang(..) | Eof => unreachable!(), }; diff --git a/src/libproc_macro/quote.rs b/src/libproc_macro/quote.rs index 0db2b86b15f..8c1f6bfc11a 100644 --- a/src/libproc_macro/quote.rs +++ b/src/libproc_macro/quote.rs @@ -202,8 +202,8 @@ impl Quote for Token { gen_match! { Eq, Lt, Le, EqEq, Ne, Ge, Gt, AndAnd, OrOr, Not, Tilde, At, Dot, DotDot, DotDotDot, - Comma, Semi, Colon, ModSep, RArrow, LArrow, FatArrow, Pound, Dollar, Question, - Underscore; + DotDotEq, Comma, Semi, Colon, ModSep, RArrow, LArrow, FatArrow, Pound, Dollar, + Question, Underscore; Token::OpenDelim(delim) => quote!(rt::token::OpenDelim((quote delim))), Token::CloseDelim(delim) => quote!(rt::token::CloseDelim((quote delim))), diff --git a/src/libprofiler_builtins/Cargo.toml b/src/libprofiler_builtins/Cargo.toml index a60db313679..eb31f5730d1 100644 --- a/src/libprofiler_builtins/Cargo.toml +++ b/src/libprofiler_builtins/Cargo.toml @@ -15,4 +15,4 @@ doc = false core = { path = "../libcore" } [build-dependencies] -gcc = "0.3.50" +cc = "1.0" diff --git a/src/libprofiler_builtins/build.rs b/src/libprofiler_builtins/build.rs index 41e92b33475..8508b2dae2c 100644 --- a/src/libprofiler_builtins/build.rs +++ b/src/libprofiler_builtins/build.rs @@ -12,14 +12,14 @@ //! //! See the build.rs for libcompiler_builtins crate for details. -extern crate gcc; +extern crate cc; use std::env; use std::path::Path; fn main() { let target = env::var("TARGET").expect("TARGET was not set"); - let cfg = &mut gcc::Build::new(); + let cfg = &mut cc::Build::new(); let mut profile_sources = vec!["GCDAProfiling.c", "InstrProfiling.c", diff --git a/src/librustc/README.md b/src/librustc/README.md index 59d346db4af..87de284d011 100644 --- a/src/librustc/README.md +++ b/src/librustc/README.md @@ -37,7 +37,7 @@ incremental improves that may change.) The dependency structure of these crates is roughly a diamond: -```` +``` rustc_driver / | \ / | \ diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index b4cb39a034b..7a78765365d 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -60,7 +60,7 @@ //! user of the `DepNode` API of having to know how to compute the expected //! fingerprint for a given set of node parameters. -use hir::def_id::{CrateNum, DefId, DefIndex}; +use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX}; use hir::map::DefPathHash; use hir::{HirId, ItemLocalId}; @@ -80,14 +80,28 @@ macro_rules! erase { ($x:tt) => ({}) } -macro_rules! anon_attr_to_bool { - (anon) => (true) +macro_rules! is_anon_attr { + (anon) => (true); + ($attr:ident) => (false); +} + +macro_rules! is_input_attr { + (input) => (true); + ($attr:ident) => (false); +} + +macro_rules! contains_anon_attr { + ($($attr:ident),*) => ({$(is_anon_attr!($attr) | )* false}); +} + +macro_rules! contains_input_attr { + ($($attr:ident),*) => ({$(is_input_attr!($attr) | )* false}); } macro_rules! define_dep_nodes { (<$tcx:tt> $( - [$($anon:ident)*] + [$($attr:ident),* ] $variant:ident $(( $($tuple_arg:tt),* ))* $({ $($struct_arg_name:ident : $struct_arg_ty:ty),* })* ,)* @@ -105,7 +119,9 @@ macro_rules! define_dep_nodes { match *self { $( DepKind :: $variant => { - $(return !anon_attr_to_bool!($anon);)* + if contains_anon_attr!($($attr),*) { + return false; + } // tuple args $({ @@ -126,15 +142,20 @@ macro_rules! define_dep_nodes { } } - #[allow(unreachable_code)] #[inline] - pub fn is_anon<$tcx>(&self) -> bool { + pub fn is_anon(&self) -> bool { match *self { $( - DepKind :: $variant => { - $(return anon_attr_to_bool!($anon);)* - false - } + DepKind :: $variant => { contains_anon_attr!($($attr),*) } + )* + } + } + + #[inline] + pub fn is_input(&self) -> bool { + match *self { + $( + DepKind :: $variant => { contains_input_attr!($($attr),*) } )* } } @@ -366,6 +387,17 @@ impl DefId { } } +impl DepKind { + #[inline] + pub fn fingerprint_needed_for_crate_hash(self) -> bool { + match self { + DepKind::HirBody | + DepKind::Krate => true, + _ => false, + } + } +} + 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 @@ -378,18 +410,17 @@ define_dep_nodes!( <'tcx> // suitable wrapper, you can use `tcx.dep_graph.ignore()` to gain // access to the krate, but you must remember to add suitable // edges yourself for the individual items that you read. - [] Krate, - - // Represents the HIR node with the given node-id - [] Hir(DefId), + [input] Krate, // Represents the body of a function or method. The def-id is that of the // function/method. - [] HirBody(DefId), + [input] HirBody(DefId), + + // Represents the HIR node with the given node-id + [input] Hir(DefId), - // Represents the metadata for a given HIR node, typically found - // in an extern crate. - [] MetaData(DefId), + // Represents metadata from an extern crate. + [input] CrateMetadata(CrateNum), // Represents some artifact that we save to disk. Note that these // do not have a def-id as part of their identifier. @@ -414,6 +445,7 @@ define_dep_nodes!( <'tcx> [] BorrowCheckKrate, [] BorrowCheck(DefId), [] MirBorrowCheck(DefId), + [] UnsafetyViolations(DefId), [] RvalueCheck(DefId), [] Reachability, @@ -529,7 +561,7 @@ define_dep_nodes!( <'tcx> [] ExternCrate(DefId), [] LintLevels, [] Specializes { impl1: DefId, impl2: DefId }, - [] InScopeTraits(DefIndex), + [input] InScopeTraits(DefIndex), [] ModuleExports(DefId), [] IsSanitizerRuntime(CrateNum), [] IsProfilerRuntime(CrateNum), @@ -647,6 +679,22 @@ impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefIndex, } } +impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (CrateNum,) { + const CAN_RECONSTRUCT_QUERY_KEY: bool = true; + + fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint { + let def_id = DefId { + krate: self.0, + index: CRATE_DEF_INDEX, + }; + tcx.def_path_hash(def_id).0 + } + + fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String { + tcx.crate_name(self.0).as_str().to_string() + } +} + impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefId, DefId) { const CAN_RECONSTRUCT_QUERY_KEY: bool = false; diff --git a/src/librustc/dep_graph/edges.rs b/src/librustc/dep_graph/edges.rs index 809d1dfcf60..b12db11cb6a 100644 --- a/src/librustc/dep_graph/edges.rs +++ b/src/librustc/dep_graph/edges.rs @@ -17,7 +17,7 @@ use std::mem; use super::{DepGraphQuery, DepKind, DepNode}; use super::debug::EdgeFilter; -pub struct DepGraphEdges { +pub(super) struct DepGraphEdges { nodes: Vec<DepNode>, indices: FxHashMap<DepNode, DepNodeIndex>, edges: FxHashSet<(DepNodeIndex, DepNodeIndex)>, @@ -31,8 +31,8 @@ pub struct DepGraphEdges { } #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -pub struct DepNodeIndex { - index: u32 +pub(super) struct DepNodeIndex { + index: u32, } impl DepNodeIndex { @@ -123,6 +123,7 @@ impl DepGraphEdges { reads } = popped_node { debug_assert_eq!(node, key); + debug_assert!(!node.kind.is_input() || reads.is_empty()); let target_id = self.get_or_create_node(node); diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 7679b7e7971..d9770db9d69 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHashingContextProvider}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use session::config::OutputType; use std::cell::{Ref, RefCell}; +use std::hash::Hash; use std::rc::Rc; use util::common::{ProfileQueriesMsg, profq_msg}; @@ -22,17 +24,56 @@ use super::dep_node::{DepNode, DepKind, WorkProductId}; use super::query::DepGraphQuery; use super::raii; use super::safe::DepGraphSafe; -use super::edges::{DepGraphEdges, DepNodeIndex}; +use super::edges::{self, DepGraphEdges}; +use super::serialized::{SerializedDepGraph, SerializedDepNodeIndex}; +use super::prev::PreviousDepGraph; #[derive(Clone)] pub struct DepGraph { - data: Option<Rc<DepGraphData>> + data: Option<Rc<DepGraphData>>, + + // At the moment we are using DepNode as key here. In the future it might + // be possible to use an IndexVec<DepNodeIndex, _> here. At the moment there + // are a few problems with that: + // - Some fingerprints are needed even if incr. comp. is disabled -- yet + // we need to have a dep-graph to generate DepNodeIndices. + // - The architecture is still in flux and it's not clear what how to best + // implement things. + fingerprints: Rc<RefCell<FxHashMap<DepNode, Fingerprint>>> +} + +/// As a temporary measure, while transitioning to the new DepGraph +/// implementation, we maintain the old and the new dep-graph encoding in +/// parallel, so a DepNodeIndex actually contains two indices, one for each +/// version. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub struct DepNodeIndex { + legacy: edges::DepNodeIndex, + new: DepNodeIndexNew, +} + +impl DepNodeIndex { + pub const INVALID: DepNodeIndex = DepNodeIndex { + legacy: edges::DepNodeIndex::INVALID, + new: DepNodeIndexNew::INVALID, + }; } struct DepGraphData { - /// The actual graph data. + /// The old, initial encoding of the dependency graph. This will soon go + /// away. edges: RefCell<DepGraphEdges>, + /// The new encoding of the dependency graph, optimized for red/green + /// tracking. The `current` field is the dependency graph of only the + /// current compilation session: We don't merge the previous dep-graph into + /// current one anymore. + current: RefCell<CurrentDepGraph>, + + /// The dep-graph from the previous compilation session. It contains all + /// nodes and edges as well as all fingerprints of nodes that have them. + previous: PreviousDepGraph, + /// When we load, there may be `.o` files, cached mir, or other such /// things available to us. If we find that they are not dirty, we /// load the path to the file storing those work-products here into @@ -46,18 +87,25 @@ struct DepGraphData { } impl DepGraph { - pub fn new(enabled: bool) -> DepGraph { + + pub fn new(prev_graph: PreviousDepGraph) -> DepGraph { DepGraph { - data: if enabled { - Some(Rc::new(DepGraphData { - previous_work_products: RefCell::new(FxHashMap()), - work_products: RefCell::new(FxHashMap()), - edges: RefCell::new(DepGraphEdges::new()), - dep_node_debug: RefCell::new(FxHashMap()), - })) - } else { - None - } + data: Some(Rc::new(DepGraphData { + previous_work_products: RefCell::new(FxHashMap()), + work_products: RefCell::new(FxHashMap()), + edges: RefCell::new(DepGraphEdges::new()), + dep_node_debug: RefCell::new(FxHashMap()), + current: RefCell::new(CurrentDepGraph::new()), + previous: prev_graph, + })), + fingerprints: Rc::new(RefCell::new(FxHashMap())), + } + } + + pub fn new_disabled() -> DepGraph { + DepGraph { + data: None, + fingerprints: Rc::new(RefCell::new(FxHashMap())), } } @@ -72,7 +120,8 @@ impl DepGraph { } pub fn in_ignore<'graph>(&'graph self) -> Option<raii::IgnoreTask<'graph>> { - self.data.as_ref().map(|data| raii::IgnoreTask::new(&data.edges)) + self.data.as_ref().map(|data| raii::IgnoreTask::new(&data.edges, + &data.current)) } pub fn with_ignore<OP,R>(&self, op: OP) -> R @@ -120,6 +169,7 @@ impl DepGraph { { if let Some(ref data) = self.data { data.edges.borrow_mut().push_task(key); + data.current.borrow_mut().push_task(key); if cfg!(debug_assertions) { profq_msg(ProfileQueriesMsg::TaskBegin(key.clone())) }; @@ -135,15 +185,36 @@ impl DepGraph { if cfg!(debug_assertions) { profq_msg(ProfileQueriesMsg::TaskEnd) }; - let dep_node_index = data.edges.borrow_mut().pop_task(key); + + let dep_node_index_legacy = data.edges.borrow_mut().pop_task(key); + let dep_node_index_new = data.current.borrow_mut().pop_task(key); let mut stable_hasher = StableHasher::new(); result.hash_stable(&mut hcx, &mut stable_hasher); - let _: Fingerprint = stable_hasher.finish(); - (result, dep_node_index) + assert!(self.fingerprints + .borrow_mut() + .insert(key, stable_hasher.finish()) + .is_none()); + + (result, DepNodeIndex { + legacy: dep_node_index_legacy, + new: dep_node_index_new, + }) } else { - (task(cx, arg), DepNodeIndex::INVALID) + if key.kind.fingerprint_needed_for_crate_hash() { + let mut hcx = cx.create_stable_hashing_context(); + let result = task(cx, arg); + let mut stable_hasher = StableHasher::new(); + result.hash_stable(&mut hcx, &mut stable_hasher); + assert!(self.fingerprints + .borrow_mut() + .insert(key, stable_hasher.finish()) + .is_none()); + (result, DepNodeIndex::INVALID) + } else { + (task(cx, arg), DepNodeIndex::INVALID) + } } } @@ -154,9 +225,14 @@ impl DepGraph { { if let Some(ref data) = self.data { data.edges.borrow_mut().push_anon_task(); + data.current.borrow_mut().push_anon_task(); let result = op(); - let dep_node = data.edges.borrow_mut().pop_anon_task(dep_kind); - (result, dep_node) + let dep_node_index_legacy = data.edges.borrow_mut().pop_anon_task(dep_kind); + let dep_node_index_new = data.current.borrow_mut().pop_anon_task(dep_kind); + (result, DepNodeIndex { + legacy: dep_node_index_legacy, + new: dep_node_index_new, + }) } else { (op(), DepNodeIndex::INVALID) } @@ -166,13 +242,21 @@ impl DepGraph { pub fn read(&self, v: DepNode) { if let Some(ref data) = self.data { data.edges.borrow_mut().read(v); + + let mut current = data.current.borrow_mut(); + if let Some(&dep_node_index_new) = current.node_to_node_index.get(&v) { + current.read_index(dep_node_index_new); + } else { + bug!("DepKind {:?} should be pre-allocated but isn't.", v.kind) + } } } #[inline] pub fn read_index(&self, v: DepNodeIndex) { if let Some(ref data) = self.data { - data.edges.borrow_mut().read_index(v); + data.edges.borrow_mut().read_index(v.legacy); + data.current.borrow_mut().read_index(v.new); } } @@ -187,12 +271,12 @@ impl DepGraph { self.data.as_ref().unwrap().edges.borrow_mut().add_node(node); } - pub fn alloc_input_node(&self, node: DepNode) -> DepNodeIndex { - if let Some(ref data) = self.data { - data.edges.borrow_mut().add_node(node) - } else { - DepNodeIndex::INVALID - } + pub fn fingerprint_of(&self, dep_node: &DepNode) -> Fingerprint { + self.fingerprints.borrow()[dep_node] + } + + pub fn prev_fingerprint_of(&self, dep_node: &DepNode) -> Fingerprint { + self.data.as_ref().unwrap().previous.fingerprint_of(dep_node) } /// Indicates that a previous work product exists for `v`. This is @@ -261,6 +345,44 @@ impl DepGraph { pub(super) fn dep_node_debug_str(&self, dep_node: DepNode) -> Option<String> { self.data.as_ref().and_then(|t| t.dep_node_debug.borrow().get(&dep_node).cloned()) } + + pub fn serialize(&self) -> SerializedDepGraph { + let fingerprints = self.fingerprints.borrow(); + let current_dep_graph = self.data.as_ref().unwrap().current.borrow(); + + let nodes: IndexVec<_, _> = current_dep_graph.nodes.iter().map(|dep_node| { + let fingerprint = fingerprints.get(dep_node) + .cloned() + .unwrap_or(Fingerprint::zero()); + (*dep_node, fingerprint) + }).collect(); + + let total_edge_count: usize = current_dep_graph.edges.iter() + .map(|v| v.len()) + .sum(); + + let mut edge_list_indices = IndexVec::with_capacity(nodes.len()); + let mut edge_list_data = Vec::with_capacity(total_edge_count); + + for (current_dep_node_index, edges) in current_dep_graph.edges.iter_enumerated() { + let start = edge_list_data.len() as u32; + // This should really just be a memcpy :/ + edge_list_data.extend(edges.iter().map(|i| SerializedDepNodeIndex(i.index))); + let end = edge_list_data.len() as u32; + + debug_assert_eq!(current_dep_node_index.index(), edge_list_indices.len()); + edge_list_indices.push((start, end)); + } + + debug_assert!(edge_list_data.len() <= ::std::u32::MAX as usize); + debug_assert_eq!(edge_list_data.len(), total_edge_count); + + SerializedDepGraph { + nodes, + edge_list_indices, + edge_list_data, + } + } } /// A "work product" is an intermediate result that we save into the @@ -305,3 +427,174 @@ pub struct WorkProduct { /// Saved files associated with this CGU pub saved_files: Vec<(OutputType, String)>, } + +pub(super) struct CurrentDepGraph { + nodes: IndexVec<DepNodeIndexNew, DepNode>, + edges: IndexVec<DepNodeIndexNew, Vec<DepNodeIndexNew>>, + node_to_node_index: FxHashMap<DepNode, DepNodeIndexNew>, + + task_stack: Vec<OpenTask>, +} + +impl CurrentDepGraph { + fn new() -> CurrentDepGraph { + CurrentDepGraph { + nodes: IndexVec::new(), + edges: IndexVec::new(), + node_to_node_index: FxHashMap(), + task_stack: Vec::new(), + } + } + + pub(super) fn push_ignore(&mut self) { + self.task_stack.push(OpenTask::Ignore); + } + + pub(super) fn pop_ignore(&mut self) { + let popped_node = self.task_stack.pop().unwrap(); + debug_assert_eq!(popped_node, OpenTask::Ignore); + } + + pub(super) fn push_task(&mut self, key: DepNode) { + self.task_stack.push(OpenTask::Regular { + node: key, + reads: Vec::new(), + read_set: FxHashSet(), + }); + } + + pub(super) fn pop_task(&mut self, key: DepNode) -> DepNodeIndexNew { + let popped_node = self.task_stack.pop().unwrap(); + + if let OpenTask::Regular { + node, + read_set: _, + reads + } = popped_node { + debug_assert_eq!(node, key); + self.alloc_node(node, reads) + } else { + bug!("pop_task() - Expected regular task to be popped") + } + } + + fn push_anon_task(&mut self) { + self.task_stack.push(OpenTask::Anon { + reads: Vec::new(), + read_set: FxHashSet(), + }); + } + + fn pop_anon_task(&mut self, kind: DepKind) -> DepNodeIndexNew { + let popped_node = self.task_stack.pop().unwrap(); + + if let OpenTask::Anon { + read_set: _, + reads + } = popped_node { + let mut fingerprint = Fingerprint::zero(); + let mut hasher = StableHasher::new(); + + for &read in reads.iter() { + let read_dep_node = self.nodes[read]; + + ::std::mem::discriminant(&read_dep_node.kind).hash(&mut hasher); + + // Fingerprint::combine() is faster than sending Fingerprint + // through the StableHasher (at least as long as StableHasher + // is so slow). + fingerprint = fingerprint.combine(read_dep_node.hash); + } + + fingerprint = fingerprint.combine(hasher.finish()); + + let target_dep_node = DepNode { + kind, + hash: fingerprint, + }; + + if let Some(&index) = self.node_to_node_index.get(&target_dep_node) { + return index; + } + + self.alloc_node(target_dep_node, reads) + } else { + bug!("pop_anon_task() - Expected anonymous task to be popped") + } + } + + fn read_index(&mut self, source: DepNodeIndexNew) { + match self.task_stack.last_mut() { + Some(&mut OpenTask::Regular { + ref mut reads, + ref mut read_set, + node: _, + }) => { + if read_set.insert(source) { + reads.push(source); + } + } + Some(&mut OpenTask::Anon { + ref mut reads, + ref mut read_set, + }) => { + if read_set.insert(source) { + reads.push(source); + } + } + Some(&mut OpenTask::Ignore) | None => { + // ignore + } + } + } + + fn alloc_node(&mut self, + dep_node: DepNode, + edges: Vec<DepNodeIndexNew>) + -> DepNodeIndexNew { + debug_assert_eq!(self.edges.len(), self.nodes.len()); + debug_assert_eq!(self.node_to_node_index.len(), self.nodes.len()); + debug_assert!(!self.node_to_node_index.contains_key(&dep_node)); + let dep_node_index = DepNodeIndexNew::new(self.nodes.len()); + self.nodes.push(dep_node); + self.node_to_node_index.insert(dep_node, dep_node_index); + self.edges.push(edges); + dep_node_index + } +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub(super) struct DepNodeIndexNew { + index: u32, +} + +impl Idx for DepNodeIndexNew { + fn new(v: usize) -> DepNodeIndexNew { + assert!((v & 0xFFFF_FFFF) == v); + DepNodeIndexNew { index: v as u32 } + } + + fn index(self) -> usize { + self.index as usize + } +} + +impl DepNodeIndexNew { + const INVALID: DepNodeIndexNew = DepNodeIndexNew { + index: ::std::u32::MAX, + }; +} + +#[derive(Clone, Debug, PartialEq)] +enum OpenTask { + Regular { + node: DepNode, + reads: Vec<DepNodeIndexNew>, + read_set: FxHashSet<DepNodeIndexNew>, + }, + Anon { + reads: Vec<DepNodeIndexNew>, + read_set: FxHashSet<DepNodeIndexNew>, + }, + Ignore, +} diff --git a/src/librustc/dep_graph/mod.rs b/src/librustc/dep_graph/mod.rs index ac0c88ced93..cd77e06bdd6 100644 --- a/src/librustc/dep_graph/mod.rs +++ b/src/librustc/dep_graph/mod.rs @@ -13,19 +13,17 @@ mod dep_node; mod dep_tracking_map; mod edges; mod graph; +mod prev; mod query; mod raii; mod safe; +mod serialized; pub use self::dep_tracking_map::{DepTrackingMap, DepTrackingMapConfig}; -pub use self::dep_node::DepNode; -pub use self::dep_node::WorkProductId; -pub use self::graph::DepGraph; -pub use self::graph::WorkProduct; -pub use self::edges::DepNodeIndex; +pub use self::dep_node::{DepNode, DepKind, DepConstructor, WorkProductId}; +pub use self::graph::{DepGraph, WorkProduct, DepNodeIndex}; +pub use self::prev::PreviousDepGraph; pub use self::query::DepGraphQuery; pub use self::safe::AssertDepGraphSafe; pub use self::safe::DepGraphSafe; -pub use self::raii::DepTask; - -pub use self::dep_node::{DepKind, DepConstructor}; +pub use self::serialized::SerializedDepGraph; diff --git a/src/librustc/dep_graph/prev.rs b/src/librustc/dep_graph/prev.rs new file mode 100644 index 00000000000..882ca0414cc --- /dev/null +++ b/src/librustc/dep_graph/prev.rs @@ -0,0 +1,46 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use ich::Fingerprint; +use rustc_data_structures::fx::FxHashMap; +use super::dep_node::DepNode; +use super::serialized::{SerializedDepGraph, SerializedDepNodeIndex}; + +#[derive(Debug, RustcEncodable, RustcDecodable)] +pub struct PreviousDepGraph { + data: SerializedDepGraph, + index: FxHashMap<DepNode, SerializedDepNodeIndex>, +} + +impl PreviousDepGraph { + pub fn new(data: SerializedDepGraph) -> PreviousDepGraph { + let index: FxHashMap<_, _> = data.nodes + .iter_enumerated() + .map(|(idx, &(dep_node, _))| (dep_node, idx)) + .collect(); + PreviousDepGraph { data, index } + } + + pub fn with_edges_from<F>(&self, dep_node: &DepNode, mut f: F) + where + F: FnMut(&(DepNode, Fingerprint)), + { + let node_index = self.index[dep_node]; + self.data + .edge_targets_from(node_index) + .into_iter() + .for_each(|&index| f(&self.data.nodes[index])); + } + + pub fn fingerprint_of(&self, dep_node: &DepNode) -> Fingerprint { + let node_index = self.index[dep_node]; + self.data.nodes[node_index].1 + } +} diff --git a/src/librustc/dep_graph/raii.rs b/src/librustc/dep_graph/raii.rs index ce261ca68e8..6e9e4f4a18b 100644 --- a/src/librustc/dep_graph/raii.rs +++ b/src/librustc/dep_graph/raii.rs @@ -8,50 +8,33 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use super::DepNode; use super::edges::DepGraphEdges; +use super::graph::CurrentDepGraph; use std::cell::RefCell; -pub struct DepTask<'graph> { - graph: &'graph RefCell<DepGraphEdges>, - key: DepNode, -} - -impl<'graph> DepTask<'graph> { - pub fn new(graph: &'graph RefCell<DepGraphEdges>, - key: DepNode) - -> DepTask<'graph> { - graph.borrow_mut().push_task(key); - DepTask { - graph, - key, - } - } -} - -impl<'graph> Drop for DepTask<'graph> { - fn drop(&mut self) { - self.graph.borrow_mut().pop_task(self.key); - } -} - pub struct IgnoreTask<'graph> { - graph: &'graph RefCell<DepGraphEdges>, + legacy_graph: &'graph RefCell<DepGraphEdges>, + new_graph: &'graph RefCell<CurrentDepGraph>, } impl<'graph> IgnoreTask<'graph> { - pub fn new(graph: &'graph RefCell<DepGraphEdges>) -> IgnoreTask<'graph> { - graph.borrow_mut().push_ignore(); + pub(super) fn new(legacy_graph: &'graph RefCell<DepGraphEdges>, + new_graph: &'graph RefCell<CurrentDepGraph>) + -> IgnoreTask<'graph> { + legacy_graph.borrow_mut().push_ignore(); + new_graph.borrow_mut().push_ignore(); IgnoreTask { - graph + legacy_graph, + new_graph, } } } impl<'graph> Drop for IgnoreTask<'graph> { fn drop(&mut self) { - self.graph.borrow_mut().pop_ignore(); + self.legacy_graph.borrow_mut().pop_ignore(); + self.new_graph.borrow_mut().pop_ignore(); } } diff --git a/src/librustc/dep_graph/serialized.rs b/src/librustc/dep_graph/serialized.rs new file mode 100644 index 00000000000..6110c270086 --- /dev/null +++ b/src/librustc/dep_graph/serialized.rs @@ -0,0 +1,63 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The data that we will serialize and deserialize. + +use dep_graph::DepNode; +use ich::Fingerprint; +use rustc_data_structures::indexed_vec::{IndexVec, Idx}; + +/// The index of a DepNode in the SerializedDepGraph::nodes array. +#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug, + RustcEncodable, RustcDecodable)] +pub struct SerializedDepNodeIndex(pub u32); + +impl Idx for SerializedDepNodeIndex { + #[inline] + fn new(idx: usize) -> Self { + assert!(idx <= ::std::u32::MAX as usize); + SerializedDepNodeIndex(idx as u32) + } + + #[inline] + fn index(self) -> usize { + self.0 as usize + } +} + +/// Data for use when recompiling the **current crate**. +#[derive(Debug, RustcEncodable, RustcDecodable)] +pub struct SerializedDepGraph { + /// The set of all DepNodes in the graph + pub nodes: IndexVec<SerializedDepNodeIndex, (DepNode, Fingerprint)>, + /// For each DepNode, stores the list of edges originating from that + /// DepNode. Encoded as a [start, end) pair indexing into edge_list_data, + /// which holds the actual DepNodeIndices of the target nodes. + pub edge_list_indices: IndexVec<SerializedDepNodeIndex, (u32, u32)>, + /// A flattened list of all edge targets in the graph. Edge sources are + /// implicit in edge_list_indices. + pub edge_list_data: Vec<SerializedDepNodeIndex>, +} + +impl SerializedDepGraph { + + pub fn new() -> SerializedDepGraph { + SerializedDepGraph { + nodes: IndexVec::new(), + edge_list_indices: IndexVec::new(), + edge_list_data: Vec::new(), + } + } + + pub fn edge_targets_from(&self, source: SerializedDepNodeIndex) -> &[SerializedDepNodeIndex] { + let targets = self.edge_list_indices[source]; + &self.edge_list_data[targets.0 as usize..targets.1 as usize] + } +} diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 4d21e5e0f47..26f56ffacae 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -479,40 +479,6 @@ fn main() { ``` "##, -E0133: r##" -Unsafe code was used outside of an unsafe function or block. - -Erroneous code example: - -```compile_fail,E0133 -unsafe fn f() { return; } // This is the unsafe code - -fn main() { - f(); // error: call to unsafe function requires unsafe function or block -} -``` - -Using unsafe functionality is potentially dangerous and disallowed by safety -checks. Examples: - -* Dereferencing raw pointers -* Calling functions via FFI -* Calling functions marked unsafe - -These safety checks can be relaxed for a section of the code by wrapping the -unsafe instructions with an `unsafe` block. For instance: - -``` -unsafe fn f() { return; } - -fn main() { - unsafe { f(); } // ok! -} -``` - -See also https://doc.rust-lang.org/book/first-edition/unsafe.html -"##, - // This shouldn't really ever trigger since the repeated value error comes first E0136: r##" A binary can only have one entry point, and by default that entry point is the @@ -1139,11 +1105,13 @@ already specify all requirements that will be used for every type parameter. "##, E0281: r##" +#### Note: this error code is no longer emitted by the compiler. + You tried to supply a type which doesn't implement some trait in a location which expected that trait. This error typically occurs when working with `Fn`-based types. Erroneous code example: -```compile_fail,E0281 +```compile-fail fn foo<F: Fn(usize)>(x: F) { } fn main() { @@ -1383,74 +1351,6 @@ struct Foo<T: 'static> { ``` "##, -E0312: r##" -A lifetime of reference outlives lifetime of borrowed content. - -Erroneous code example: - -```compile_fail,E0312 -fn make_child<'tree, 'human>( - x: &'human i32, - y: &'tree i32 -) -> &'human i32 { - if x > y - { x } - else - { y } - // error: lifetime of reference outlives lifetime of borrowed content -} -``` - -The function declares that it returns a reference with the `'human` -lifetime, but it may return data with the `'tree` lifetime. As neither -lifetime is declared longer than the other, this results in an -error. Sometimes, this error is because the function *body* is -incorrect -- that is, maybe you did not *mean* to return data from -`y`. In that case, you should fix the function body. - -Often, however, the body is correct. In that case, the function -signature needs to be altered to match the body, so that the caller -understands that data from either `x` or `y` may be returned. The -simplest way to do this is to give both function parameters the *same* -named lifetime: - -``` -fn make_child<'human>( - x: &'human i32, - y: &'human i32 -) -> &'human i32 { - if x > y - { x } - else - { y } // ok! -} -``` - -However, in some cases, you may prefer to explicitly declare that one lifetime -outlives another using a `where` clause: - -``` -fn make_child<'tree, 'human>( - x: &'human i32, - y: &'tree i32 -) -> &'human i32 -where - 'tree: 'human -{ - if x > y - { x } - else - { y } // ok! -} -``` - -Here, the where clause `'tree: 'human` can be read as "the lifetime -'tree outlives the lifetime 'human" -- meaning, references with the -`'tree` lifetime live *at least as long as* references with the -`'human` lifetime. Therefore, it is safe to return data with lifetime -`'tree` when data with the lifetime `'human` is needed. -"##, - E0317: r##" This error occurs when an `if` expression without an `else` block is used in a context where a type other than `()` is expected, for example a `let` @@ -2060,6 +1960,7 @@ register_diagnostics! { // E0304, // expected signed integer constant // E0305, // expected constant E0311, // thing may not live long enough + E0312, // lifetime of reference outlives lifetime of borrowed content E0313, // lifetime of borrowed pointer outlives lifetime of captured variable E0314, // closure outlives stack frame E0315, // cannot invoke closure outside of its lifetime @@ -2086,4 +1987,6 @@ register_diagnostics! { E0566, // conflicting representation hints E0623, // lifetime mismatch where both parameters are anonymous regions E0628, // generators cannot have explicit arguments + E0631, // type mismatch in closure arguments + E0637, // "'_" is not a valid lifetime bound } diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs index 78daff9f67a..8e48352007b 100644 --- a/src/librustc/hir/def_id.rs +++ b/src/librustc/hir/def_id.rs @@ -97,6 +97,17 @@ impl serialize::UseSpecializedDecodable for CrateNum { RustcDecodable, Hash, Copy)] pub struct DefIndex(u32); +impl Idx for DefIndex { + fn new(value: usize) -> Self { + assert!(value < (u32::MAX) as usize); + DefIndex(value as u32) + } + + fn index(self) -> usize { + self.0 as usize + } +} + impl fmt::Debug for DefIndex { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 9d8075de2eb..1755b3bca05 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -422,7 +422,12 @@ pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) { pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) { visitor.visit_id(lifetime.id); - visitor.visit_name(lifetime.span, lifetime.name); + match lifetime.name { + LifetimeName::Name(name) => { + visitor.visit_name(lifetime.span, name); + } + LifetimeName::Static | LifetimeName::Implicit | LifetimeName::Underscore => {} + } } pub fn walk_lifetime_def<'v, V: Visitor<'v>>(visitor: &mut V, lifetime_def: &'v LifetimeDef) { @@ -622,7 +627,9 @@ pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V, path_span: Span, segment: &'v PathSegment) { visitor.visit_name(path_span, segment.name); - visitor.visit_path_parameters(path_span, &segment.parameters); + if let Some(ref parameters) = segment.parameters { + visitor.visit_path_parameters(path_span, parameters); + } } pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V, diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index c7ea9c47028..1fdfbe20328 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -65,7 +65,7 @@ use syntax::codemap::{self, respan, Spanned, CompilerDesugaringKind}; use syntax::std_inject; use syntax::symbol::{Symbol, keywords}; use syntax::tokenstream::{TokenStream, TokenTree, Delimited}; -use syntax::parse::token::{Token, DelimToken}; +use syntax::parse::token::Token; use syntax::util::small_vector::SmallVector; use syntax::visit::{self, Visitor}; use syntax_pos::Span; @@ -606,10 +606,12 @@ impl<'a> LoweringContext<'a> { } fn lower_token_stream(&mut self, tokens: TokenStream) -> TokenStream { - tokens.into_trees().map(|tree| self.lower_token_tree(tree)).collect() + tokens.into_trees() + .flat_map(|tree| self.lower_token_tree(tree).into_trees()) + .collect() } - fn lower_token_tree(&mut self, tree: TokenTree) -> TokenTree { + fn lower_token_tree(&mut self, tree: TokenTree) -> TokenStream { match tree { TokenTree::Token(span, token) => { self.lower_token(token, span) @@ -618,23 +620,19 @@ impl<'a> LoweringContext<'a> { TokenTree::Delimited(span, Delimited { delim: delimited.delim, tts: self.lower_token_stream(delimited.tts.into()).into(), - }) + }).into() } } } - fn lower_token(&mut self, token: Token, span: Span) -> TokenTree { + fn lower_token(&mut self, token: Token, span: Span) -> TokenStream { match token { Token::Interpolated(_) => {} - other => return TokenTree::Token(span, other), + other => return TokenTree::Token(span, other).into(), } let tts = token.interpolated_to_tokenstream(&self.sess.parse_sess, span); - let tts = self.lower_token_stream(tts); - TokenTree::Delimited(span, Delimited { - delim: DelimToken::NoDelim, - tts: tts.into(), - }) + self.lower_token_stream(tts) } fn lower_arm(&mut self, arm: &Arm) -> hir::Arm { @@ -685,17 +683,16 @@ impl<'a> LoweringContext<'a> { return self.lower_ty(ty); } TyKind::Path(ref qself, ref path) => { - let id = self.lower_node_id(t.id).node_id; + let id = self.lower_node_id(t.id); let qpath = self.lower_qpath(t.id, qself, path, ParamMode::Explicit); return self.ty_path(id, t.span, qpath); } TyKind::ImplicitSelf => { hir::TyPath(hir::QPath::Resolved(None, P(hir::Path { def: self.expect_full_def(t.id), - segments: hir_vec![hir::PathSegment { - name: keywords::SelfType.name(), - parameters: hir::PathParameters::none() - }], + segments: hir_vec![ + hir::PathSegment::from_name(keywords::SelfType.name()) + ], span: t.span, }))) } @@ -734,10 +731,12 @@ impl<'a> LoweringContext<'a> { TyKind::Mac(_) => panic!("TyMac should have been expanded by now."), }; + let LoweredNodeId { node_id, hir_id } = self.lower_node_id(t.id); P(hir::Ty { - id: self.lower_node_id(t.id).node_id, + id: node_id, node: kind, span: t.span, + hir_id, }) } @@ -863,7 +862,7 @@ impl<'a> LoweringContext<'a> { // Otherwise, the base path is an implicit `Self` type path, // e.g. `Vec` in `Vec::new` or `<I as Iterator>::Item` in // `<I as Iterator>::Item::default`. - let new_id = self.next_id().node_id; + let new_id = self.next_id(); self.ty_path(new_id, p.span, hir::QPath::Resolved(qself, path)) }; @@ -888,7 +887,7 @@ impl<'a> LoweringContext<'a> { } // Wrap the associated extension in another type node. - let new_id = self.next_id().node_id; + let new_id = self.next_id(); ty = self.ty_path(new_id, p.span, qpath); } @@ -914,12 +913,8 @@ impl<'a> LoweringContext<'a> { segments: segments.map(|segment| { self.lower_path_segment(p.span, segment, param_mode, 0, ParenthesizedGenericArgs::Err) - }).chain(name.map(|name| { - hir::PathSegment { - name, - parameters: hir::PathParameters::none() - } - })).collect(), + }).chain(name.map(|name| hir::PathSegment::from_name(name))) + .collect(), span: p.span, } } @@ -940,7 +935,7 @@ impl<'a> LoweringContext<'a> { expected_lifetimes: usize, parenthesized_generic_args: ParenthesizedGenericArgs) -> hir::PathSegment { - let mut parameters = if let Some(ref parameters) = segment.parameters { + let (mut parameters, infer_types) = if let Some(ref parameters) = segment.parameters { let msg = "parenthesized parameters may only be used with a trait"; match **parameters { PathParameters::AngleBracketed(ref data) => { @@ -951,12 +946,12 @@ impl<'a> LoweringContext<'a> { ParenthesizedGenericArgs::Warn => { self.sess.buffer_lint(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES, CRATE_NODE_ID, data.span, msg.into()); - hir::PathParameters::none() + (hir::PathParameters::none(), true) } ParenthesizedGenericArgs::Err => { struct_span_err!(self.sess, data.span, E0214, "{}", msg) .span_label(data.span, "only traits may use parentheses").emit(); - hir::PathParameters::none() + (hir::PathParameters::none(), true) } } } @@ -970,39 +965,39 @@ impl<'a> LoweringContext<'a> { }).collect(); } - hir::PathSegment { - name: self.lower_ident(segment.identifier), + hir::PathSegment::new( + self.lower_ident(segment.identifier), parameters, - } + infer_types + ) } fn lower_angle_bracketed_parameter_data(&mut self, data: &AngleBracketedParameterData, param_mode: ParamMode) - -> hir::PathParameters { + -> (hir::PathParameters, bool) { let &AngleBracketedParameterData { ref lifetimes, ref types, ref bindings, .. } = data; - hir::PathParameters { + (hir::PathParameters { lifetimes: self.lower_lifetimes(lifetimes), types: types.iter().map(|ty| self.lower_ty(ty)).collect(), - infer_types: types.is_empty() && param_mode == ParamMode::Optional, bindings: bindings.iter().map(|b| self.lower_ty_binding(b)).collect(), parenthesized: false, - } + }, types.is_empty() && param_mode == ParamMode::Optional) } fn lower_parenthesized_parameter_data(&mut self, data: &ParenthesizedParameterData) - -> hir::PathParameters { + -> (hir::PathParameters, bool) { let &ParenthesizedParameterData { ref inputs, ref output, span } = data; let inputs = inputs.iter().map(|ty| self.lower_ty(ty)).collect(); let mk_tup = |this: &mut Self, tys, span| { - P(hir::Ty { node: hir::TyTup(tys), id: this.next_id().node_id, span }) + let LoweredNodeId { node_id, hir_id } = this.next_id(); + P(hir::Ty { node: hir::TyTup(tys), id: node_id, hir_id, span }) }; - hir::PathParameters { + (hir::PathParameters { lifetimes: hir::HirVec::new(), types: hir_vec![mk_tup(self, inputs, span)], - infer_types: false, bindings: hir_vec![hir::TypeBinding { id: self.next_id().node_id, name: Symbol::intern(FN_OUTPUT_NAME), @@ -1011,7 +1006,7 @@ impl<'a> LoweringContext<'a> { span: output.as_ref().map_or(span, |ty| ty.span), }], parenthesized: true, - } + }, false) } fn lower_local(&mut self, l: &Local) -> P<hir::Local> { @@ -1108,6 +1103,10 @@ impl<'a> LoweringContext<'a> { default: tp.default.as_ref().map(|x| self.lower_ty(x)), span: tp.span, pure_wrt_drop: tp.attrs.iter().any(|attr| attr.check_name("may_dangle")), + synthetic: tp.attrs.iter() + .filter(|attr| attr.check_name("rustc_synthetic")) + .map(|_| hir::SyntheticTyParamKind::ImplTrait) + .nth(0), } } @@ -1121,7 +1120,11 @@ impl<'a> LoweringContext<'a> { fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime { hir::Lifetime { id: self.lower_node_id(l.id).node_id, - name: self.lower_ident(l.ident), + name: match self.lower_ident(l.ident) { + x if x == "'_" => hir::LifetimeName::Underscore, + x if x == "'static" => hir::LifetimeName::Static, + name => hir::LifetimeName::Name(name), + }, span: l.span, } } @@ -1865,7 +1868,7 @@ impl<'a> LoweringContext<'a> { fn lower_range_end(&mut self, e: &RangeEnd) -> hir::RangeEnd { match *e { - RangeEnd::Included => hir::RangeEnd::Included, + RangeEnd::Included(_) => hir::RangeEnd::Included, RangeEnd::Excluded => hir::RangeEnd::Excluded, } } @@ -2972,7 +2975,7 @@ impl<'a> LoweringContext<'a> { self.expr_block(block, attrs) } - fn ty_path(&mut self, id: NodeId, span: Span, qpath: hir::QPath) -> P<hir::Ty> { + fn ty_path(&mut self, id: LoweredNodeId, span: Span, qpath: hir::QPath) -> P<hir::Ty> { let mut id = id; let node = match qpath { hir::QPath::Resolved(None, path) => { @@ -2982,14 +2985,14 @@ impl<'a> LoweringContext<'a> { bound_lifetimes: hir_vec![], trait_ref: hir::TraitRef { path: path.and_then(|path| path), - ref_id: id, + ref_id: id.node_id, }, span, }; // The original ID is taken by the `PolyTraitRef`, // so the `Ty` itself needs a different one. - id = self.next_id().node_id; + id = self.next_id(); hir::TyTraitObject(hir_vec![principal], self.elided_lifetime(span)) } else { @@ -2998,14 +3001,14 @@ impl<'a> LoweringContext<'a> { } _ => hir::TyPath(qpath) }; - P(hir::Ty { id, node, span }) + P(hir::Ty { id: id.node_id, hir_id: id.hir_id, node, span }) } fn elided_lifetime(&mut self, span: Span) -> hir::Lifetime { hir::Lifetime { id: self.next_id().node_id, span, - name: keywords::Invalid.name() + name: hir::LifetimeName::Implicit, } } } diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index a54068c6483..80fadcda277 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -16,6 +16,9 @@ use std::iter::repeat; use syntax::ast::{NodeId, CRATE_NODE_ID}; use syntax_pos::Span; +use ich::StableHashingContext; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; + /// A Visitor that walks over the HIR and collects Nodes into a HIR map pub(super) struct NodeCollector<'a, 'hir> { /// The crate @@ -25,37 +28,113 @@ pub(super) struct NodeCollector<'a, 'hir> { /// The parent of this node parent_node: NodeId, + // These fields keep track of the currently relevant DepNodes during + // the visitor's traversal. current_dep_node_owner: DefIndex, - current_dep_node_index: DepNodeIndex, + current_signature_dep_index: DepNodeIndex, + current_full_dep_index: DepNodeIndex, + currently_in_body: bool, dep_graph: &'a DepGraph, definitions: &'a definitions::Definitions, + + hcx: StableHashingContext<'a>, + + // We are collecting DepNode::HirBody hashes here so we can compute the + // crate hash from then later on. + hir_body_nodes: Vec<DefPathHash>, } impl<'a, 'hir> NodeCollector<'a, 'hir> { pub(super) fn root(krate: &'hir Crate, - dep_graph: &'a DepGraph, - definitions: &'a definitions::Definitions) + dep_graph: &'a DepGraph, + definitions: &'a definitions::Definitions, + hcx: StableHashingContext<'a>) -> NodeCollector<'a, 'hir> { let root_mod_def_path_hash = definitions.def_path_hash(CRATE_DEF_INDEX); - let root_mod_dep_node = root_mod_def_path_hash.to_dep_node(DepKind::Hir); - let root_mod_dep_node_index = dep_graph.alloc_input_node(root_mod_dep_node); + + // Allocate DepNodes for the root module + let (root_mod_sig_dep_index, root_mod_full_dep_index); + { + let Crate { + ref module, + // Crate attributes are not copied over to the root `Mod`, so hash + // them explicitly here. + ref attrs, + span, + + // These fields are handled separately: + exported_macros: _, + items: _, + trait_items: _, + impl_items: _, + bodies: _, + trait_impls: _, + trait_default_impl: _, + body_ids: _, + } = *krate; + + root_mod_sig_dep_index = dep_graph.with_task( + root_mod_def_path_hash.to_dep_node(DepKind::Hir), + &hcx, + HirItemLike { item_like: (module, attrs, span), hash_bodies: false }, + identity_fn + ).1; + root_mod_full_dep_index = dep_graph.with_task( + root_mod_def_path_hash.to_dep_node(DepKind::HirBody), + &hcx, + HirItemLike { item_like: (module, attrs, span), hash_bodies: true }, + identity_fn + ).1; + } + + { + dep_graph.with_task( + DepNode::new_no_params(DepKind::AllLocalTraitImpls), + &hcx, + &krate.trait_impls, + identity_fn + ); + } + + let hir_body_nodes = vec![root_mod_def_path_hash]; let mut collector = NodeCollector { krate, map: vec![], parent_node: CRATE_NODE_ID, - current_dep_node_index: root_mod_dep_node_index, + current_signature_dep_index: root_mod_sig_dep_index, + current_full_dep_index: root_mod_full_dep_index, current_dep_node_owner: CRATE_DEF_INDEX, + currently_in_body: false, dep_graph, definitions, + hcx, + hir_body_nodes, }; - collector.insert_entry(CRATE_NODE_ID, RootCrate(root_mod_dep_node_index)); + collector.insert_entry(CRATE_NODE_ID, RootCrate(root_mod_sig_dep_index)); collector } - pub(super) fn into_map(self) -> Vec<MapEntry<'hir>> { + pub(super) fn finalize_and_compute_crate_hash(self, + crate_disambiguator: &str) + -> Vec<MapEntry<'hir>> { + let mut node_hashes: Vec<_> = self + .hir_body_nodes + .iter() + .map(|&def_path_hash| { + let dep_node = def_path_hash.to_dep_node(DepKind::HirBody); + (def_path_hash, self.dep_graph.fingerprint_of(&dep_node)) + }) + .collect(); + + node_hashes.sort_unstable_by(|&(ref d1, _), &(ref d2, _)| d1.cmp(d2)); + + self.dep_graph.with_task(DepNode::new_no_params(DepKind::Krate), + &self.hcx, + (node_hashes, crate_disambiguator), + identity_fn); self.map } @@ -70,7 +149,11 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { fn insert(&mut self, id: NodeId, node: Node<'hir>) { let parent = self.parent_node; - let dep_node_index = self.current_dep_node_index; + let dep_node_index = if self.currently_in_body { + self.current_full_dep_index + } else { + self.current_signature_dep_index + }; let entry = match node { NodeItem(n) => EntryItem(parent, dep_node_index, n), @@ -91,6 +174,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { NodeTyParam(n) => EntryTyParam(parent, dep_node_index, n), NodeVisibility(n) => EntryVisibility(parent, dep_node_index, n), NodeLocal(n) => EntryLocal(parent, dep_node_index, n), + NodeMacroDef(n) => EntryMacroDef(dep_node_index, n), }; // Make sure that the DepNode of some node coincides with the HirId @@ -127,22 +211,41 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { self.parent_node = parent_node; } - fn with_dep_node_owner<F: FnOnce(&mut Self)>(&mut self, + fn with_dep_node_owner<T: HashStable<StableHashingContext<'a>>, + F: FnOnce(&mut Self)>(&mut self, dep_node_owner: DefIndex, + item_like: &T, f: F) { let prev_owner = self.current_dep_node_owner; - let prev_index = self.current_dep_node_index; - - // When we enter a new owner (item, impl item, or trait item), we always - // start out again with DepKind::Hir. - let new_dep_node = self.definitions - .def_path_hash(dep_node_owner) - .to_dep_node(DepKind::Hir); - self.current_dep_node_index = self.dep_graph.alloc_input_node(new_dep_node); + let prev_signature_dep_index = self.current_signature_dep_index; + let prev_full_dep_index = self.current_signature_dep_index; + let prev_in_body = self.currently_in_body; + + let def_path_hash = self.definitions.def_path_hash(dep_node_owner); + + self.current_signature_dep_index = self.dep_graph.with_task( + def_path_hash.to_dep_node(DepKind::Hir), + &self.hcx, + HirItemLike { item_like, hash_bodies: false }, + identity_fn + ).1; + + self.current_full_dep_index = self.dep_graph.with_task( + def_path_hash.to_dep_node(DepKind::HirBody), + &self.hcx, + HirItemLike { item_like, hash_bodies: true }, + identity_fn + ).1; + + self.hir_body_nodes.push(def_path_hash); + self.current_dep_node_owner = dep_node_owner; + self.currently_in_body = false; f(self); - self.current_dep_node_index = prev_index; + self.currently_in_body = prev_in_body; self.current_dep_node_owner = prev_owner; + self.current_full_dep_index = prev_full_dep_index; + self.current_signature_dep_index = prev_signature_dep_index; } } @@ -169,24 +272,17 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_nested_body(&mut self, id: BodyId) { - // When we enter a body, we switch to DepKind::HirBody. - // Note that current_dep_node_index might already be DepKind::HirBody, - // e.g. when entering the body of a closure that is already part of a - // surrounding body. That's expected and not a problem. - let prev_index = self.current_dep_node_index; - let new_dep_node = self.definitions - .def_path_hash(self.current_dep_node_owner) - .to_dep_node(DepKind::HirBody); - self.current_dep_node_index = self.dep_graph.alloc_input_node(new_dep_node); + let prev_in_body = self.currently_in_body; + self.currently_in_body = true; self.visit_body(self.krate.body(id)); - self.current_dep_node_index = prev_index; + self.currently_in_body = prev_in_body; } fn visit_item(&mut self, i: &'hir Item) { debug!("visit_item: {:?}", i); debug_assert_eq!(i.hir_id.owner, self.definitions.opt_def_index(i.id).unwrap()); - self.with_dep_node_owner(i.hir_id.owner, |this| { + self.with_dep_node_owner(i.hir_id.owner, i, |this| { this.insert(i.id, NodeItem(i)); this.with_parent(i.id, |this| { match i.node { @@ -222,7 +318,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_trait_item(&mut self, ti: &'hir TraitItem) { debug_assert_eq!(ti.hir_id.owner, self.definitions.opt_def_index(ti.id).unwrap()); - self.with_dep_node_owner(ti.hir_id.owner, |this| { + self.with_dep_node_owner(ti.hir_id.owner, ti, |this| { this.insert(ti.id, NodeTraitItem(ti)); this.with_parent(ti.id, |this| { @@ -234,7 +330,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_impl_item(&mut self, ii: &'hir ImplItem) { debug_assert_eq!(ii.hir_id.owner, self.definitions.opt_def_index(ii.id).unwrap()); - self.with_dep_node_owner(ii.hir_id.owner, |this| { + self.with_dep_node_owner(ii.hir_id.owner, ii, |this| { this.insert(ii.id, NodeImplItem(ii)); this.with_parent(ii.id, |this| { @@ -328,7 +424,11 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_macro_def(&mut self, macro_def: &'hir MacroDef) { - self.insert_entry(macro_def.id, NotPresent); + let def_index = self.definitions.opt_def_index(macro_def.id).unwrap(); + + self.with_dep_node_owner(def_index, macro_def, |this| { + this.insert(macro_def.id, NodeMacroDef(macro_def)); + }); } fn visit_variant(&mut self, v: &'hir Variant, g: &'hir Generics, item_id: NodeId) { @@ -375,3 +475,28 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { self.visit_nested_impl_item(id); } } + +// We use this with DepGraph::with_task(). Since we are handling only input +// values here, the "task" computing them just passes them through. +fn identity_fn<T>(_: &StableHashingContext, item_like: T) -> T { + item_like +} + +// This is a wrapper structure that allows determining if span values within +// the wrapped item should be hashed or not. +struct HirItemLike<T> { + item_like: T, + hash_bodies: bool, +} + +impl<'hir, T> HashStable<StableHashingContext<'hir>> for HirItemLike<T> + where T: HashStable<StableHashingContext<'hir>> +{ + fn hash_stable<W: StableHasherResult>(&self, + hcx: &mut StableHashingContext<'hir>, + hasher: &mut StableHasher<W>) { + hcx.while_hashing_hir_bodies(self.hash_bodies, |hcx| { + self.item_like.hash_stable(hcx, hasher); + }); + } +} diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index b2d6886e7f2..8ce2feab06c 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -57,6 +57,7 @@ pub enum Node<'hir> { NodePat(&'hir Pat), NodeBlock(&'hir Block), NodeLocal(&'hir Local), + NodeMacroDef(&'hir MacroDef), /// NodeStructCtor represents a tuple struct. NodeStructCtor(&'hir VariantData), @@ -93,6 +94,8 @@ enum MapEntry<'hir> { EntryVisibility(NodeId, DepNodeIndex, &'hir Visibility), EntryLocal(NodeId, DepNodeIndex, &'hir Local), + EntryMacroDef(DepNodeIndex, &'hir MacroDef), + /// Roots for node trees. The DepNodeIndex is the dependency node of the /// crate's root module. RootCrate(DepNodeIndex), @@ -127,6 +130,7 @@ impl<'hir> MapEntry<'hir> { EntryLocal(id, _, _) => id, NotPresent | + EntryMacroDef(..) | RootCrate(_) => return None, }) } @@ -151,6 +155,7 @@ impl<'hir> MapEntry<'hir> { EntryTyParam(_, _, n) => NodeTyParam(n), EntryVisibility(_, _, n) => NodeVisibility(n), EntryLocal(_, _, n) => NodeLocal(n), + EntryMacroDef(_, n) => NodeMacroDef(n), NotPresent | RootCrate(_) => return None @@ -285,20 +290,12 @@ impl<'hir> Map<'hir> { EntryVisibility(_, dep_node_index, _) | EntryExpr(_, dep_node_index, _) | EntryLocal(_, dep_node_index, _) | + EntryMacroDef(dep_node_index, _) | RootCrate(dep_node_index) => { self.dep_graph.read_index(dep_node_index); } NotPresent => { - // Some nodes, notably macro definitions, are not - // present in the map for whatever reason, but - // they *do* have def-ids. So if we encounter an - // empty hole, check for that case. - if let Some(def_index) = self.definitions.opt_def_index(id) { - let def_path_hash = self.definitions.def_path_hash(def_index); - self.dep_graph.read(def_path_hash.to_dep_node(DepKind::Hir)); - } else { - bug!("called HirMap::read() with invalid NodeId") - } + bug!("called HirMap::read() with invalid NodeId") } } } @@ -805,7 +802,7 @@ impl<'hir> Map<'hir> { NodeTraitItem(ti) => ti.name, NodeVariant(v) => v.node.name, NodeField(f) => f.name, - NodeLifetime(lt) => lt.name, + NodeLifetime(lt) => lt.name.name(), NodeTyParam(tp) => tp.name, NodeBinding(&Pat { node: PatKind::Binding(_,_,l,_), .. }) => l.node, NodeStructCtor(_) => self.name(self.get_parent(id)), @@ -875,20 +872,11 @@ impl<'hir> Map<'hir> { Some(EntryVisibility(_, _, &Visibility::Restricted { ref path, .. })) => path.span, Some(EntryVisibility(_, _, v)) => bug!("unexpected Visibility {:?}", v), Some(EntryLocal(_, _, local)) => local.span, + Some(EntryMacroDef(_, macro_def)) => macro_def.span, Some(RootCrate(_)) => self.forest.krate.span, Some(NotPresent) | None => { - // Some nodes, notably macro definitions, are not - // present in the map for whatever reason, but - // they *do* have def-ids. So if we encounter an - // empty hole, check for that case. - if let Some(def_index) = self.definitions.opt_def_index(id) { - let def_path_hash = self.definitions.def_path_hash(def_index); - self.dep_graph.read(def_path_hash.to_dep_node(DepKind::Hir)); - DUMMY_SP - } else { - bug!("hir::map::Map::span: id not in map: {:?}", id) - } + bug!("hir::map::Map::span: id not in map: {:?}", id) } } } @@ -1012,15 +1000,22 @@ impl Named for StructField { fn name(&self) -> Name { self.name } } impl Named for TraitItem { fn name(&self) -> Name { self.name } } impl Named for ImplItem { fn name(&self) -> Name { self.name } } -pub fn map_crate<'hir>(forest: &'hir mut Forest, +pub fn map_crate<'hir>(sess: &::session::Session, + cstore: &::middle::cstore::CrateStore, + forest: &'hir mut Forest, definitions: &'hir Definitions) -> Map<'hir> { let map = { + let hcx = ::ich::StableHashingContext::new(sess, &forest.krate, definitions, cstore); + let mut collector = NodeCollector::root(&forest.krate, &forest.dep_graph, - &definitions); + &definitions, + hcx); intravisit::walk_crate(&mut collector, &forest.krate); - collector.into_map() + + let crate_disambiguator = sess.local_crate_disambiguator().as_str(); + collector.finalize_and_compute_crate_hash(&crate_disambiguator) }; if log_enabled!(::log::LogLevel::Debug) { @@ -1103,6 +1098,7 @@ impl<'a> print::State<'a> { // printing. NodeStructCtor(_) => bug!("cannot print isolated StructCtor"), NodeLocal(a) => self.print_local_decl(&a), + NodeMacroDef(_) => bug!("cannot print MacroDef"), } } } @@ -1219,6 +1215,9 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { Some(NodeVisibility(ref vis)) => { format!("visibility {:?}{}", vis, id_str) } + Some(NodeMacroDef(_)) => { + format!("macro {}{}", path_str(), id_str) + } None => { format!("unknown node{}", id_str) } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index c250695f361..9bfedd7a381 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -145,7 +145,27 @@ pub struct Lifetime { /// HIR lowering inserts these placeholders in type paths that /// refer to type definitions needing lifetime parameters, /// `&T` and `&mut T`, and trait objects without `... + 'a`. - pub name: Name, + pub name: LifetimeName, +} + +#[derive(Debug, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)] +pub enum LifetimeName { + Implicit, + Underscore, + Static, + Name(Name), +} + +impl LifetimeName { + pub fn name(&self) -> Name { + use self::LifetimeName::*; + match *self { + Implicit => keywords::Invalid.name(), + Underscore => Symbol::intern("'_"), + Static => keywords::StaticLifetime.name(), + Name(name) => name, + } + } } impl fmt::Debug for Lifetime { @@ -159,11 +179,15 @@ impl fmt::Debug for Lifetime { impl Lifetime { pub fn is_elided(&self) -> bool { - self.name == keywords::Invalid.name() + use self::LifetimeName::*; + match self.name { + Implicit | Underscore => true, + Static | Name(_) => false, + } } pub fn is_static(&self) -> bool { - self.name == "'static" + self.name == LifetimeName::Static } } @@ -212,7 +236,13 @@ pub struct PathSegment { /// this is more than just simple syntactic sugar; the use of /// parens affects the region binding rules, so we preserve the /// distinction. - pub parameters: PathParameters, + pub parameters: Option<P<PathParameters>>, + + /// 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 `<Vec<..>>::new::<..>`. + pub infer_types: bool, } impl PathSegment { @@ -220,9 +250,35 @@ impl PathSegment { pub fn from_name(name: Name) -> PathSegment { PathSegment { name, - parameters: PathParameters::none() + infer_types: true, + parameters: None + } + } + + pub fn new(name: Name, parameters: PathParameters, infer_types: bool) -> Self { + PathSegment { + name, + infer_types, + parameters: if parameters.is_empty() { + None + } else { + Some(P(parameters)) + } } } + + // FIXME: hack required because you can't create a static + // PathParameters, so you can't just return a &PathParameters. + pub fn with_parameters<F, R>(&self, f: F) -> R + where F: FnOnce(&PathParameters) -> R + { + let dummy = PathParameters::none(); + f(if let Some(ref params) = self.parameters { + ¶ms + } else { + &dummy + }) + } } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] @@ -231,11 +287,6 @@ pub struct PathParameters { pub lifetimes: HirVec<Lifetime>, /// The type parameters for this path segment, if present. pub types: HirVec<P<Ty>>, - /// 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 `<Vec<..>>::new::<..>`. - pub infer_types: bool, /// Bindings (equality constraints) on associated types, if present. /// E.g., `Foo<A=Bar>`. pub bindings: HirVec<TypeBinding>, @@ -250,12 +301,16 @@ impl PathParameters { Self { lifetimes: HirVec::new(), types: HirVec::new(), - infer_types: true, bindings: HirVec::new(), parenthesized: false, } } + pub fn is_empty(&self) -> bool { + self.lifetimes.is_empty() && self.types.is_empty() && + self.bindings.is_empty() && !self.parenthesized + } + pub fn inputs(&self) -> &[P<Ty>] { if self.parenthesized { if let Some(ref ty) = self.types.get(0) { @@ -296,6 +351,7 @@ pub struct TyParam { pub default: Option<P<Ty>>, pub span: Span, pub pure_wrt_drop: bool, + pub synthetic: Option<SyntheticTyParamKind>, } /// Represents lifetimes and type parameters attached to a declaration @@ -364,6 +420,13 @@ impl Generics { } } +/// Synthetic Type Parameters are converted to an other form during lowering, this allows +/// to track the original form they had. Usefull for error messages. +#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub enum SyntheticTyParamKind { + ImplTrait +} + /// A `where` clause in a definition #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct WhereClause { @@ -1330,6 +1393,7 @@ pub struct Ty { pub id: NodeId, pub node: Ty_, pub span: Span, + pub hir_id: HirId, } impl fmt::Debug for Ty { diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 41a253f7904..5daffe667fd 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -1213,11 +1213,17 @@ impl<'a> State<'a> { self.print_expr_maybe_paren(&args[0], parser::PREC_POSTFIX)?; self.s.word(".")?; self.print_name(segment.name)?; - if !segment.parameters.lifetimes.is_empty() || - !segment.parameters.types.is_empty() || - !segment.parameters.bindings.is_empty() { - self.print_path_parameters(&segment.parameters, true)?; - } + + segment.with_parameters(|parameters| { + if !parameters.lifetimes.is_empty() || + !parameters.types.is_empty() || + !parameters.bindings.is_empty() + { + self.print_path_parameters(¶meters, segment.infer_types, true) + } else { + Ok(()) + } + })?; self.print_call_post(base_args) } @@ -1564,8 +1570,12 @@ impl<'a> State<'a> { } if segment.name != keywords::CrateRoot.name() && segment.name != keywords::DollarCrate.name() { - self.print_name(segment.name)?; - self.print_path_parameters(&segment.parameters, colons_before_params)?; + self.print_name(segment.name)?; + segment.with_parameters(|parameters| { + self.print_path_parameters(parameters, + segment.infer_types, + colons_before_params) + })?; } } @@ -1593,7 +1603,11 @@ impl<'a> State<'a> { if segment.name != keywords::CrateRoot.name() && segment.name != keywords::DollarCrate.name() { self.print_name(segment.name)?; - self.print_path_parameters(&segment.parameters, colons_before_params)?; + segment.with_parameters(|parameters| { + self.print_path_parameters(parameters, + segment.infer_types, + colons_before_params) + })?; } } @@ -1601,7 +1615,11 @@ impl<'a> State<'a> { self.s.word("::")?; let item_segment = path.segments.last().unwrap(); self.print_name(item_segment.name)?; - self.print_path_parameters(&item_segment.parameters, colons_before_params) + item_segment.with_parameters(|parameters| { + self.print_path_parameters(parameters, + item_segment.infer_types, + colons_before_params) + }) } hir::QPath::TypeRelative(ref qself, ref item_segment) => { self.s.word("<")?; @@ -1609,13 +1627,18 @@ impl<'a> State<'a> { self.s.word(">")?; self.s.word("::")?; self.print_name(item_segment.name)?; - self.print_path_parameters(&item_segment.parameters, colons_before_params) + item_segment.with_parameters(|parameters| { + self.print_path_parameters(parameters, + item_segment.infer_types, + colons_before_params) + }) } } } fn print_path_parameters(&mut self, parameters: &hir::PathParameters, + infer_types: bool, colons_before_params: bool) -> io::Result<()> { if parameters.parenthesized { @@ -1652,7 +1675,7 @@ impl<'a> State<'a> { // FIXME(eddyb) This would leak into error messages, e.g.: // "non-exhaustive patterns: `Some::<..>(_)` not covered". - if parameters.infer_types && false { + if infer_types && false { start_or_comma(self)?; self.s.word("..")?; } @@ -1975,7 +1998,7 @@ impl<'a> State<'a> { } pub fn print_lifetime(&mut self, lifetime: &hir::Lifetime) -> io::Result<()> { - self.print_name(lifetime.name) + self.print_name(lifetime.name.name()) } pub fn print_lifetime_def(&mut self, lifetime: &hir::LifetimeDef) -> io::Result<()> { diff --git a/src/librustc/ich/caching_codemap_view.rs b/src/librustc/ich/caching_codemap_view.rs index 71e442b3bb2..e3934590278 100644 --- a/src/librustc/ich/caching_codemap_view.rs +++ b/src/librustc/ich/caching_codemap_view.rs @@ -22,6 +22,7 @@ struct CacheEntry { file_index: usize, } +#[derive(Clone)] pub struct CachingCodemapView<'cm> { codemap: &'cm CodeMap, line_cache: [CacheEntry; 3], diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs index 64fc63002da..e7a26e14db5 100644 --- a/src/librustc/ich/hcx.rs +++ b/src/librustc/ich/hcx.rs @@ -43,6 +43,7 @@ thread_local!(static IGNORED_ATTR_NAMES: RefCell<FxHashSet<Symbol>> = /// 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). +#[derive(Clone)] pub struct StableHashingContext<'gcx> { sess: &'gcx Session, definitions: &'gcx Definitions, @@ -169,6 +170,11 @@ impl<'gcx> StableHashingContext<'gcx> { } #[inline] + pub fn node_to_hir_id(&self, node_id: ast::NodeId) -> hir::HirId { + self.definitions.node_to_hir_id(node_id) + } + + #[inline] pub fn hash_spans(&self) -> bool { self.hash_spans } @@ -259,6 +265,18 @@ impl<'a, 'gcx, 'lcx> StableHashingContextProvider for TyCtxt<'a, 'gcx, 'lcx> { } } + +impl<'gcx> StableHashingContextProvider for StableHashingContext<'gcx> { + type ContextType = StableHashingContext<'gcx>; + fn create_stable_hashing_context(&self) -> Self::ContextType { + self.clone() + } +} + +impl<'gcx> ::dep_graph::DepGraphSafe for StableHashingContext<'gcx> { +} + + impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::BodyId { fn hash_stable<W: StableHasherResult>(&self, hcx: &mut StableHashingContext<'gcx>, diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 9582b03ce1c..776f85cf5da 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -123,6 +123,13 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::ImplItemId { } } +impl_stable_hash_for!(enum hir::LifetimeName { + Implicit, + Underscore, + Static, + Name(name) +}); + impl_stable_hash_for!(struct hir::Lifetime { id, span, @@ -143,13 +150,13 @@ impl_stable_hash_for!(struct hir::Path { impl_stable_hash_for!(struct hir::PathSegment { name, + infer_types, parameters }); impl_stable_hash_for!(struct hir::PathParameters { lifetimes, types, - infer_types, bindings, parenthesized }); @@ -170,7 +177,8 @@ impl_stable_hash_for!(struct hir::TyParam { bounds, default, span, - pure_wrt_drop + pure_wrt_drop, + synthetic }); impl_stable_hash_for!(struct hir::Generics { @@ -180,6 +188,10 @@ impl_stable_hash_for!(struct hir::Generics { span }); +impl_stable_hash_for!(enum hir::SyntheticTyParamKind { + ImplTrait +}); + impl_stable_hash_for!(struct hir::WhereClause { id, predicates @@ -238,6 +250,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Ty { hcx.while_hashing_hir_bodies(true, |hcx| { let hir::Ty { id: _, + hir_id: _, ref node, ref span, } = *self; @@ -691,7 +704,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::TraitItem { hcx: &mut StableHashingContext<'gcx>, hasher: &mut StableHasher<W>) { let hir::TraitItem { - id, + id: _, hir_id: _, name, ref attrs, @@ -700,7 +713,6 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::TraitItem { } = *self; hcx.hash_hir_item_like(attrs, |hcx| { - id.hash_stable(hcx, hasher); name.hash_stable(hcx, hasher); attrs.hash_stable(hcx, hasher); node.hash_stable(hcx, hasher); @@ -725,7 +737,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::ImplItem { hcx: &mut StableHashingContext<'gcx>, hasher: &mut StableHasher<W>) { let hir::ImplItem { - id, + id: _, hir_id: _, name, ref vis, @@ -736,7 +748,6 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::ImplItem { } = *self; hcx.hash_hir_item_like(attrs, |hcx| { - id.hash_stable(hcx, hasher); name.hash_stable(hcx, hasher); vis.hash_stable(hcx, hasher); defaultness.hash_stable(hcx, hasher); @@ -1160,6 +1171,25 @@ for hir::TraitCandidate { } } +impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for hir::TraitCandidate { + type KeyType = (DefPathHash, Option<(DefPathHash, hir::ItemLocalId)>); + + fn to_stable_hash_key(&self, + hcx: &StableHashingContext<'gcx>) + -> Self::KeyType { + let hir::TraitCandidate { + def_id, + import_id, + } = *self; + + let import_id = import_id.map(|node_id| hcx.node_to_hir_id(node_id)) + .map(|hir_id| (hcx.local_def_path_hash(hir_id.owner), + hir_id.local_id)); + (hcx.def_path_hash(def_id), import_id) + } +} + + impl_stable_hash_for!(struct hir::Freevar { def, span diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs index 9b6613e4cae..4bda89690b7 100644 --- a/src/librustc/ich/impls_mir.rs +++ b/src/librustc/ich/impls_mir.rs @@ -28,10 +28,12 @@ impl_stable_hash_for!(struct mir::LocalDecl<'tcx> { name, source_info, internal, + lexical_scope, is_user_variable }); impl_stable_hash_for!(struct mir::UpvarDecl { debug_name, by_ref }); impl_stable_hash_for!(struct mir::BasicBlockData<'tcx> { statements, terminator, is_cleanup }); +impl_stable_hash_for!(struct mir::UnsafetyViolation { source_info, description, lint_node_id }); impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Terminator<'gcx> { @@ -75,6 +77,22 @@ for mir::Terminator<'gcx> { } } +impl<'gcx, T> HashStable<StableHashingContext<'gcx>> for mir::ClearOnDecode<T> + where T: HashStable<StableHashingContext<'gcx>> +{ + #[inline] + fn hash_stable<W: StableHasherResult>(&self, + hcx: &mut StableHashingContext<'gcx>, + hasher: &mut StableHasher<W>) { + mem::discriminant(self).hash_stable(hcx, hasher); + match *self { + mir::ClearOnDecode::Clear => {} + mir::ClearOnDecode::Set(ref value) => { + value.hash_stable(hcx, hasher); + } + } + } +} impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Local { #[inline] @@ -347,6 +365,26 @@ for mir::ProjectionElem<'gcx, V, T> } impl_stable_hash_for!(struct mir::VisibilityScopeData { span, parent_scope }); +impl_stable_hash_for!(struct mir::VisibilityScopeInfo { + lint_root, safety +}); + +impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Safety { + fn hash_stable<W: StableHasherResult>(&self, + hcx: &mut StableHashingContext<'gcx>, + hasher: &mut StableHasher<W>) { + mem::discriminant(self).hash_stable(hcx, hasher); + + match *self { + mir::Safety::Safe | + mir::Safety::BuiltinUnsafe | + mir::Safety::FnUnsafe => {} + mir::Safety::ExplicitUnsafe(node_id) => { + node_id.hash_stable(hcx, hasher); + } + } + } +} impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Operand<'gcx> { fn hash_stable<W: StableHasherResult>(&self, diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index 56ec6a65eb6..669e1ba773e 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -272,6 +272,8 @@ fn hash_token<'gcx, W: StableHasherResult>(token: &token::Token, token::Token::Dot | token::Token::DotDot | token::Token::DotDotDot | + token::Token::DotDotEq | + token::Token::DotEq | token::Token::Comma | token::Token::Semi | token::Token::Colon | diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index e3ecaae953a..fe060aaf426 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -463,7 +463,8 @@ impl_stable_hash_for!(struct ty::TypeParameterDef { index, has_default, object_lifetime_default, - pure_wrt_drop + pure_wrt_drop, + synthetic }); impl<'gcx, T> HashStable<StableHashingContext<'gcx>> @@ -514,13 +515,8 @@ impl_stable_hash_for!(enum ty::cast::CastKind { FnPtrAddrCast }); -impl_stable_hash_for!(enum ::middle::region::Scope { - Node(local_id), - Destruction(local_id), - CallSite(local_id), - Arguments(local_id), - Remainder(block_remainder) -}); +impl_stable_hash_for!(struct ::middle::region::FirstStatementIndex { idx }); +impl_stable_hash_for!(struct ::middle::region::Scope { id, code }); impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for region::Scope { type KeyType = region::Scope; diff --git a/src/librustc/infer/error_reporting/different_lifetimes.rs b/src/librustc/infer/error_reporting/different_lifetimes.rs index 6c57130a995..ee30db26255 100644 --- a/src/librustc/infer/error_reporting/different_lifetimes.rs +++ b/src/librustc/infer/error_reporting/different_lifetimes.rs @@ -18,6 +18,7 @@ use infer::region_inference::RegionResolutionError; use hir::map as hir_map; use middle::resolve_lifetime as rl; use hir::intravisit::{self, Visitor, NestedVisitorMap}; +use infer::error_reporting::util::AnonymousArgInfo; impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // This method prints the error message for lifetime errors when both the concerned regions @@ -57,6 +58,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let ty_sup = or_false!(self.find_anon_type(sup, &bregion_sup)); let ty_sub = or_false!(self.find_anon_type(sub, &bregion_sub)); + debug!("try_report_anon_anon_conflict: found_arg1={:?} sup={:?} br1={:?}", ty_sub, sup, @@ -66,56 +68,70 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { sub, bregion_sub); - let (main_label, label1, label2) = if let (Some(sup_arg), Some(sub_arg)) = - (self.find_arg_with_region(sup, sup), self.find_arg_with_region(sub, sub)) { + let (ty_sup, ty_fndecl_sup) = ty_sup; + let (ty_sub, ty_fndecl_sub) = ty_sub; - let (anon_arg_sup, is_first_sup, anon_arg_sub, is_first_sub) = - (sup_arg.arg, sup_arg.is_first, sub_arg.arg, sub_arg.is_first); - if self.is_self_anon(is_first_sup, scope_def_id_sup) || - self.is_self_anon(is_first_sub, scope_def_id_sub) { - return false; - } + let AnonymousArgInfo { arg: anon_arg_sup, .. } = + or_false!(self.find_arg_with_region(sup, sup)); + let AnonymousArgInfo { arg: anon_arg_sub, .. } = + or_false!(self.find_arg_with_region(sub, sub)); - if self.is_return_type_anon(scope_def_id_sup, bregion_sup) || - self.is_return_type_anon(scope_def_id_sub, bregion_sub) { - return false; - } + let sup_is_ret_type = + self.is_return_type_anon(scope_def_id_sup, bregion_sup, ty_fndecl_sup); + let sub_is_ret_type = + self.is_return_type_anon(scope_def_id_sub, bregion_sub, ty_fndecl_sub); - if anon_arg_sup == anon_arg_sub { - (format!("this type was declared with multiple lifetimes..."), - format!(" with one lifetime"), - format!(" into the other")) - } else { - let span_label_var1 = if let Some(simple_name) = anon_arg_sup.pat.simple_name() { - format!(" from `{}`", simple_name) - } else { - format!("") - }; + let span_label_var1 = if let Some(simple_name) = anon_arg_sup.pat.simple_name() { + format!(" from `{}`", simple_name) + } else { + format!("") + }; + + let span_label_var2 = if let Some(simple_name) = anon_arg_sub.pat.simple_name() { + format!(" into `{}`", simple_name) + } else { + format!("") + }; + + + let (span_1, span_2, main_label, span_label) = match (sup_is_ret_type, sub_is_ret_type) { + (None, None) => { + let (main_label_1, span_label_1) = if ty_sup == ty_sub { - let span_label_var2 = if let Some(simple_name) = anon_arg_sub.pat.simple_name() { - format!(" into `{}`", simple_name) + (format!("this type is declared with multiple lifetimes..."), + format!("...but data{} flows{} here", + format!(" with one lifetime"), + format!(" into the other"))) } else { - format!("") + (format!("these two types are declared with different lifetimes..."), + format!("...but data{} flows{} here", + span_label_var1, + span_label_var2)) }; + (ty_sup.span, ty_sub.span, main_label_1, span_label_1) + } - let span_label = - format!("these two types are declared with different lifetimes...",); - - (span_label, span_label_var1, span_label_var2) + (Some(ret_span), _) => { + (ty_sub.span, + ret_span, + format!("this parameter and the return type are declared \ + with different lifetimes...",), + format!("...but data{} is returned here", span_label_var1)) + } + (_, Some(ret_span)) => { + (ty_sup.span, + ret_span, + format!("this parameter and the return type are declared \ + with different lifetimes...",), + format!("...but data{} is returned here", span_label_var1)) } - } else { - debug!("no arg with anon region found"); - debug!("try_report_anon_anon_conflict: is_suitable(sub) = {:?}", - self.is_suitable_region(sub)); - debug!("try_report_anon_anon_conflict: is_suitable(sup) = {:?}", - self.is_suitable_region(sup)); - return false; }; + struct_span_err!(self.tcx.sess, span, E0623, "lifetime mismatch") - .span_label(ty_sup.span, main_label) - .span_label(ty_sub.span, format!("")) - .span_label(span, format!("...but data{} flows{} here", label1, label2)) + .span_label(span_1, main_label) + .span_label(span_2, format!("")) + .span_label(span, span_label) .emit(); return true; } @@ -135,28 +151,32 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// ``` /// The function returns the nested type corresponding to the anonymous region /// for e.g. `&u8` and Vec<`&u8`. - pub fn find_anon_type(&self, region: Region<'tcx>, br: &ty::BoundRegion) -> Option<&hir::Ty> { + pub fn find_anon_type(&self, + region: Region<'tcx>, + br: &ty::BoundRegion) + -> Option<(&hir::Ty, &hir::FnDecl)> { if let Some(anon_reg) = self.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 inputs: &[_] = match self.tcx.hir.get(node_id) { + let fndecl = match self.tcx.hir.get(node_id) { hir_map::NodeItem(&hir::Item { node: hir::ItemFn(ref fndecl, ..), .. }) => { - &fndecl.inputs + &fndecl } hir_map::NodeTraitItem(&hir::TraitItem { - node: hir::TraitItemKind::Method(ref fndecl, ..), .. - }) => &fndecl.decl.inputs, + node: hir::TraitItemKind::Method(ref m, ..), .. + }) | hir_map::NodeImplItem(&hir::ImplItem { - node: hir::ImplItemKind::Method(ref fndecl, ..), .. - }) => &fndecl.decl.inputs, - - _ => &[], + node: hir::ImplItemKind::Method(ref m, ..), .. + }) => &m.decl, + _ => return None, }; - return inputs + return fndecl + .inputs .iter() - .filter_map(|arg| self.find_component_for_bound_region(&**arg, br)) - .next(); + .filter_map(|arg| self.find_component_for_bound_region(arg, br)) + .next() + .map(|ty| (ty, &**fndecl)); } } None diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index a88e90caee3..3f22950fc77 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -72,6 +72,8 @@ use syntax::ast::DUMMY_NODE_ID; use syntax_pos::{Pos, Span}; use errors::{DiagnosticBuilder, DiagnosticStyledString}; +use rustc_data_structures::indexed_vec::Idx; + mod note; mod need_type_info; @@ -152,21 +154,21 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { return; } }; - let scope_decorated_tag = match scope { - region::Scope::Node(_) => tag, - region::Scope::CallSite(_) => { + let scope_decorated_tag = match scope.data() { + region::ScopeData::Node(_) => tag, + region::ScopeData::CallSite(_) => { "scope of call-site for function" } - region::Scope::Arguments(_) => { + region::ScopeData::Arguments(_) => { "scope of function body" } - region::Scope::Destruction(_) => { + region::ScopeData::Destruction(_) => { new_string = format!("destruction scope surrounding {}", tag); &new_string[..] } - region::Scope::Remainder(r) => { + region::ScopeData::Remainder(r) => { new_string = format!("block suffix following statement {}", - r.first_statement_index); + r.first_statement_index.index()); &new_string[..] } }; @@ -333,11 +335,20 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { GenericBoundFailure(..) => true, }; - if errors.iter().all(|e| is_bound_failure(e)) { + + let mut errors = if errors.iter().all(|e| is_bound_failure(e)) { errors.clone() } else { errors.iter().filter(|&e| !is_bound_failure(e)).cloned().collect() - } + }; + + // sort the errors by span, for better error message stability. + errors.sort_by_key(|u| match *u { + ConcreteFailure(ref sro, _, _) => sro.span(), + GenericBoundFailure(ref sro, _, _) => sro.span(), + SubSupConflict(ref rvo, _, _, _, _) => rvo.span(), + }); + errors } /// Adds a note if the types come from similarly named crates @@ -774,10 +785,44 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { bound_kind: GenericKind<'tcx>, sub: Region<'tcx>) { - // FIXME: it would be better to report the first error message - // with the span of the parameter itself, rather than the span - // where the error was detected. But that span is not readily - // accessible. + // Attempt to obtain the span of the parameter so we can + // suggest adding an explicit lifetime bound to it. + let type_param_span = match (self.in_progress_tables, bound_kind) { + (Some(ref table), GenericKind::Param(ref param)) => { + let table = table.borrow(); + table.local_id_root.and_then(|did| { + let generics = self.tcx.generics_of(did); + // Account for the case where `did` corresponds to `Self`, which doesn't have + // the expected type argument. + if generics.types.len() > 0 { + let type_param = generics.type_param(param); + let hir = &self.tcx.hir; + hir.as_local_node_id(type_param.def_id).map(|id| { + // Get the `hir::TyParam` to verify wether it already has any bounds. + // We do this to avoid suggesting code that ends up as `T: 'a'b`, + // instead we suggest `T: 'a + 'b` in that case. + let has_lifetimes = if let hir_map::NodeTyParam(ref p) = hir.get(id) { + p.bounds.len() > 0 + } else { + false + }; + let sp = hir.span(id); + // `sp` only covers `T`, change it so that it covers + // `T:` when appropriate + let sp = if has_lifetimes { + sp.to(sp.next_point().next_point()) + } else { + sp + }; + (sp, has_lifetimes) + }) + } else { + None + } + }) + } + _ => None, + }; let labeled_user_string = match bound_kind { GenericKind::Param(ref p) => @@ -799,6 +844,26 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { return; } + fn binding_suggestion<'tcx, S: fmt::Display>(err: &mut DiagnosticBuilder<'tcx>, + type_param_span: Option<(Span, bool)>, + bound_kind: GenericKind<'tcx>, + sub: S) { + let consider = &format!("consider adding an explicit lifetime bound `{}: {}`...", + 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); + err.span_suggestion_short(sp, consider, suggestion); + } else { + err.help(consider); + } + } + let mut err = match *sub { ty::ReEarlyBound(_) | ty::ReFree(ty::FreeRegion {bound_region: ty::BrNamed(..), ..}) => { @@ -808,9 +873,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { E0309, "{} may not live long enough", labeled_user_string); - err.help(&format!("consider adding an explicit lifetime bound `{}: {}`...", - bound_kind, - sub)); + binding_suggestion(&mut err, type_param_span, bound_kind, sub); err } @@ -821,9 +884,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { E0310, "{} may not live long enough", labeled_user_string); - err.help(&format!("consider adding an explicit lifetime \ - bound `{}: 'static`...", - bound_kind)); + binding_suggestion(&mut err, type_param_span, bound_kind, "'static"); err } diff --git a/src/librustc/infer/error_reporting/named_anon_conflict.rs b/src/librustc/infer/error_reporting/named_anon_conflict.rs index a3bbdab497a..80fb4ce8e03 100644 --- a/src/librustc/infer/error_reporting/named_anon_conflict.rs +++ b/src/librustc/infer/error_reporting/named_anon_conflict.rs @@ -35,15 +35,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // only introduced anonymous regions in parameters) as well as a // version new_ty of its type where the anonymous region is replaced // with the named one.//scope_def_id - let (named, anon_arg_info, region_info) = + let (named, anon, anon_arg_info, region_info) = if self.is_named_region(sub) && self.is_suitable_region(sup).is_some() && self.find_arg_with_region(sup, sub).is_some() { (sub, + sup, self.find_arg_with_region(sup, sub).unwrap(), self.is_suitable_region(sup).unwrap()) } else if self.is_named_region(sup) && self.is_suitable_region(sub).is_some() && self.find_arg_with_region(sub, sup).is_some() { (sup, + sub, self.find_arg_with_region(sub, sup).unwrap(), self.is_suitable_region(sub).unwrap()) } else { @@ -76,33 +78,29 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { return false; } - if self.is_return_type_anon(scope_def_id, br) { - debug!("try_report_named_anon_conflict: is_return_type_anon({:?}, {:?}) = true", - scope_def_id, - br); - return false; - } else if self.is_self_anon(is_first, scope_def_id) { - debug!("try_report_named_anon_conflict: is_self_anon({:?}, {:?}) = true", - is_first, - scope_def_id); - return false; + if let Some((_, fndecl)) = self.find_anon_type(anon, &br) { + if self.is_return_type_anon(scope_def_id, br, fndecl).is_some() || + self.is_self_anon(is_first, scope_def_id) { + return false; + } + } + + let (error_var, span_label_var) = if let Some(simple_name) = arg.pat.simple_name() { + (format!("the type of `{}`", simple_name), format!("the type of `{}`", simple_name)) } else { - let (error_var, span_label_var) = if let Some(simple_name) = arg.pat.simple_name() { - (format!("the type of `{}`", simple_name), format!("the type of `{}`", simple_name)) - } else { - ("parameter type".to_owned(), "type".to_owned()) - }; + ("parameter type".to_owned(), "type".to_owned()) + }; + + struct_span_err!(self.tcx.sess, + span, + E0621, + "explicit lifetime required in {}", + error_var) + .span_label(arg.pat.span, + format!("consider changing {} to `{}`", span_label_var, new_ty)) + .span_label(span, format!("lifetime `{}` required", named)) + .emit(); + return true; - struct_span_err!(self.tcx.sess, - span, - E0621, - "explicit lifetime required in {}", - error_var) - .span_label(arg.pat.span, - format!("consider changing {} to `{}`", span_label_var, new_ty)) - .span_label(span, format!("lifetime `{}` required", named)) - .emit(); - return true; - } } } diff --git a/src/librustc/infer/error_reporting/util.rs b/src/librustc/infer/error_reporting/util.rs index 94faec464b2..47db3f1b792 100644 --- a/src/librustc/infer/error_reporting/util.rs +++ b/src/librustc/infer/error_reporting/util.rs @@ -15,6 +15,7 @@ use infer::InferCtxt; use ty::{self, Region, Ty}; use hir::def_id::DefId; use hir::map as hir_map; +use syntax_pos::Span; macro_rules! or_false { ($v:expr) => { @@ -163,7 +164,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // Here, we check for the case where the anonymous region // is in the return type. // FIXME(#42703) - Need to handle certain cases here. - pub fn is_return_type_anon(&self, scope_def_id: DefId, br: ty::BoundRegion) -> bool { + pub fn is_return_type_anon(&self, + scope_def_id: DefId, + br: ty::BoundRegion, + decl: &hir::FnDecl) + -> Option<Span> { let ret_ty = self.tcx.type_of(scope_def_id); match ret_ty.sty { ty::TyFnDef(_, _) => { @@ -171,12 +176,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let late_bound_regions = self.tcx .collect_referenced_late_bound_regions(&sig.output()); if late_bound_regions.iter().any(|r| *r == br) { - return true; + return Some(decl.output.span()); } } _ => {} } - false + None } // Here we check for the case where anonymous region // corresponds to self and if yes, we display E0312. diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index cd39ef70946..1e90aa47267 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -111,7 +111,6 @@ pub mod middle { pub mod dataflow; pub mod dead; pub mod dependency_format; - pub mod effect; pub mod entry; pub mod exported_symbols; pub mod free_region; diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 21852468146..5fe75d8ca71 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -30,7 +30,7 @@ declare_lint! { declare_lint! { pub UNUSED_EXTERN_CRATES, - Warn, + Allow, "extern crates that are never used" } diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index 21dfd3267df..4bc37747f2a 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -384,6 +384,11 @@ impl LintLevelMap { self.sets.get_lint_level(lint, *idx, None) }) } + + /// Returns if this `id` has lint level information. + pub fn lint_level_set(&self, id: HirId) -> Option<u32> { + self.id_to_set.get(&id).cloned() + } } impl<'gcx> HashStable<StableHashingContext<'gcx>> for LintLevelMap { diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index de647913f0f..a97bfa05369 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -267,6 +267,8 @@ pub trait CrateStore { fn export_macros_untracked(&self, cnum: CrateNum); fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind; fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol; + fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> Symbol; + fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh; fn struct_field_names_untracked(&self, def: DefId) -> Vec<ast::Name>; fn item_children_untracked(&self, did: DefId, sess: &Session) -> Vec<def::Export>; fn load_macro_untracked(&self, did: DefId, sess: &Session) -> LoadedMacro; @@ -336,6 +338,10 @@ impl CrateStore for DummyCrateStore { fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind { bug!("is_explicitly_linked") } fn export_macros_untracked(&self, cnum: CrateNum) { bug!("export_macros") } fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol { bug!("crate_name") } + fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> Symbol { + bug!("crate_disambiguator") + } + fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh { bug!("crate_hash") } // resolve fn def_key(&self, def: DefId) -> DefKey { bug!("def_key") } diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 66a425a2d47..a9d9f6f28ec 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -553,9 +553,22 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item) { if self.should_warn_about_item(item) { + // For items that have a definition with a signature followed by a + // block, point only at the signature. + let span = match item.node { + hir::ItemFn(..) | + hir::ItemMod(..) | + hir::ItemEnum(..) | + hir::ItemStruct(..) | + hir::ItemUnion(..) | + hir::ItemTrait(..) | + hir::ItemDefaultImpl(..) | + hir::ItemImpl(..) => self.tcx.sess.codemap().def_span(item.span), + _ => item.span, + }; self.warn_dead_code( item.id, - item.span, + span, item.name, item.node.descriptive_variant() ); @@ -570,8 +583,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> { g: &'tcx hir::Generics, id: ast::NodeId) { if self.should_warn_about_variant(&variant.node) { - self.warn_dead_code(variant.node.data.id(), variant.span, - variant.node.name, "variant"); + self.warn_dead_code(variant.node.data.id(), variant.span, variant.node.name, "variant"); } else { intravisit::walk_variant(self, variant, g, id); } @@ -596,15 +608,17 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> { match impl_item.node { hir::ImplItemKind::Const(_, body_id) => { if !self.symbol_is_live(impl_item.id, None) { - self.warn_dead_code(impl_item.id, impl_item.span, - impl_item.name, "associated const"); + self.warn_dead_code(impl_item.id, + impl_item.span, + impl_item.name, + "associated const"); } self.visit_nested_body(body_id) } hir::ImplItemKind::Method(_, body_id) => { if !self.symbol_is_live(impl_item.id, None) { - self.warn_dead_code(impl_item.id, impl_item.span, - impl_item.name, "method"); + let span = self.tcx.sess.codemap().def_span(impl_item.span); + self.warn_dead_code(impl_item.id, span, impl_item.name, "method"); } self.visit_nested_body(body_id) } diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs index 1c7d0b76a64..db0ecb6aa5e 100644 --- a/src/librustc/middle/dependency_format.rs +++ b/src/librustc/middle/dependency_format.rs @@ -112,52 +112,61 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, return Vec::new(); } - match ty { - // If the global prefer_dynamic switch is turned off, first attempt - // static linkage (this can fail). - config::CrateTypeExecutable if !sess.opts.cg.prefer_dynamic => { - if let Some(v) = attempt_static(tcx) { - return v; - } - } + let preferred_linkage = match ty { + // cdylibs must have all static dependencies. + config::CrateTypeCdylib => Linkage::Static, + + // Generating a dylib without `-C prefer-dynamic` means that we're going + // to try to eagerly statically link all dependencies. This is normally + // done for end-product dylibs, not intermediate products. + config::CrateTypeDylib if !sess.opts.cg.prefer_dynamic => Linkage::Static, + config::CrateTypeDylib => Linkage::Dynamic, + + // If the global prefer_dynamic switch is turned off, or the final + // executable will be statically linked, prefer static crate linkage. + config::CrateTypeExecutable if !sess.opts.cg.prefer_dynamic || + sess.crt_static() => Linkage::Static, + config::CrateTypeExecutable => Linkage::Dynamic, + + // proc-macro crates are required to be dylibs, and they're currently + // required to link to libsyntax as well. + config::CrateTypeProcMacro => Linkage::Dynamic, // No linkage happens with rlibs, we just needed the metadata (which we // got long ago), so don't bother with anything. - config::CrateTypeRlib => return Vec::new(), - - // Staticlibs and cdylibs must have all static dependencies. If any fail - // to be found, we generate some nice pretty errors. - config::CrateTypeStaticlib | - config::CrateTypeCdylib => { - if let Some(v) = attempt_static(tcx) { - return v; - } + config::CrateTypeRlib => Linkage::NotLinked, + + // staticlibs must have all static dependencies. + config::CrateTypeStaticlib => Linkage::Static, + }; + + if preferred_linkage == Linkage::NotLinked { + // If the crate is not linked, there are no link-time dependencies. + return Vec::new(); + } + + if preferred_linkage == Linkage::Static { + // Attempt static linkage first. For dylibs and executables, we may be + // able to retry below with dynamic linkage. + if let Some(v) = attempt_static(tcx) { + return v; + } + + // Staticlibs, cdylibs, and static executables must have all static + // dependencies. If any are not found, generate some nice pretty errors. + if ty == config::CrateTypeCdylib || ty == config::CrateTypeStaticlib || + (ty == config::CrateTypeExecutable && sess.crt_static() && + !sess.target.target.options.crt_static_allows_dylibs) { for &cnum in tcx.crates().iter() { if tcx.dep_kind(cnum).macros_only() { continue } let src = tcx.used_crate_source(cnum); if src.rlib.is_some() { continue } - sess.err(&format!("dependency `{}` not found in rlib format", + sess.err(&format!("crate `{}` required to be available in rlib format, \ + but was not found in this form", tcx.crate_name(cnum))); } return Vec::new(); } - - // Generating a dylib without `-C prefer-dynamic` means that we're going - // to try to eagerly statically link all dependencies. This is normally - // done for end-product dylibs, not intermediate products. - config::CrateTypeDylib if !sess.opts.cg.prefer_dynamic => { - if let Some(v) = attempt_static(tcx) { - return v; - } - } - - // Everything else falls through below. This will happen either with the - // `-C prefer-dynamic` or because we're a proc-macro crate. Note that - // proc-macro crates are required to be dylibs, and they're currently - // required to link to libsyntax as well. - config::CrateTypeExecutable | - config::CrateTypeDylib | - config::CrateTypeProcMacro => {}, } let mut formats = FxHashMap(); @@ -236,10 +245,9 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, Linkage::Static => "rlib", _ => "dylib", }; - let name = tcx.crate_name(cnum); - sess.err(&format!("crate `{}` required to be available in {}, \ - but it was not available in this form", - name, kind)); + sess.err(&format!("crate `{}` required to be available in {} format, \ + but was not found in this form", + tcx.crate_name(cnum), kind)); } } } diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs deleted file mode 100644 index 7290353e48b..00000000000 --- a/src/librustc/middle/effect.rs +++ /dev/null @@ -1,316 +0,0 @@ -// Copyright 2012-2013 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 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Enforces the Rust effect system. Currently there is just one effect, -//! `unsafe`. -use self::RootUnsafeContext::*; - -use ty::{self, TyCtxt}; -use lint; -use lint::builtin::UNUSED_UNSAFE; - -use hir::def::Def; -use hir::intravisit::{self, FnKind, Visitor, NestedVisitorMap}; -use hir::{self, PatKind}; -use syntax::ast; -use syntax_pos::Span; -use util::nodemap::FxHashSet; - -#[derive(Copy, Clone)] -struct UnsafeContext { - push_unsafe_count: usize, - root: RootUnsafeContext, -} - -impl UnsafeContext { - fn new(root: RootUnsafeContext) -> UnsafeContext { - UnsafeContext { root: root, push_unsafe_count: 0 } - } -} - -#[derive(Copy, Clone, PartialEq)] -enum RootUnsafeContext { - SafeContext, - UnsafeFn, - UnsafeBlock(ast::NodeId), -} - -struct EffectCheckVisitor<'a, 'tcx: 'a> { - tcx: TyCtxt<'a, 'tcx, 'tcx>, - tables: &'a ty::TypeckTables<'tcx>, - body_id: hir::BodyId, - - /// Whether we're in an unsafe context. - unsafe_context: UnsafeContext, - used_unsafe: FxHashSet<ast::NodeId>, -} - -impl<'a, 'tcx> EffectCheckVisitor<'a, 'tcx> { - fn require_unsafe_ext(&mut self, node_id: ast::NodeId, span: Span, - description: &str, is_lint: bool) { - if self.unsafe_context.push_unsafe_count > 0 { return; } - match self.unsafe_context.root { - SafeContext => { - if is_lint { - self.tcx.lint_node(lint::builtin::SAFE_EXTERN_STATICS, - node_id, - span, - &format!("{} requires unsafe function or \ - block (error E0133)", description)); - } else { - // Report an error. - struct_span_err!( - self.tcx.sess, span, E0133, - "{} requires unsafe function or block", description) - .span_label(span, description) - .emit(); - } - } - UnsafeBlock(block_id) => { - // OK, but record this. - debug!("effect: recording unsafe block as used: {}", block_id); - self.used_unsafe.insert(block_id); - } - UnsafeFn => {} - } - } - - fn require_unsafe(&mut self, span: Span, description: &str) { - self.require_unsafe_ext(ast::DUMMY_NODE_ID, span, description, false) - } -} - -impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::None - } - - fn visit_nested_body(&mut self, body: hir::BodyId) { - let old_tables = self.tables; - let old_body_id = self.body_id; - self.tables = self.tcx.body_tables(body); - self.body_id = body; - let body = self.tcx.hir.body(body); - self.visit_body(body); - self.tables = old_tables; - self.body_id = old_body_id; - } - - fn visit_fn(&mut self, fn_kind: FnKind<'tcx>, fn_decl: &'tcx hir::FnDecl, - body_id: hir::BodyId, span: Span, id: ast::NodeId) { - - let (is_item_fn, is_unsafe_fn) = match fn_kind { - FnKind::ItemFn(_, _, unsafety, ..) => - (true, unsafety == hir::Unsafety::Unsafe), - FnKind::Method(_, sig, ..) => - (true, sig.unsafety == hir::Unsafety::Unsafe), - _ => (false, false), - }; - - let old_unsafe_context = self.unsafe_context; - if is_unsafe_fn { - self.unsafe_context = UnsafeContext::new(UnsafeFn) - } else if is_item_fn { - self.unsafe_context = UnsafeContext::new(SafeContext) - } - - intravisit::walk_fn(self, fn_kind, fn_decl, body_id, span, id); - - self.unsafe_context = old_unsafe_context - } - - fn visit_block(&mut self, block: &'tcx hir::Block) { - let old_unsafe_context = self.unsafe_context; - match block.rules { - hir::UnsafeBlock(source) => { - // By default only the outermost `unsafe` block is - // "used" and so nested unsafe blocks are pointless - // (the inner ones are unnecessary and we actually - // warn about them). As such, there are two cases when - // we need to create a new context, when we're - // - outside `unsafe` and found a `unsafe` block - // (normal case) - // - inside `unsafe`, found an `unsafe` block - // created internally to the compiler - // - // The second case is necessary to ensure that the - // compiler `unsafe` blocks don't accidentally "use" - // external blocks (e.g. `unsafe { println("") }`, - // expands to `unsafe { ... unsafe { ... } }` where - // the inner one is compiler generated). - if self.unsafe_context.root == SafeContext || source == hir::CompilerGenerated { - self.unsafe_context.root = UnsafeBlock(block.id) - } - } - hir::PushUnsafeBlock(..) => { - self.unsafe_context.push_unsafe_count = - self.unsafe_context.push_unsafe_count.checked_add(1).unwrap(); - } - hir::PopUnsafeBlock(..) => { - self.unsafe_context.push_unsafe_count = - self.unsafe_context.push_unsafe_count.checked_sub(1).unwrap(); - } - hir::DefaultBlock => {} - } - - intravisit::walk_block(self, block); - - self.unsafe_context = old_unsafe_context; - - // Don't warn about generated blocks, that'll just pollute the output. - match block.rules { - hir::UnsafeBlock(hir::UserProvided) => {} - _ => return, - } - if self.used_unsafe.contains(&block.id) { - return - } - - /// Return the NodeId for an enclosing scope that is also `unsafe` - fn is_enclosed(tcx: TyCtxt, - used_unsafe: &FxHashSet<ast::NodeId>, - id: ast::NodeId) -> Option<(String, ast::NodeId)> { - 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(hir::map::NodeItem(&hir::Item { - node: hir::ItemFn(_, hir::Unsafety::Unsafe, _, _, _, _), - .. - })) = tcx.hir.find(parent_id) { - Some(("fn".to_string(), parent_id)) - } else { - is_enclosed(tcx, used_unsafe, parent_id) - } - } else { - None - } - } - - let mut db = self.tcx.struct_span_lint_node(UNUSED_UNSAFE, - block.id, - block.span, - "unnecessary `unsafe` block"); - db.span_label(block.span, "unnecessary `unsafe` block"); - if let Some((kind, id)) = is_enclosed(self.tcx, &self.used_unsafe, block.id) { - db.span_note(self.tcx.hir.span(id), - &format!("because it's nested under this `unsafe` {}", kind)); - } - db.emit(); - } - - fn visit_expr(&mut self, expr: &'tcx hir::Expr) { - match expr.node { - hir::ExprMethodCall(..) => { - let def_id = self.tables.type_dependent_defs()[expr.hir_id].def_id(); - let sig = self.tcx.fn_sig(def_id); - debug!("effect: method call case, signature is {:?}", - sig); - - if sig.0.unsafety == hir::Unsafety::Unsafe { - self.require_unsafe(expr.span, - "invocation of unsafe method") - } - } - hir::ExprCall(ref base, _) => { - let base_type = self.tables.expr_ty_adjusted(base); - debug!("effect: call case, base type is {:?}", - base_type); - match base_type.sty { - ty::TyFnDef(..) | ty::TyFnPtr(_) => { - if base_type.fn_sig(self.tcx).unsafety() == hir::Unsafety::Unsafe { - self.require_unsafe(expr.span, "call to unsafe function") - } - } - _ => {} - } - } - hir::ExprUnary(hir::UnDeref, ref base) => { - let base_type = self.tables.expr_ty_adjusted(base); - debug!("effect: unary case, base type is {:?}", - base_type); - if let ty::TyRawPtr(_) = base_type.sty { - self.require_unsafe(expr.span, "dereference of raw pointer") - } - } - hir::ExprInlineAsm(..) => { - self.require_unsafe(expr.span, "use of inline assembly"); - } - hir::ExprPath(hir::QPath::Resolved(_, ref path)) => { - if let Def::Static(def_id, mutbl) = path.def { - if mutbl { - self.require_unsafe(expr.span, "use of mutable static"); - } else if match self.tcx.hir.get_if_local(def_id) { - Some(hir::map::NodeForeignItem(..)) => true, - Some(..) => false, - None => self.tcx.is_foreign_item(def_id), - } { - self.require_unsafe_ext(expr.id, expr.span, "use of extern static", true); - } - } - } - hir::ExprField(ref base_expr, field) => { - if let ty::TyAdt(adt, ..) = self.tables.expr_ty_adjusted(base_expr).sty { - if adt.is_union() { - self.require_unsafe(field.span, "access to union field"); - } - } - } - hir::ExprAssign(ref lhs, ref rhs) => { - if let hir::ExprField(ref base_expr, field) = lhs.node { - if let ty::TyAdt(adt, ..) = self.tables.expr_ty_adjusted(base_expr).sty { - if adt.is_union() { - let field_ty = self.tables.expr_ty_adjusted(lhs); - let owner_def_id = self.tcx.hir.body_owner_def_id(self.body_id); - let param_env = self.tcx.param_env(owner_def_id); - if field_ty.moves_by_default(self.tcx, param_env, field.span) { - self.require_unsafe(field.span, - "assignment to non-`Copy` union field"); - } - // Do not walk the field expr again. - intravisit::walk_expr(self, base_expr); - intravisit::walk_expr(self, rhs); - return - } - } - } - } - _ => {} - } - - intravisit::walk_expr(self, expr); - } - - fn visit_pat(&mut self, pat: &'tcx hir::Pat) { - if let PatKind::Struct(_, ref fields, _) = pat.node { - if let ty::TyAdt(adt, ..) = self.tables.pat_ty(pat).sty { - if adt.is_union() { - for field in fields { - self.require_unsafe(field.span, "matching on union field"); - } - } - } - } - - intravisit::walk_pat(self, pat); - } -} - -pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - let mut visitor = EffectCheckVisitor { - tcx, - tables: &ty::TypeckTables::empty(None), - body_id: hir::BodyId { node_id: ast::CRATE_NODE_ID }, - unsafe_context: UnsafeContext::new(SafeContext), - used_unsafe: FxHashSet(), - }; - - tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor()); -} diff --git a/src/librustc/middle/free_region.rs b/src/librustc/middle/free_region.rs index 4de86b66916..49a241b86e0 100644 --- a/src/librustc/middle/free_region.rs +++ b/src/librustc/middle/free_region.rs @@ -117,7 +117,7 @@ impl<'a, 'gcx, 'tcx> RegionRelations<'a, 'gcx, 'tcx> { } } -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct FreeRegionMap<'tcx> { // Stores the relation `a < b`, where `a` and `b` are regions. // diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 0c0b9697338..679c4f17a6c 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -280,8 +280,6 @@ language_item_table! { EqTraitLangItem, "eq", eq_trait; OrdTraitLangItem, "ord", ord_trait; - StrEqFnLangItem, "str_eq", str_eq_fn; - // A number of panic-related lang items. The `panic` item corresponds to // divide-by-zero and various panic cases with `match`. The // `panic_bounds_check` item is for indexing arrays. diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index fa29dda86dd..55d0c6b4c66 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -310,7 +310,8 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { hir_map::NodeVariant(_) | hir_map::NodeStructCtor(_) | hir_map::NodeField(_) | - hir_map::NodeTy(_) => {} + hir_map::NodeTy(_) | + hir_map::NodeMacroDef(_) => {} _ => { bug!("found unexpected thingy in worklist: {}", self.tcx.hir.node_to_string(search_item)) diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 6cce7447669..59c9e8b4c43 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -18,6 +18,7 @@ use ich::{StableHashingContext, NodeIdHashingMode}; use util::nodemap::{FxHashMap, FxHashSet}; use ty; +use std::fmt; use std::mem; use std::rc::Rc; use syntax::codemap; @@ -31,6 +32,7 @@ use hir::def_id::DefId; use hir::intravisit::{self, Visitor, NestedVisitorMap}; use hir::{Block, Arm, Pat, PatKind, Stmt, Expr, Local}; use mir::transform::MirSource; +use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; @@ -95,8 +97,24 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, /// placate the same deriving in `ty::FreeRegion`, but we may want to /// actually attach a more meaningful ordering to scopes than the one /// generated via deriving here. +/// +/// Scope is a bit-packed to save space - if `code` is SCOPE_DATA_REMAINDER_MAX +/// or less, it is a `ScopeData::Remainder`, otherwise it is a type specified +/// by the bitpacking. +#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy, RustcEncodable, RustcDecodable)] +pub struct Scope { + pub(crate) id: hir::ItemLocalId, + pub(crate) code: u32 +} + +const SCOPE_DATA_NODE: u32 = !0; +const SCOPE_DATA_CALLSITE: u32 = !1; +const SCOPE_DATA_ARGUMENTS: u32 = !2; +const SCOPE_DATA_DESTRUCTION: u32 = !3; +const SCOPE_DATA_REMAINDER_MAX: u32 = !4; + #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug, Copy, RustcEncodable, RustcDecodable)] -pub enum Scope { +pub enum ScopeData { Node(hir::ItemLocalId), // Scope of the call-site for a function or closure @@ -135,7 +153,90 @@ pub enum Scope { RustcDecodable, Debug, Copy)] pub struct BlockRemainder { pub block: hir::ItemLocalId, - pub first_statement_index: u32, + pub first_statement_index: FirstStatementIndex, +} + +#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable, + RustcDecodable, Copy)] +pub struct FirstStatementIndex { pub idx: u32 } + +impl Idx for FirstStatementIndex { + fn new(idx: usize) -> Self { + assert!(idx <= SCOPE_DATA_REMAINDER_MAX as usize); + FirstStatementIndex { idx: idx as u32 } + } + + fn index(self) -> usize { + self.idx as usize + } +} + +impl fmt::Debug for FirstStatementIndex { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self.index(), formatter) + } +} + +impl From<ScopeData> for Scope { + #[inline] + fn from(scope_data: ScopeData) -> Self { + let (id, code) = match scope_data { + ScopeData::Node(id) => (id, SCOPE_DATA_NODE), + ScopeData::CallSite(id) => (id, SCOPE_DATA_CALLSITE), + ScopeData::Arguments(id) => (id, SCOPE_DATA_ARGUMENTS), + ScopeData::Destruction(id) => (id, SCOPE_DATA_DESTRUCTION), + ScopeData::Remainder(r) => (r.block, r.first_statement_index.index() as u32) + }; + Self { id, code } + } +} + +impl fmt::Debug for Scope { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self.data(), formatter) + } +} + +#[allow(non_snake_case)] +impl Scope { + #[inline] + pub fn data(self) -> ScopeData { + match self.code { + SCOPE_DATA_NODE => ScopeData::Node(self.id), + SCOPE_DATA_CALLSITE => ScopeData::CallSite(self.id), + SCOPE_DATA_ARGUMENTS => ScopeData::Arguments(self.id), + SCOPE_DATA_DESTRUCTION => ScopeData::Destruction(self.id), + idx => ScopeData::Remainder(BlockRemainder { + block: self.id, + first_statement_index: FirstStatementIndex { idx } + }) + } + } + + #[inline] + pub fn Node(id: hir::ItemLocalId) -> Self { + Self::from(ScopeData::Node(id)) + } + + #[inline] + pub fn CallSite(id: hir::ItemLocalId) -> Self { + Self::from(ScopeData::CallSite(id)) + } + + #[inline] + pub fn Arguments(id: hir::ItemLocalId) -> Self { + Self::from(ScopeData::Arguments(id)) + } + + #[inline] + pub fn Destruction(id: hir::ItemLocalId) -> Self { + Self::from(ScopeData::Destruction(id)) + } + + #[inline] + pub fn Remainder(r: BlockRemainder) -> Self { + Self::from(ScopeData::Remainder(r)) + } } impl Scope { @@ -144,16 +245,7 @@ impl Scope { /// NB: 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 { - match *self { - Scope::Node(id) => id, - - // These cases all return rough approximations to the - // precise scope denoted by `self`. - Scope::Remainder(br) => br.block, - Scope::Destruction(id) | - Scope::CallSite(id) | - Scope::Arguments(id) => id, - } + self.id } pub fn node_id(&self, tcx: TyCtxt, scope_tree: &ScopeTree) -> ast::NodeId { @@ -177,7 +269,7 @@ impl Scope { return DUMMY_SP; } let span = tcx.hir.span(node_id); - if let Scope::Remainder(r) = *self { + if let ScopeData::Remainder(r) = self.data() { if let hir::map::NodeBlock(ref blk) = tcx.hir.get(node_id) { // Want span for scope starting after the // indexed statement and ending at end of @@ -187,7 +279,7 @@ impl Scope { // (This is the special case aluded to in the // doc-comment for this method) - let stmt_span = blk.stmts[r.first_statement_index as usize].span; + let stmt_span = blk.stmts[r.first_statement_index.index()].span; // To avoid issues with macro-generated spans, the span // of the statement must be nested in that of the block. @@ -201,7 +293,7 @@ impl Scope { } /// The region scope tree encodes information about region relationships. -#[derive(Default)] +#[derive(Default, Debug)] pub struct ScopeTree { /// If not empty, this body is the root of this region hierarchy. root_body: Option<hir::HirId>, @@ -387,7 +479,7 @@ impl<'tcx> ScopeTree { } // record the destruction scopes for later so we can query them - if let Scope::Destruction(n) = child { + if let ScopeData::Destruction(n) = child.data() { self.destruction_scopes.insert(n, child); } } @@ -482,8 +574,8 @@ impl<'tcx> ScopeTree { let mut id = Scope::Node(expr_id); while let Some(&p) = self.parent_map.get(&id) { - match p { - Scope::Destruction(..) => { + match p.data() { + ScopeData::Destruction(..) => { debug!("temporary_scope({:?}) = {:?} [enclosing]", expr_id, id); return Some(id); @@ -573,9 +665,9 @@ impl<'tcx> ScopeTree { // infer::region_inference for more details. let a_root_scope = a_ancestors[a_index]; let b_root_scope = a_ancestors[a_index]; - return match (a_root_scope, b_root_scope) { - (Scope::Destruction(a_root_id), - Scope::Destruction(b_root_id)) => { + return match (a_root_scope.data(), b_root_scope.data()) { + (ScopeData::Destruction(a_root_id), + ScopeData::Destruction(b_root_id)) => { if self.closure_is_enclosed_by(a_root_id, b_root_id) { // `a` is enclosed by `b`, hence `b` is the ancestor of everything in `a` scope_b @@ -764,7 +856,7 @@ fn resolve_block<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, blk: visitor.enter_scope( Scope::Remainder(BlockRemainder { block: blk.hir_id.local_id, - first_statement_index: i as u32 + first_statement_index: FirstStatementIndex::new(i) }) ); visitor.cx.var_parent = visitor.cx.parent; @@ -915,8 +1007,10 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr: // Keep traversing up while we can. match visitor.scope_tree.parent_map.get(&scope) { // Don't cross from closure bodies to their parent. - Some(&Scope::CallSite(_)) => break, - Some(&superscope) => scope = superscope, + Some(&superscope) => match superscope.data() { + ScopeData::CallSite(_) => break, + _ => scope = superscope + }, None => break } } diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 2d201e5935e..d0c5460fa97 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -46,14 +46,16 @@ pub enum Region { } impl Region { - fn early(hir_map: &Map, index: &mut u32, def: &hir::LifetimeDef) -> (ast::Name, Region) { + fn early(hir_map: &Map, index: &mut u32, def: &hir::LifetimeDef) + -> (hir::LifetimeName, Region) + { let i = *index; *index += 1; let def_id = hir_map.local_def_id(def.lifetime.id); (def.lifetime.name, Region::EarlyBound(i, def_id)) } - fn late(hir_map: &Map, def: &hir::LifetimeDef) -> (ast::Name, Region) { + fn late(hir_map: &Map, def: &hir::LifetimeDef) -> (hir::LifetimeName, Region) { let depth = ty::DebruijnIndex::new(1); let def_id = hir_map.local_def_id(def.lifetime.id); (def.lifetime.name, Region::LateBound(depth, def_id)) @@ -198,7 +200,7 @@ enum Scope<'a> { /// it should be shifted by the number of `Binder`s in between the /// declaration `Binder` and the location it's referenced from. Binder { - lifetimes: FxHashMap<ast::Name, Region>, + lifetimes: FxHashMap<hir::LifetimeName, Region>, s: ScopeRef<'a> }, @@ -443,7 +445,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { fn visit_path(&mut self, path: &'tcx hir::Path, _: ast::NodeId) { for (i, segment) in path.segments.iter().enumerate() { let depth = path.segments.len() - i - 1; - self.visit_segment_parameters(path.def, depth, &segment.parameters); + if let Some(ref parameters) = segment.parameters { + self.visit_segment_parameters(path.def, depth, parameters); + } } } @@ -654,7 +658,7 @@ fn extract_labels(ctxt: &mut LifetimeContext, body: &hir::Body) { Scope::Binder { ref lifetimes, s } => { // FIXME (#24278): non-hygienic comparison - if let Some(def) = lifetimes.get(&label) { + if let Some(def) = lifetimes.get(&hir::LifetimeName::Name(label)) { let node_id = hir_map.as_local_node_id(def.id().unwrap()) .unwrap(); @@ -692,7 +696,7 @@ fn compute_object_lifetime_defaults(sess: &Session, hir_map: &Map) Set1::Empty => "BaseDefault".to_string(), Set1::One(Region::Static) => "'static".to_string(), Set1::One(Region::EarlyBound(i, _)) => { - generics.lifetimes[i as usize].lifetime.name.to_string() + generics.lifetimes[i as usize].lifetime.name.name().to_string() } Set1::One(_) => bug!(), Set1::Many => "Ambiguous".to_string(), @@ -714,7 +718,7 @@ fn compute_object_lifetime_defaults(sess: &Session, hir_map: &Map) /// for each type parameter. fn object_lifetime_defaults_for_item(hir_map: &Map, generics: &hir::Generics) -> Vec<ObjectLifetimeDefault> { - fn add_bounds(set: &mut Set1<ast::Name>, bounds: &[hir::TyParamBound]) { + fn add_bounds(set: &mut Set1<hir::LifetimeName>, bounds: &[hir::TyParamBound]) { for bound in bounds { if let hir::RegionTyParamBound(ref lifetime) = *bound { set.insert(lifetime.name); @@ -754,7 +758,7 @@ fn object_lifetime_defaults_for_item(hir_map: &Map, generics: &hir::Generics) match set { Set1::Empty => Set1::Empty, Set1::One(name) => { - if name == "'static" { + if name == hir::LifetimeName::Static { Set1::One(Region::Static) } else { generics.lifetimes.iter().enumerate().find(|&(_, def)| { @@ -922,7 +926,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { self.insert_lifetime(lifetime_ref, def); } else { struct_span_err!(self.sess, lifetime_ref.span, E0261, - "use of undeclared lifetime name `{}`", lifetime_ref.name) + "use of undeclared lifetime name `{}`", lifetime_ref.name.name()) .span_label(lifetime_ref.span, "undeclared lifetime") .emit(); } @@ -1422,13 +1426,17 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let lifetime_i = &lifetimes[i]; for lifetime in lifetimes { - if lifetime.lifetime.is_static() { - let lifetime = lifetime.lifetime; - let mut err = struct_span_err!(self.sess, lifetime.span, E0262, - "invalid lifetime parameter name: `{}`", lifetime.name); - err.span_label(lifetime.span, - format!("{} is a reserved lifetime name", lifetime.name)); - err.emit(); + match lifetime.lifetime.name { + hir::LifetimeName::Static | hir::LifetimeName::Underscore => { + let lifetime = lifetime.lifetime; + let name = lifetime.name.name(); + let mut err = struct_span_err!(self.sess, lifetime.span, E0262, + "invalid lifetime parameter name: `{}`", name); + err.span_label(lifetime.span, + format!("{} is a reserved lifetime name", name)); + err.emit(); + } + hir::LifetimeName::Implicit | hir::LifetimeName::Name(_) => {} } } @@ -1439,7 +1447,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { if lifetime_i.lifetime.name == lifetime_j.lifetime.name { struct_span_err!(self.sess, lifetime_j.lifetime.span, E0263, "lifetime name `{}` declared twice in the same scope", - lifetime_j.lifetime.name) + lifetime_j.lifetime.name.name()) .span_label(lifetime_j.lifetime.span, "declared twice") .span_label(lifetime_i.lifetime.span, @@ -1452,15 +1460,27 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { self.check_lifetime_def_for_shadowing(old_scope, &lifetime_i.lifetime); for bound in &lifetime_i.bounds { - if !bound.is_static() { - self.resolve_lifetime_ref(bound); - } else { - self.insert_lifetime(bound, Region::Static); - self.sess.struct_span_warn(lifetime_i.lifetime.span.to(bound.span), - &format!("unnecessary lifetime parameter `{}`", lifetime_i.lifetime.name)) - .help(&format!("you can use the `'static` lifetime directly, in place \ - of `{}`", lifetime_i.lifetime.name)) - .emit(); + match bound.name { + hir::LifetimeName::Underscore => { + let mut err = struct_span_err!(self.sess, bound.span, E0637, + "invalid lifetime bound name: `'_`"); + err.span_label(bound.span, "`'_` is a reserved lifetime name"); + err.emit(); + } + hir::LifetimeName::Static => { + self.insert_lifetime(bound, Region::Static); + self.sess.struct_span_warn(lifetime_i.lifetime.span.to(bound.span), + &format!("unnecessary lifetime parameter `{}`", + lifetime_i.lifetime.name.name())) + .help(&format!( + "you can use the `'static` lifetime directly, in place \ + of `{}`", lifetime_i.lifetime.name.name())) + .emit(); + } + hir::LifetimeName::Implicit | + hir::LifetimeName::Name(_) => { + self.resolve_lifetime_ref(bound); + } } } } @@ -1472,9 +1492,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { { for &(label, label_span) in &self.labels_in_fn { // FIXME (#24278): non-hygienic comparison - if lifetime.name == label { + if lifetime.name.name() == label { signal_shadowing_problem(self.sess, - lifetime.name, + label, original_label(label_span), shadower_lifetime(&lifetime)); return; @@ -1501,7 +1521,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { signal_shadowing_problem( self.sess, - lifetime.name, + lifetime.name.name(), original_lifetime(self.hir_map.span(node_id)), shadower_lifetime(&lifetime)); return; @@ -1617,7 +1637,7 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap, return; struct ConstrainedCollector { - regions: FxHashSet<ast::Name>, + regions: FxHashSet<hir::LifetimeName>, } impl<'v> Visitor<'v> for ConstrainedCollector { @@ -1657,7 +1677,7 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap, } struct AllCollector { - regions: FxHashSet<ast::Name>, + regions: FxHashSet<hir::LifetimeName>, impl_trait: bool } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index d43504b77ba..ba221ef6ae1 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -18,6 +18,7 @@ use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use rustc_data_structures::control_flow_graph::dominators::{Dominators, dominators}; use rustc_data_structures::control_flow_graph::{GraphPredecessors, GraphSuccessors}; use rustc_data_structures::control_flow_graph::ControlFlowGraph; +use rustc_serialize as serialize; use hir::def::CtorKind; use hir::def_id::DefId; use ty::subst::{Subst, Substs}; @@ -33,7 +34,7 @@ use std::fmt::{self, Debug, Formatter, Write}; use std::{iter, u32}; use std::ops::{Index, IndexMut}; use std::vec::IntoIter; -use syntax::ast::Name; +use syntax::ast::{self, Name}; use syntax_pos::Span; mod cache; @@ -96,6 +97,10 @@ pub struct Mir<'tcx> { /// and used (eventually) for debuginfo. Indexed by a `VisibilityScope`. pub visibility_scopes: IndexVec<VisibilityScope, VisibilityScopeData>, + /// Crate-local information for each visibility scope, that can't (and + /// needn't) be tracked across crates. + pub visibility_scope_info: ClearOnDecode<IndexVec<VisibilityScope, VisibilityScopeInfo>>, + /// Rvalues promoted from this function, such as borrows of constants. /// Each of them is the Mir of a constant with the fn's type parameters /// in scope, but a separate set of locals. @@ -151,6 +156,8 @@ pub const START_BLOCK: BasicBlock = BasicBlock(0); impl<'tcx> Mir<'tcx> { pub fn new(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>, visibility_scopes: IndexVec<VisibilityScope, VisibilityScopeData>, + visibility_scope_info: ClearOnDecode<IndexVec<VisibilityScope, + VisibilityScopeInfo>>, promoted: IndexVec<Promoted, Mir<'tcx>>, return_ty: Ty<'tcx>, yield_ty: Option<Ty<'tcx>>, @@ -167,6 +174,7 @@ impl<'tcx> Mir<'tcx> { Mir { basic_blocks, visibility_scopes, + visibility_scope_info, promoted, return_ty, yield_ty, @@ -278,9 +286,29 @@ impl<'tcx> Mir<'tcx> { } } +#[derive(Clone, Debug)] +pub struct VisibilityScopeInfo { + /// A NodeId with lint levels equivalent to this scope's lint levels. + pub lint_root: ast::NodeId, + /// The unsafe block that contains this node. + pub safety: Safety, +} + +#[derive(Copy, Clone, Debug)] +pub enum Safety { + Safe, + /// Unsafe because of a PushUnsafeBlock + BuiltinUnsafe, + /// Unsafe because of an unsafe fn + FnUnsafe, + /// Unsafe because of an `unsafe` block + ExplicitUnsafe(ast::NodeId) +} + impl_stable_hash_for!(struct Mir<'tcx> { basic_blocks, visibility_scopes, + visibility_scope_info, promoted, return_ty, yield_ty, @@ -310,10 +338,28 @@ impl<'tcx> IndexMut<BasicBlock> for Mir<'tcx> { } } +#[derive(Clone, Debug)] +pub enum ClearOnDecode<T> { + Clear, + Set(T) +} + +impl<T> serialize::Encodable for ClearOnDecode<T> { + fn encode<S: serialize::Encoder>(&self, s: &mut S) -> Result<(), S::Error> { + serialize::Encodable::encode(&(), s) + } +} + +impl<T> serialize::Decodable for ClearOnDecode<T> { + fn decode<D: serialize::Decoder>(d: &mut D) -> Result<Self, D::Error> { + serialize::Decodable::decode(d).map(|()| ClearOnDecode::Clear) + } +} + /// Grouped information about the source code origin of a MIR entity. /// Intended to be inspected by diagnostics and debuginfo. /// Most passes can work with it as a whole, within a single function. -#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)] pub struct SourceInfo { /// Source span for the AST pertaining to this MIR entity. pub span: Span, @@ -414,7 +460,7 @@ pub struct LocalDecl<'tcx> { /// True if this is an internal local /// /// These locals are not based on types in the source code and are only used - /// for drop flags at the moment. + /// for a few desugarings at the moment. /// /// The generator transformation will sanity check the locals which are live /// across a suspension point against the type components of the generator @@ -422,6 +468,9 @@ pub struct LocalDecl<'tcx> { /// flag drop flags to avoid triggering this check as they are introduced /// after typeck. /// + /// Unsafety checking will also ignore dereferences of these locals, + /// so they can be used for raw pointers only used in a desugaring. + /// /// This should be sound because the drop flags are fully algebraic, and /// therefore don't affect the OIBIT or outlives properties of the /// generator. @@ -438,6 +487,12 @@ pub struct LocalDecl<'tcx> { /// Source info of the local. pub source_info: SourceInfo, + + /// The *lexical* visibility 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. + pub lexical_scope: VisibilityScope, } impl<'tcx> LocalDecl<'tcx> { @@ -452,6 +507,7 @@ impl<'tcx> LocalDecl<'tcx> { span, scope: ARGUMENT_VISIBILITY_SCOPE }, + lexical_scope: ARGUMENT_VISIBILITY_SCOPE, internal: false, is_user_variable: false } @@ -468,6 +524,7 @@ impl<'tcx> LocalDecl<'tcx> { span, scope: ARGUMENT_VISIBILITY_SCOPE }, + lexical_scope: ARGUMENT_VISIBILITY_SCOPE, internal: true, is_user_variable: false } @@ -485,6 +542,7 @@ impl<'tcx> LocalDecl<'tcx> { span, scope: ARGUMENT_VISIBILITY_SCOPE }, + lexical_scope: ARGUMENT_VISIBILITY_SCOPE, internal: false, name: None, // FIXME maybe we do want some name here? is_user_variable: false @@ -1592,6 +1650,13 @@ impl Location { } } +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub struct UnsafetyViolation { + pub source_info: SourceInfo, + pub description: &'static str, + pub lint_node_id: Option<ast::NodeId>, +} + /// The layout of generator state #[derive(Clone, Debug, RustcEncodable, RustcDecodable)] pub struct GeneratorLayout<'tcx> { @@ -1607,6 +1672,7 @@ impl<'tcx> TypeFoldable<'tcx> for Mir<'tcx> { Mir { basic_blocks: self.basic_blocks.fold_with(folder), visibility_scopes: self.visibility_scopes.clone(), + visibility_scope_info: self.visibility_scope_info.clone(), promoted: self.promoted.fold_with(folder), return_ty: self.return_ty.fold_with(folder), yield_ty: self.yield_ty.fold_with(folder), diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 37c97ad3dad..63652980f9b 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -690,11 +690,13 @@ macro_rules! make_mir_visitor { name: _, ref $($mutability)* source_info, internal: _, + ref $($mutability)* lexical_scope, is_user_variable: _, } = *local_decl; self.visit_ty(ty, Lookup::Src(*source_info)); self.visit_source_info(source_info); + self.visit_visibility_scope(lexical_scope); } fn super_visibility_scope(&mut self, diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 1d490c8f27d..153d8c3a152 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -350,6 +350,9 @@ top_level_options!( // is currently just a hack and will be removed eventually, so please // try to not rely on this too much. actually_rustdoc: bool [TRACKED], + + // Number of object files/codegen units to produce on the backend + codegen_units: usize [UNTRACKED], } ); @@ -512,6 +515,7 @@ pub fn basic_options() -> Options { unstable_features: UnstableFeatures::Disallow, debug_assertions: true, actually_rustdoc: false, + codegen_units: 1, } } @@ -529,11 +533,6 @@ impl Options { (self.debugging_opts.query_dep_graph || self.debugging_opts.incremental_info) } - pub fn single_codegen_unit(&self) -> bool { - self.incremental.is_none() || - self.cg.codegen_units == 1 - } - pub fn file_path_mapping(&self) -> FilePathMapping { FilePathMapping::new( self.debugging_opts.remap_path_prefix_from.iter().zip( @@ -791,7 +790,7 @@ macro_rules! options { fn parse_opt_uint(slot: &mut Option<usize>, v: Option<&str>) -> bool { match v { Some(s) => { *slot = s.parse().ok(); slot.is_some() } - None => { *slot = None; true } + None => { *slot = None; false } } } @@ -924,7 +923,7 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, "metadata to mangle symbol names with"), extra_filename: String = ("".to_string(), parse_string, [UNTRACKED], "extra data to put in each output filename"), - codegen_units: usize = (1, parse_uint, [UNTRACKED], + codegen_units: Option<usize> = (None, parse_opt_uint, [UNTRACKED], "divide crate into N units to optimize in parallel"), remark: Passes = (SomePasses(Vec::new()), parse_passes, [UNTRACKED], "print remarks for these optimization passes (space separated, or \"all\")"), @@ -1021,7 +1020,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "attempt to recover from parse errors (experimental)"), incremental: Option<String> = (None, parse_opt_string, [UNTRACKED], "enable incremental compilation (experimental)"), - incremental_cc: bool = (true, parse_bool, [UNTRACKED], + incremental_cc: bool = (false, parse_bool, [UNTRACKED], "enable cross-crate incremental compilation (even more experimental)"), incremental_info: bool = (false, parse_bool, [UNTRACKED], "print high-level information about incremental reuse (or the lack thereof)"), @@ -1373,20 +1372,20 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> { always = always colorize output; never = never colorize output", "auto|always|never"), - opt::flagopt("", "pretty", - "Pretty-print the input instead of compiling; - valid types are: `normal` (un-annotated source), - `expanded` (crates expanded), or - `expanded,identified` (fully parenthesized, AST nodes with IDs).", - "TYPE"), - opt::flagopt("", "unpretty", - "Present the input source, unstable (and less-pretty) variants; - valid types are any of the types for `--pretty`, as well as: - `flowgraph=<nodeid>` (graphviz formatted flowgraph for node), - `everybody_loops` (all function bodies replaced with `loop {}`), - `hir` (the HIR), `hir,identified`, or - `hir,typed` (HIR with types for each node).", - "TYPE"), + opt::opt("", "pretty", + "Pretty-print the input instead of compiling; + valid types are: `normal` (un-annotated source), + `expanded` (crates expanded), or + `expanded,identified` (fully parenthesized, AST nodes with IDs).", + "TYPE"), + opt::opt("", "unpretty", + "Present the input source, unstable (and less-pretty) variants; + valid types are any of the types for `--pretty`, as well as: + `flowgraph=<nodeid>` (graphviz formatted flowgraph for node), + `everybody_loops` (all function bodies replaced with `loop {}`), + `hir` (the HIR), `hir,identified`, or + `hir,typed` (HIR with types for each node).", + "TYPE"), ]); opts } @@ -1521,27 +1520,35 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches) } let mut cg = build_codegen_options(matches, error_format); + let mut codegen_units = cg.codegen_units; // Issue #30063: if user requests llvm-related output to one // particular path, disable codegen-units. - if matches.opt_present("o") && cg.codegen_units != 1 { - let incompatible: Vec<_> = output_types.iter() - .map(|ot_path| ot_path.0) - .filter(|ot| { - !ot.is_compatible_with_codegen_units_and_single_output_file() - }).collect(); - if !incompatible.is_empty() { - for ot in &incompatible { - early_warn(error_format, &format!("--emit={} with -o incompatible with \ - -C codegen-units=N for N > 1", - ot.shorthand())); + let incompatible: Vec<_> = output_types.iter() + .map(|ot_path| ot_path.0) + .filter(|ot| { + !ot.is_compatible_with_codegen_units_and_single_output_file() + }) + .map(|ot| ot.shorthand()) + .collect(); + if !incompatible.is_empty() { + match codegen_units { + Some(n) if n > 1 => { + if matches.opt_present("o") { + for ot in &incompatible { + early_warn(error_format, &format!("--emit={} with -o incompatible with \ + -C codegen-units=N for N > 1", + ot)); + } + early_warn(error_format, "resetting to default -C codegen-units=1"); + codegen_units = Some(1); + } } - early_warn(error_format, "resetting to default -C codegen-units=1"); - cg.codegen_units = 1; + _ => codegen_units = Some(1), } } - if cg.codegen_units < 1 { + if codegen_units == Some(0) { early_error(error_format, "Value for codegen units must be a positive nonzero integer"); } @@ -1550,12 +1557,17 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches) // case, but it would be confusing to have the validity of // `-Z lto -C codegen-units=2` depend on details of the crate being // compiled, so we complain regardless. - if cg.lto && cg.codegen_units > 1 { - // This case is impossible to handle because LTO expects to be able - // to combine the entire crate and all its dependencies into a - // single compilation unit, but each codegen unit is in a separate - // LLVM context, so they can't easily be combined. - early_error(error_format, "can't perform LTO when using multiple codegen units"); + if cg.lto { + if let Some(n) = codegen_units { + if n > 1 { + // This case is impossible to handle because LTO expects to be able + // to combine the entire crate and all its dependencies into a + // single compilation unit, but each codegen unit is in a separate + // LLVM context, so they can't easily be combined. + early_error(error_format, "can't perform LTO when using multiple codegen units"); + } + } + codegen_units = Some(1); } if cg.lto && debugging_opts.incremental.is_some() { @@ -1720,6 +1732,34 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches) let incremental = debugging_opts.incremental.as_ref().map(|m| PathBuf::from(m)); + let codegen_units = codegen_units.unwrap_or_else(|| { + match opt_level { + // If we're compiling at `-O0` then default to 32 codegen units. + // The number here shouldn't matter too too much as debug mode + // builds don't rely on performance at all, meaning that lost + // opportunities for inlining through multiple codegen units is + // a non-issue. + // + // Note that the high number here doesn't mean that we'll be + // spawning a large number of threads in parallel. The backend + // of rustc contains global rate limiting through the + // `jobserver` crate so we'll never overload the system with too + // much work, but rather we'll only be optimizing when we're + // otherwise cooperating with other instances of rustc. + // + // Rather the high number here means that we should be able to + // keep a lot of idle cpus busy. By ensuring that no codegen + // unit takes *too* long to build we'll be guaranteed that all + // cpus will finish pretty closely to one another and we should + // make relatively optimal use of system resources + OptLevel::No => 32, + + // All other optimization levels default use one codegen unit, + // the historical default in Rust for a Long Time. + _ => 1, + } + }); + (Options { crate_types, optimize: opt_level, @@ -1744,6 +1784,7 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches) unstable_features: UnstableFeatures::from_environment(), debug_assertions, actually_rustdoc: false, + codegen_units, }, cfg) } @@ -2447,7 +2488,7 @@ mod tests { opts.cg.extra_filename = String::from("extra-filename"); assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.cg.codegen_units = 42; + opts.cg.codegen_units = Some(42); assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); opts.cg.remark = super::SomePasses(vec![String::from("pass1"), diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 96f46b270a1..e87443619ec 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -411,7 +411,8 @@ impl Session { } pub fn emit_end_regions(&self) -> bool { self.opts.debugging_opts.emit_end_regions || - (self.opts.debugging_opts.mir_emit_validate > 0) + (self.opts.debugging_opts.mir_emit_validate > 0) || + self.opts.debugging_opts.borrowck_mir } pub fn lto(&self) -> bool { self.opts.cg.lto diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index b491baadd7c..c7c8141f4f7 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -37,7 +37,7 @@ use rustc::lint::builtin::EXTRA_REQUIREMENT_IN_IMPL; use std::fmt; use syntax::ast; use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; -use ty::error::{ExpectedFound, TypeError}; +use ty::error::ExpectedFound; use ty::fast_reject; use ty::fold::TypeFolder; use ty::subst::Subst; @@ -711,7 +711,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } - OutputTypeParameterMismatch(ref expected_trait_ref, ref actual_trait_ref, ref e) => { + OutputTypeParameterMismatch(ref expected_trait_ref, ref actual_trait_ref, _) => { let expected_trait_ref = self.resolve_type_vars_if_possible(&*expected_trait_ref); let actual_trait_ref = self.resolve_type_vars_if_possible(&*actual_trait_ref); if actual_trait_ref.self_ty().references_error() { @@ -722,48 +722,31 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.tcx.hir.span_if_local(did) }); - if let &TypeError::TupleSize(ref expected_found) = e { - // Expected `|x| { }`, found `|x, y| { }` - self.report_arg_count_mismatch(span, - found_span, - expected_found.expected, - expected_found.found, - expected_trait_ty.is_closure()) - } else if let &TypeError::Sorts(ref expected_found) = e { - let expected = if let ty::TyTuple(tys, _) = expected_found.expected.sty { - tys.len() - } else { - 1 + let self_ty_count = + match expected_trait_ref.skip_binder().substs.type_at(1).sty { + ty::TyTuple(ref tys, _) => tys.len(), + _ => 1, }; - let found = if let ty::TyTuple(tys, _) = expected_found.found.sty { - tys.len() - } else { - 1 + let arg_ty_count = + match actual_trait_ref.skip_binder().substs.type_at(1).sty { + ty::TyTuple(ref tys, _) => tys.len(), + _ => 1, }; - - if expected != found { - // Expected `|| { }`, found `|x, y| { }` - // Expected `fn(x) -> ()`, found `|| { }` - self.report_arg_count_mismatch(span, - found_span, - expected, - found, - expected_trait_ty.is_closure()) - } else { - self.report_type_argument_mismatch(span, - found_span, - expected_trait_ty, - expected_trait_ref, - actual_trait_ref, - e) - } + if self_ty_count == arg_ty_count { + self.report_closure_arg_mismatch(span, + found_span, + expected_trait_ref, + actual_trait_ref) } else { - self.report_type_argument_mismatch(span, - found_span, - expected_trait_ty, - expected_trait_ref, - actual_trait_ref, - e) + // Expected `|| { }`, found `|x, y| { }` + // Expected `fn(x) -> ()`, found `|| { }` + self.report_arg_count_mismatch( + span, + found_span, + arg_ty_count, + self_ty_count, + expected_trait_ty.is_closure() + ) } } @@ -784,31 +767,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { err.emit(); } - fn report_type_argument_mismatch(&self, - span: Span, - found_span: Option<Span>, - expected_ty: Ty<'tcx>, - expected_ref: ty::PolyTraitRef<'tcx>, - found_ref: ty::PolyTraitRef<'tcx>, - type_error: &TypeError<'tcx>) - -> DiagnosticBuilder<'tcx> - { - let mut err = struct_span_err!(self.tcx.sess, span, E0281, - "type mismatch: `{}` implements the trait `{}`, but the trait `{}` is required", - expected_ty, - expected_ref, - found_ref); - - err.span_label(span, format!("{}", type_error)); - - if let Some(sp) = found_span { - err.span_label(span, format!("requires `{}`", found_ref)); - err.span_label(sp, format!("implements `{}`", expected_ref)); - } - - err - } - fn report_arg_count_mismatch(&self, span: Span, found_span: Option<Span>, @@ -837,6 +795,57 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } err } + + fn report_closure_arg_mismatch(&self, + span: Span, + found_span: Option<Span>, + expected_ref: ty::PolyTraitRef<'tcx>, + found: ty::PolyTraitRef<'tcx>) + -> DiagnosticBuilder<'tcx> + { + fn build_fn_sig_string<'a, 'gcx, 'tcx>(tcx: ty::TyCtxt<'a, 'gcx, 'tcx>, + trait_ref: &ty::TraitRef<'tcx>) -> String { + let inputs = trait_ref.substs.type_at(1); + let sig = if let ty::TyTuple(inputs, _) = inputs.sty { + tcx.mk_fn_sig( + inputs.iter().map(|&x| x), + tcx.mk_infer(ty::TyVar(ty::TyVid { index: 0 })), + false, + hir::Unsafety::Normal, + ::syntax::abi::Abi::Rust + ) + } else { + tcx.mk_fn_sig( + ::std::iter::once(inputs), + tcx.mk_infer(ty::TyVar(ty::TyVid { index: 0 })), + false, + hir::Unsafety::Normal, + ::syntax::abi::Abi::Rust + ) + }; + format!("{}", ty::Binder(sig)) + } + + let argument_is_closure = expected_ref.skip_binder().substs.type_at(0).is_closure(); + let mut err = struct_span_err!(self.tcx.sess, span, E0631, + "type mismatch in {} arguments", + if argument_is_closure { "closure" } else { "function" }); + + let found_str = format!( + "expected signature of `{}`", + build_fn_sig_string(self.tcx, found.skip_binder()) + ); + err.span_label(span, found_str); + + let found_span = found_span.unwrap_or(span); + let expected_str = format!( + "found signature of `{}`", + build_fn_sig_string(self.tcx, expected_ref.skip_binder()) + ); + err.span_label(found_span, expected_str); + + err + } } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { diff --git a/src/librustc/traits/trans/mod.rs b/src/librustc/traits/trans/mod.rs index 9c4a260b35d..947e7117c4e 100644 --- a/src/librustc/traits/trans/mod.rs +++ b/src/librustc/traits/trans/mod.rs @@ -19,7 +19,7 @@ use std::cell::RefCell; use std::marker::PhantomData; use syntax::ast; use syntax_pos::Span; -use traits::{FulfillmentContext, Obligation, ObligationCause, Reveal, SelectionContext, Vtable}; +use traits::{FulfillmentContext, Obligation, ObligationCause, SelectionContext, Vtable}; use ty::{self, Ty, TyCtxt}; use ty::subst::{Subst, Substs}; use ty::fold::{TypeFoldable, TypeFolder}; @@ -31,24 +31,25 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { /// (necessarily) resolve all nested obligations on the impl. Note /// that type check should guarantee to us that all nested /// obligations *could be* resolved if we wanted to. + /// Assumes that this is run after the entire crate has been successfully type-checked. pub fn trans_fulfill_obligation(self, span: Span, + param_env: ty::ParamEnv<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) -> Vtable<'tcx, ()> { // Remove any references to regions; this helps improve caching. let trait_ref = self.erase_regions(&trait_ref); - self.trans_trait_caches.trait_cache.memoize(trait_ref, || { + self.trans_trait_caches.trait_cache.memoize((param_env, trait_ref), || { debug!("trans::fulfill_obligation(trait_ref={:?}, def_id={:?})", - trait_ref, trait_ref.def_id()); + (param_env, trait_ref), trait_ref.def_id()); // Do the initial selection for the obligation. This yields the // shallow result we are looking for -- that is, what specific impl. self.infer_ctxt().enter(|infcx| { let mut selcx = SelectionContext::new(&infcx); - let param_env = ty::ParamEnv::empty(Reveal::All); let obligation_cause = ObligationCause::misc(span, ast::DUMMY_NODE_ID); let obligation = Obligation::new(obligation_cause, @@ -167,7 +168,7 @@ pub struct TraitSelectionCache<'tcx> { } impl<'tcx> DepTrackingMapConfig for TraitSelectionCache<'tcx> { - type Key = ty::PolyTraitRef<'tcx>; + type Key = (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>); type Value = Vtable<'tcx, ()>; fn to_dep_kind() -> DepKind { DepKind::TraitSelect diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 4a309ee0eb0..315ba622ccf 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -11,6 +11,7 @@ //! type context book-keeping use dep_graph::DepGraph; +use dep_graph::{DepNode, DepConstructor}; use errors::DiagnosticBuilder; use session::Session; use session::config::OutputFilenames; @@ -50,8 +51,8 @@ use util::nodemap::{NodeMap, NodeSet, DefIdSet, ItemLocalMap}; use util::nodemap::{FxHashMap, FxHashSet}; use rustc_data_structures::accumulate_vec::AccumulateVec; use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap, - StableHasher, StableHasherResult}; - + StableHasher, StableHasherResult, + StableVec}; use arena::{TypedArena, DroplessArena}; use rustc_const_math::{ConstInt, ConstUsize}; use rustc_data_structures::indexed_vec::IndexVec; @@ -314,7 +315,7 @@ impl<'a, V> LocalTableInContextMut<'a, V> { } } -#[derive(RustcEncodable, RustcDecodable)] +#[derive(RustcEncodable, RustcDecodable, Debug)] pub struct TypeckTables<'tcx> { /// The HirId::owner all ItemLocalIds in this table are relative to. pub local_id_root: Option<DefId>, @@ -828,7 +829,9 @@ pub struct GlobalCtxt<'tcx> { /// Map indicating what traits are in scope for places where this /// is relevant; generated by resolve. - trait_map: FxHashMap<DefIndex, Rc<FxHashMap<ItemLocalId, Rc<Vec<TraitCandidate>>>>>, + trait_map: FxHashMap<DefIndex, + Rc<FxHashMap<ItemLocalId, + Rc<StableVec<TraitCandidate>>>>>, /// Export map produced by name resolution. export_map: FxHashMap<DefId, Rc<Vec<Export>>>, @@ -1081,15 +1084,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { None }; - // FIXME(mw): Each of the Vecs in the trait_map should be brought into - // a deterministic order here. Otherwise we might end up with - // unnecessarily unstable incr. comp. hashes. let mut trait_map = FxHashMap(); for (k, v) in resolutions.trait_map { let hir_id = hir.node_to_hir_id(k); let map = trait_map.entry(hir_id.owner) .or_insert_with(|| Rc::new(FxHashMap())); - Rc::get_mut(map).unwrap().insert(hir_id.local_id, Rc::new(v)); + Rc::get_mut(map).unwrap() + .insert(hir_id.local_id, + Rc::new(StableVec::new(v))); } let mut defs = FxHashMap(); for (k, v) in named_region_map.defs { @@ -1235,6 +1237,35 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.hir.definitions(), self.cstore) } + + // This method makes sure that we have a DepNode and a Fingerprint for + // every upstream crate. It needs to be called once right after the tcx is + // created. + // With full-fledged red/green, the method will probably become unnecessary + // as this will be done on-demand. + pub fn allocate_metadata_dep_nodes(self) { + // We cannot use the query versions of crates() and crate_hash(), since + // those would need the DepNodes that we are allocating here. + for cnum in self.cstore.crates_untracked() { + let dep_node = DepNode::new(self, DepConstructor::CrateMetadata(cnum)); + let crate_hash = self.cstore.crate_hash_untracked(cnum); + self.dep_graph.with_task(dep_node, + self, + crate_hash, + |_, x| x // No transformation needed + ); + } + } + + // This method exercises the `in_scope_traits_map` query for all possible + // values so that we have their fingerprints available in the DepGraph. + // This is only required as long as we still use the old dependency tracking + // which needs to have the fingerprints of all input nodes beforehand. + pub fn precompute_in_scope_traits_hashes(self) { + for &def_index in self.trait_map.keys() { + self.in_scope_traits_map(def_index); + } + } } impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { @@ -2103,7 +2134,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { lint::struct_lint_level(self.sess, lint, level, src, None, msg) } - pub fn in_scope_traits(self, id: HirId) -> Option<Rc<Vec<TraitCandidate>>> { + pub fn in_scope_traits(self, id: HirId) -> Option<Rc<StableVec<TraitCandidate>>> { self.in_scope_traits_map(id.owner) .and_then(|map| map.get(&id.local_id).cloned()) } diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index 313a831f6b0..4bd2d5be6d7 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -42,6 +42,7 @@ use rustc_data_structures::indexed_set::IdxSetBuf; use rustc_back::PanicStrategy; use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::stable_hasher::StableVec; use std::cell::{RefCell, Cell}; use std::ops::Deref; @@ -158,6 +159,10 @@ define_maps! { <'tcx> /// expression defining the closure. [] fn closure_kind: ClosureKind(DefId) -> ty::ClosureKind, + /// Unsafety violations for this def ID. + [] fn unsafety_violations: UnsafetyViolations(DefId) + -> Rc<[mir::UnsafetyViolation]>, + /// The signature of functions and closures. [] fn fn_sig: FnSignature(DefId) -> ty::PolyFnSig<'tcx>, @@ -259,7 +264,7 @@ define_maps! { <'tcx> [] fn specializes: specializes_node((DefId, DefId)) -> bool, [] fn in_scope_traits_map: InScopeTraits(DefIndex) - -> Option<Rc<FxHashMap<ItemLocalId, Rc<Vec<TraitCandidate>>>>>, + -> Option<Rc<FxHashMap<ItemLocalId, Rc<StableVec<TraitCandidate>>>>>, [] fn module_exports: ModuleExports(DefId) -> Option<Rc<Vec<Export>>>, [] fn lint_levels: lint_levels_node(CrateNum) -> Rc<lint::LintLevelMap>, diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 87a9eef0de5..581f47dc13c 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -221,7 +221,7 @@ macro_rules! define_maps { profq_msg!(tcx, ProfileQueriesMsg::QueryBegin( - span.clone(), + span.data(), QueryMsg::$name(profq_key!(tcx, key)) ) ); diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 2c1b3e28ffb..da635ec80fc 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -675,6 +675,8 @@ pub struct TypeParameterDef { /// on generic parameter `T`, asserts data behind the parameter /// `T` won't be accessed during the parent type's `Drop` impl. pub pure_wrt_drop: bool, + + pub synthetic: Option<hir::SyntheticTyParamKind>, } #[derive(Copy, Clone, RustcEncodable, RustcDecodable)] diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index 618a4ed331e..9e566d2b907 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -20,7 +20,7 @@ use std::path::Path; use std::time::{Duration, Instant}; use std::sync::mpsc::{Sender}; -use syntax_pos::{Span}; +use syntax_pos::{SpanData}; use ty::maps::{QueryMsg}; use dep_graph::{DepNode}; @@ -61,7 +61,8 @@ pub enum ProfileQueriesMsg { /// end a task TaskEnd, /// begin a new query - QueryBegin(Span, QueryMsg), + /// can't use `Span` because queries are sent to other thread + QueryBegin(SpanData, QueryMsg), /// query is satisfied by using an already-known value for the given key CacheHit, /// query requires running a provider; providers may nest, permitting queries to nest. diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index cf7a29d2845..214973e3085 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -26,6 +26,7 @@ use std::fmt; use std::usize; use rustc_const_math::ConstInt; +use rustc_data_structures::indexed_vec::Idx; use syntax::abi::Abi; use syntax::ast::CRATE_NODE_ID; use syntax::symbol::Symbol; @@ -530,17 +531,17 @@ impl fmt::Display for ty::RegionKind { write!(f, "{}", br) } ty::ReScope(scope) if identify_regions() => { - match scope { - region::Scope::Node(id) => + match scope.data() { + region::ScopeData::Node(id) => write!(f, "'{}s", id.as_usize()), - region::Scope::CallSite(id) => + region::ScopeData::CallSite(id) => write!(f, "'{}cs", id.as_usize()), - region::Scope::Arguments(id) => + region::ScopeData::Arguments(id) => write!(f, "'{}as", id.as_usize()), - region::Scope::Destruction(id) => + region::ScopeData::Destruction(id) => write!(f, "'{}ds", id.as_usize()), - region::Scope::Remainder(BlockRemainder { block, first_statement_index }) => - write!(f, "'{}_{}rs", block.as_usize(), first_statement_index), + region::ScopeData::Remainder(BlockRemainder { block, first_statement_index }) => + write!(f, "'{}_{}rs", block.as_usize(), first_statement_index.index()), } } ty::ReVar(region_vid) if identify_regions() => { @@ -676,6 +677,12 @@ impl<'tcx> fmt::Display for ty::Binder<ty::TraitRef<'tcx>> { } } +impl<'tcx> fmt::Display for ty::Binder<ty::FnSig<'tcx>> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self))) + } +} + impl<'tcx> fmt::Display for ty::Binder<ty::TraitPredicate<'tcx>> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self))) diff --git a/src/librustc_back/target/aarch64_unknown_linux_musl.rs b/src/librustc_back/target/aarch64_unknown_linux_musl.rs new file mode 100644 index 00000000000..1edac616366 --- /dev/null +++ b/src/librustc_back/target/aarch64_unknown_linux_musl.rs @@ -0,0 +1,36 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use LinkerFlavor; +use target::{Target, TargetOptions, TargetResult}; + +pub fn target() -> TargetResult { + let mut base = super::linux_musl_base::opts(); + base.max_atomic_width = Some(128); + + // see #36994 + base.exe_allocation_crate = None; + + Ok(Target { + llvm_target: "aarch64-unknown-linux-musl".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "64".to_string(), + target_env: "musl".to_string(), + data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), + arch: "aarch64".to_string(), + target_os: "linux".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_back/target/mod.rs b/src/librustc_back/target/mod.rs index 301cf3f8c82..27a0855dc29 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -153,6 +153,7 @@ supported_targets! { ("armv7-unknown-linux-gnueabihf", armv7_unknown_linux_gnueabihf), ("armv7-unknown-linux-musleabihf", armv7_unknown_linux_musleabihf), ("aarch64-unknown-linux-gnu", aarch64_unknown_linux_gnu), + ("aarch64-unknown-linux-musl", aarch64_unknown_linux_musl), ("x86_64-unknown-linux-musl", x86_64_unknown_linux_musl), ("i686-unknown-linux-musl", i686_unknown_linux_musl), ("mips-unknown-linux-musl", mips_unknown_linux_musl), diff --git a/src/librustc_data_structures/bitvec.rs b/src/librustc_data_structures/bitvec.rs index 7331016c2d2..e8f9a672087 100644 --- a/src/librustc_data_structures/bitvec.rs +++ b/src/librustc_data_structures/bitvec.rs @@ -138,7 +138,7 @@ impl FromIterator<bool> for BitVector { /// A "bit matrix" is basically a matrix of booleans represented as /// one gigantic bitvector. In other words, it is as if you have /// `rows` bitvectors, each of length `columns`. -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct BitMatrix { columns: usize, vector: Vec<u64>, diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs index f6b23af2f73..9aba48c5bef 100644 --- a/src/librustc_data_structures/stable_hasher.rs +++ b/src/librustc_data_structures/stable_hasher.rs @@ -558,3 +558,37 @@ pub fn hash_stable_hashmap<HCX, K, V, R, SK, F, W>( entries.hash_stable(hcx, hasher); } + +/// A vector container that makes sure that its items are hashed in a stable +/// order. +pub struct StableVec<T>(Vec<T>); + +impl<T> StableVec<T> { + pub fn new(v: Vec<T>) -> Self { + StableVec(v) + } +} + +impl<T> ::std::ops::Deref for StableVec<T> { + type Target = Vec<T>; + + fn deref(&self) -> &Vec<T> { + &self.0 + } +} + +impl<T, HCX> HashStable<HCX> for StableVec<T> + where T: HashStable<HCX> + ToStableHashKey<HCX> +{ + fn hash_stable<W: StableHasherResult>(&self, + hcx: &mut HCX, + hasher: &mut StableHasher<W>) { + let StableVec(ref v) = *self; + + let mut sorted: Vec<_> = v.iter() + .map(|x| x.to_stable_hash_key(hcx)) + .collect(); + sorted.sort_unstable(); + sorted.hash_stable(hcx, hasher); + } +} diff --git a/src/librustc_data_structures/transitive_relation.rs b/src/librustc_data_structures/transitive_relation.rs index 46463944043..7cb386b0197 100644 --- a/src/librustc_data_structures/transitive_relation.rs +++ b/src/librustc_data_structures/transitive_relation.rs @@ -18,7 +18,7 @@ use std::hash::Hash; use std::mem; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct TransitiveRelation<T: Clone + Debug + Eq + Hash + Clone> { // List of elements. This is used to map from a T to a usize. elements: Vec<T>, @@ -42,10 +42,10 @@ pub struct TransitiveRelation<T: Clone + Debug + Eq + Hash + Clone> { closure: RefCell<Option<BitMatrix>>, } -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)] struct Index(usize); -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable)] +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)] struct Edge { source: Index, target: Index, diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index d50d3deb673..57989f75cba 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![cfg_attr(not(feature="llvm"), allow(dead_code))] - use rustc::dep_graph::DepGraph; use rustc::hir::{self, map as hir_map}; use rustc::hir::lowering::lower_crate; @@ -30,12 +28,12 @@ use rustc::traits; use rustc::util::common::{ErrorReported, time}; use rustc_allocator as allocator; use rustc_borrowck as borrowck; -use rustc_incremental::{self, IncrementalHashesMap}; +use rustc_incremental; use rustc_resolve::{MakeGlobMap, Resolver}; use rustc_metadata::creader::CrateLoader; use rustc_metadata::cstore::{self, CStore}; -use rustc_trans::back::write; use rustc_trans as trans; +use rustc_trans_utils::trans_crate::TransCrate; use rustc_typeck as typeck; use rustc_privacy; use rustc_plugin::registry::Registry; @@ -43,6 +41,7 @@ use rustc_plugin as plugin; use rustc_passes::{ast_validation, no_asm, loops, consts, static_recursion, hir_stats}; use rustc_const_eval::{self, check_match}; use super::Compilation; +use ::DefaultTransCrate; use serialize::json; @@ -76,7 +75,8 @@ pub fn compile_input(sess: &Session, output: &Option<PathBuf>, addl_plugins: Option<Vec<String>>, control: &CompileController) -> CompileResult { - use rustc_trans::back::write::OngoingCrateTranslation; + use rustc::session::config::CrateType; + macro_rules! controller_entry_point { ($point: ident, $tsess: expr, $make_state: expr, $phase_result: expr) => {{ let state = &mut $make_state; @@ -94,17 +94,16 @@ pub fn compile_input(sess: &Session, } if cfg!(not(feature="llvm")) { - use rustc::session::config::CrateType; - if !sess.opts.debugging_opts.no_trans && sess.opts.output_types.should_trans() { - sess.err("LLVM is not supported by this rustc. Please use -Z no-trans to compile") - } - - if sess.opts.crate_types.iter().all(|&t|{ - t != CrateType::CrateTypeRlib && t != CrateType::CrateTypeExecutable - }) && !sess.opts.crate_types.is_empty() { - sess.err( - "LLVM is not supported by this rustc, so non rlib libraries are not supported" - ); + for cty in sess.opts.crate_types.iter() { + match *cty { + CrateType::CrateTypeRlib | CrateType::CrateTypeDylib | + CrateType::CrateTypeExecutable => {}, + _ => { + sess.parse_sess.span_diagnostic.warn( + &format!("LLVM unsupported, so output type {} is not supported", cty) + ); + }, + } } sess.abort_if_errors(); @@ -117,7 +116,7 @@ pub fn compile_input(sess: &Session, // We need nested scopes here, because the intermediate results can keep // large chunks of memory alive and we want to free them as soon as // possible to keep the peak memory usage low - let (outputs, trans, dep_graph): (OutputFilenames, OngoingCrateTranslation, DepGraph) = { + let (outputs, trans, dep_graph) = { let krate = match phase_1_parse_input(control, sess, input) { Ok(krate) => krate, Err(mut parse_error) => { @@ -175,7 +174,7 @@ pub fn compile_input(sess: &Session, // Construct the HIR map let hir_map = time(sess.time_passes(), "indexing hir", - || hir_map::map_crate(&mut hir_forest, &defs)); + || hir_map::map_crate(sess, cstore, &mut hir_forest, &defs)); { let _ignore = hir_map.dep_graph.in_ignore(); @@ -218,7 +217,7 @@ pub fn compile_input(sess: &Session, &arenas, &crate_name, &outputs, - |tcx, analysis, incremental_hashes_map, rx, result| { + |tcx, analysis, rx, result| { { // Eventually, we will want to track plugins. let _ignore = tcx.dep_graph.in_ignore(); @@ -246,9 +245,7 @@ pub fn compile_input(sess: &Session, tcx.print_debug_stats(); } - let trans = phase_4_translate_to_llvm(tcx, - incremental_hashes_map, - rx); + let trans = phase_4_translate_to_llvm::<DefaultTransCrate>(tcx, rx); if log_enabled!(::log::LogLevel::Info) { println!("Post-trans"); @@ -266,44 +263,42 @@ pub fn compile_input(sess: &Session, })?? }; - if cfg!(not(feature="llvm")) { - let (_, _) = (outputs, trans); - sess.fatal("LLVM is not supported by this rustc"); + if sess.opts.debugging_opts.print_type_sizes { + sess.code_stats.borrow().print_type_sizes(); } - #[cfg(feature="llvm")] - { - if sess.opts.debugging_opts.print_type_sizes { - sess.code_stats.borrow().print_type_sizes(); - } - - let (phase5_result, trans) = phase_5_run_llvm_passes(sess, &dep_graph, trans); + let (phase5_result, trans) = + phase_5_run_llvm_passes::<DefaultTransCrate>(sess, &dep_graph, trans); - controller_entry_point!(after_llvm, - sess, - CompileState::state_after_llvm(input, sess, outdir, output, &trans), - phase5_result); - phase5_result?; + controller_entry_point!(after_llvm, + sess, + CompileState::state_after_llvm(input, sess, outdir, output, &trans), + phase5_result); + phase5_result?; - phase_6_link_output(sess, &trans, &outputs); - - // Now that we won't touch anything in the incremental compilation directory - // any more, we can finalize it (which involves renaming it) - rustc_incremental::finalize_session_directory(sess, trans.link.crate_hash); + // Run the linker on any artifacts that resulted from the LLVM run. + // This should produce either a finished executable or library. + time(sess.time_passes(), "linking", || { + DefaultTransCrate::link_binary(sess, &trans, &outputs) + }); - if sess.opts.debugging_opts.perf_stats { - sess.print_perf_stats(); - } + // Now that we won't touch anything in the incremental compilation directory + // any more, we can finalize it (which involves renaming it) + #[cfg(feature="llvm")] + rustc_incremental::finalize_session_directory(sess, trans.link.crate_hash); - controller_entry_point!( - compilation_done, - sess, - CompileState::state_when_compilation_done(input, sess, outdir, output), - Ok(()) - ); + if sess.opts.debugging_opts.perf_stats { + sess.print_perf_stats(); + } + controller_entry_point!( + compilation_done, + sess, + CompileState::state_when_compilation_done(input, sess, outdir, output), Ok(()) - } + ); + + Ok(()) } fn keep_hygiene_data(sess: &Session) -> bool { @@ -645,7 +640,16 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session, &crate_name, &disambiguator.as_str(), ); - let dep_graph = DepGraph::new(sess.opts.build_dep_graph()); + + let dep_graph = if sess.opts.build_dep_graph() { + let prev_dep_graph = time(time_passes, "load prev dep-graph (new)", || { + rustc_incremental::load_dep_graph_new(sess) + }); + + DepGraph::new(prev_dep_graph) + } else { + DepGraph::new_disabled() + }; time(time_passes, "recursion limit", || { middle::recursion_limit::update_limits(sess, &krate); @@ -715,7 +719,6 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session, // item, much like we do for macro expansion. In other words, the hash reflects not just // its contents but the results of name resolution on those contents. Hopefully we'll push // this back at some point. - let _ignore = dep_graph.in_ignore(); let mut crate_loader = CrateLoader::new(sess, &cstore, crate_name); let resolver_arenas = Resolver::arenas(); let mut resolver = Resolver::new(sess, @@ -921,7 +924,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, -> Result<R, CompileIncomplete> where F: for<'a> FnOnce(TyCtxt<'a, 'tcx, 'tcx>, ty::CrateAnalysis, - IncrementalHashesMap, mpsc::Receiver<Box<Any + Send>>, CompileResult) -> R { @@ -965,7 +967,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, mir::provide(&mut local_providers); reachable::provide(&mut local_providers); rustc_privacy::provide(&mut local_providers); - trans::provide_local(&mut local_providers); + DefaultTransCrate::provide_local(&mut local_providers); typeck::provide(&mut local_providers); ty::provide(&mut local_providers); traits::provide(&mut local_providers); @@ -977,7 +979,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, let mut extern_providers = ty::maps::Providers::default(); cstore::provide(&mut extern_providers); - trans::provide_extern(&mut extern_providers); + DefaultTransCrate::provide_extern(&mut extern_providers); ty::provide_extern(&mut extern_providers); traits::provide_extern(&mut extern_providers); // FIXME(eddyb) get rid of this once we replace const_eval with miri. @@ -1000,19 +1002,16 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, // What we need to run borrowck etc. passes.push_pass(MIR_VALIDATED, mir::transform::qualify_consts::QualifyAndPromoteConstants); - - // FIXME: ariel points SimplifyBranches should run after - // mir-borrowck; otherwise code within `if false { ... }` would - // not be checked. - passes.push_pass(MIR_VALIDATED, - mir::transform::simplify_branches::SimplifyBranches::new("initial")); passes.push_pass(MIR_VALIDATED, mir::transform::simplify::SimplifyCfg::new("qualify-consts")); passes.push_pass(MIR_VALIDATED, mir::transform::nll::NLL); // borrowck runs between MIR_VALIDATED and MIR_OPTIMIZED. - // These next passes must be executed together passes.push_pass(MIR_OPTIMIZED, mir::transform::no_landing_pads::NoLandingPads); + passes.push_pass(MIR_OPTIMIZED, + mir::transform::simplify_branches::SimplifyBranches::new("initial")); + + // These next passes must be executed together passes.push_pass(MIR_OPTIMIZED, mir::transform::add_call_guards::CriticalCallEdges); passes.push_pass(MIR_OPTIMIZED, mir::transform::elaborate_drops::ElaborateDrops); passes.push_pass(MIR_OPTIMIZED, mir::transform::no_landing_pads::NoLandingPads); @@ -1053,22 +1052,16 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, tx, output_filenames, |tcx| { - let incremental_hashes_map = - time(time_passes, - "compute_incremental_hashes_map", - || rustc_incremental::compute_incremental_hashes_map(tcx)); - time(time_passes, "load_dep_graph", - || rustc_incremental::load_dep_graph(tcx, &incremental_hashes_map)); + || rustc_incremental::load_dep_graph(tcx)); time(time_passes, "stability checking", || stability::check_unstable_api_usage(tcx)); // passes are timed inside typeck - try_with_f!(typeck::check_crate(tcx), - (tcx, analysis, incremental_hashes_map, rx)); + try_with_f!(typeck::check_crate(tcx), (tcx, analysis, rx)); time(time_passes, "const checking", @@ -1082,10 +1075,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, || middle::intrinsicck::check_crate(tcx)); time(time_passes, - "effect checking", - || middle::effect::check_crate(tcx)); - - time(time_passes, "match checking", || check_match::check_crate(tcx)); @@ -1105,6 +1094,11 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, "MIR borrow checking", || for def_id in tcx.body_owners() { tcx.mir_borrowck(def_id) }); + time(time_passes, + "MIR effect checking", + || for def_id in tcx.body_owners() { + mir::transform::check_unsafety::check_unsafety(tcx, def_id) + }); // Avoid overwhelming user with errors if type checking failed. // I'm not sure how helpful this is, to be honest, but it avoids // a @@ -1112,7 +1106,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, // lint warnings and so on -- kindck used to do this abort, but // kindck is gone now). -nmatsakis if sess.err_count() > 0 { - return Ok(f(tcx, analysis, incremental_hashes_map, rx, sess.compile_status())); + return Ok(f(tcx, analysis, rx, sess.compile_status())); } time(time_passes, "death checking", || middle::dead::check_crate(tcx)); @@ -1123,16 +1117,15 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, time(time_passes, "lint checking", || lint::check_crate(tcx)); - return Ok(f(tcx, analysis, incremental_hashes_map, rx, tcx.sess.compile_status())); + return Ok(f(tcx, analysis, rx, tcx.sess.compile_status())); }) } /// Run the translation phase to LLVM, after which the AST and analysis can /// be discarded. -pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - incremental_hashes_map: IncrementalHashesMap, +pub fn phase_4_translate_to_llvm<'a, 'tcx, Trans: TransCrate>(tcx: TyCtxt<'a, 'tcx, 'tcx>, rx: mpsc::Receiver<Box<Any + Send>>) - -> write::OngoingCrateTranslation { + -> <Trans as TransCrate>::OngoingCrateTranslation { let time_passes = tcx.sess.time_passes(); time(time_passes, @@ -1141,9 +1134,8 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let translation = time(time_passes, "translation", move || { - trans::trans_crate(tcx, incremental_hashes_map, rx) + Trans::trans_crate(tcx, rx) }); - if tcx.sess.profile_queries() { profile::dump("profile_queries".to_string()) } @@ -1153,15 +1145,14 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, /// Run LLVM itself, producing a bitcode file, assembly file or object file /// as a side effect. -#[cfg(feature="llvm")] -pub fn phase_5_run_llvm_passes(sess: &Session, +pub fn phase_5_run_llvm_passes<Trans: TransCrate>(sess: &Session, dep_graph: &DepGraph, - trans: write::OngoingCrateTranslation) - -> (CompileResult, trans::CrateTranslation) { - let trans = trans.join(sess, dep_graph); + trans: <Trans as TransCrate>::OngoingCrateTranslation) + -> (CompileResult, <Trans as TransCrate>::TranslatedCrate) { + let trans = Trans::join_trans(trans, sess, dep_graph); if sess.opts.debugging_opts.incremental_info { - write::dump_incremental_data(&trans); + Trans::dump_incremental_data(&trans); } time(sess.time_passes(), @@ -1171,20 +1162,6 @@ pub fn phase_5_run_llvm_passes(sess: &Session, (sess.compile_status(), trans) } -/// Run the linker on any artifacts that resulted from the LLVM run. -/// This should produce either a finished executable or library. -#[cfg(feature="llvm")] -pub fn phase_6_link_output(sess: &Session, - trans: &trans::CrateTranslation, - outputs: &OutputFilenames) { - time(sess.time_passes(), "linking", || { - ::rustc_trans::back::link::link_binary(sess, - trans, - outputs, - &trans.crate_name.as_str()) - }); -} - fn escape_dep_filename(filename: &str) -> String { // Apparently clang and gcc *only* escape spaces: // http://llvm.org/klaus/clang/commit/9d50634cfc268ecc9a7250226dd5ca0e945240d4 diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 044f4a5eaf5..6bdad0b212c 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -75,6 +75,7 @@ use rustc::middle::cstore::CrateStore; use rustc_metadata::locator; use rustc_metadata::cstore::CStore; use rustc::util::common::{time, ErrorReported}; +use rustc_trans_utils::trans_crate::TransCrate; use serialize::json::ToJson; @@ -151,101 +152,31 @@ pub fn run<F>(run_compiler: F) -> isize } #[cfg(not(feature="llvm"))] -pub use no_llvm_metadata_loader::NoLLvmMetadataLoader as MetadataLoader; +pub use rustc_trans_utils::trans_crate::MetadataOnlyTransCrate as DefaultTransCrate; #[cfg(feature="llvm")] -pub use rustc_trans::LlvmMetadataLoader as MetadataLoader; - -#[cfg(not(feature="llvm"))] -mod no_llvm_metadata_loader { - extern crate ar; - extern crate owning_ref; - - use rustc::middle::cstore::MetadataLoader as MetadataLoaderTrait; - use rustc_back::target::Target; - use std::io; - use std::fs::File; - use std::path::Path; - - use self::ar::Archive; - use self::owning_ref::{OwningRef, ErasedBoxRef}; - - pub struct NoLLvmMetadataLoader; - - impl MetadataLoaderTrait for NoLLvmMetadataLoader { - fn get_rlib_metadata( - &self, - _: &Target, - filename: &Path - ) -> Result<ErasedBoxRef<[u8]>, String> { - let file = File::open(filename).map_err(|e| { - format!("metadata file open err: {:?}", e) - })?; - let mut archive = Archive::new(file); - - while let Some(entry_result) = archive.next_entry() { - let mut entry = entry_result.map_err(|e| { - format!("metadata section read err: {:?}", e) - })?; - if entry.header().identifier() == "rust.metadata.bin" { - let mut buf = Vec::new(); - io::copy(&mut entry, &mut buf).unwrap(); - let buf: OwningRef<Vec<u8>, [u8]> = OwningRef::new(buf).into(); - return Ok(buf.map_owner_box().erase_owner()); - } - } - - Err("Couldnt find metadata section".to_string()) - } - - fn get_dylib_metadata(&self, - _target: &Target, - _filename: &Path) - -> Result<ErasedBoxRef<[u8]>, String> { - panic!("Dylib metadata loading not supported without LLVM") - } - } -} +pub use rustc_trans::LlvmTransCrate as DefaultTransCrate; #[cfg(not(feature="llvm"))] mod rustc_trans { use syntax_pos::symbol::Symbol; use rustc::session::Session; - use rustc::session::config::{PrintRequest, OutputFilenames}; - use rustc::ty::{TyCtxt, CrateAnalysis}; - use rustc::ty::maps::Providers; - use rustc_incremental::IncrementalHashesMap; - - use self::back::write::OngoingCrateTranslation; + use rustc::session::config::PrintRequest; + pub use rustc_trans_utils::trans_crate::MetadataOnlyTransCrate as LlvmTransCrate; + pub use rustc_trans_utils::trans_crate::TranslatedCrate as CrateTranslation; pub fn init(_sess: &Session) {} pub fn enable_llvm_debug() {} - pub fn provide(_providers: &mut Providers) {} pub fn print_version() {} pub fn print_passes() {} pub fn print(_req: PrintRequest, _sess: &Session) {} pub fn target_features(_sess: &Session) -> Vec<Symbol> { vec![] } - pub fn trans_crate<'a, 'tcx>( - _tcx: TyCtxt<'a, 'tcx, 'tcx>, - _analysis: CrateAnalysis, - _incr_hashes_map: IncrementalHashesMap, - _output_filenames: &OutputFilenames - ) -> OngoingCrateTranslation { - OngoingCrateTranslation(()) - } - - pub struct CrateTranslation(()); - pub mod back { pub mod write { - pub struct OngoingCrateTranslation(pub (in ::rustc_trans) ()); - pub const RELOC_MODEL_ARGS: [(&'static str, ()); 0] = []; pub const CODE_GEN_MODEL_ARGS: [(&'static str, ()); 0] = []; } } - - __build_diagnostic_array! { librustc_trans, DIAGNOSTICS } } // Parse args and run the compiler. This is the primary entry point for rustc. @@ -293,7 +224,7 @@ pub fn run_compiler<'a>(args: &[String], }, }; - let cstore = Rc::new(CStore::new(box ::MetadataLoader)); + let cstore = Rc::new(CStore::new(DefaultTransCrate::metadata_loader())); let loader = file_loader.unwrap_or(box RealFileLoader); let codemap = Rc::new(CodeMap::with_file_loader(loader, sopts.file_path_mapping())); @@ -1331,6 +1262,7 @@ pub fn diagnostics_registry() -> errors::registry::Registry { all_errors.extend_from_slice(&rustc_borrowck::DIAGNOSTICS); all_errors.extend_from_slice(&rustc_resolve::DIAGNOSTICS); all_errors.extend_from_slice(&rustc_privacy::DIAGNOSTICS); + #[cfg(feature="llvm")] all_errors.extend_from_slice(&rustc_trans::DIAGNOSTICS); all_errors.extend_from_slice(&rustc_const_eval::DIAGNOSTICS); all_errors.extend_from_slice(&rustc_metadata::DIAGNOSTICS); diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index cd153b82077..2f665af8433 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -20,7 +20,6 @@ use {abort_on_err, driver}; use rustc::ty::{self, TyCtxt, GlobalArenas, Resolutions}; use rustc::cfg; use rustc::cfg::graphviz::LabelledCFG; -use rustc::dep_graph::DepGraph; use rustc::middle::cstore::CrateStore; use rustc::session::Session; use rustc::session::config::{Input, OutputFilenames}; @@ -237,7 +236,7 @@ impl PpSourceMode { arenas, id, output_filenames, - |tcx, _, _, _, _| { + |tcx, _, _, _| { let empty_tables = ty::TypeckTables::empty(None); let annotation = TypedAnnotation { tcx, @@ -848,9 +847,6 @@ pub fn print_after_parsing(sess: &Session, krate: &ast::Crate, ppm: PpMode, ofile: Option<&Path>) { - let dep_graph = DepGraph::new(false); - let _ignore = dep_graph.in_ignore(); - let (src, src_name) = get_source(input, sess); let mut rdr = &*src; @@ -893,9 +889,6 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, output_filenames: &OutputFilenames, opt_uii: Option<UserIdentifiedItem>, ofile: Option<&Path>) { - let dep_graph = DepGraph::new(false); - let _ignore = dep_graph.in_ignore(); - if ppm.needs_analysis() { print_with_analysis(sess, cstore, @@ -1036,7 +1029,7 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session, arenas, crate_name, output_filenames, - |tcx, _, _, _, _| { + |tcx, _, _, _| { match ppm { PpmMir | PpmMirCFG => { if let Some(nodeid) = nodeid { diff --git a/src/librustc_driver/profile/trace.rs b/src/librustc_driver/profile/trace.rs index f5079836c3c..280f3c8c796 100644 --- a/src/librustc_driver/profile/trace.rs +++ b/src/librustc_driver/profile/trace.rs @@ -9,7 +9,7 @@ // except according to those terms. use super::*; -use syntax_pos::Span; +use syntax_pos::SpanData; use rustc::ty::maps::QueryMsg; use std::fs::File; use std::time::{Duration, Instant}; @@ -18,7 +18,7 @@ use rustc::dep_graph::{DepNode}; #[derive(Debug, Clone, Eq, PartialEq)] pub struct Query { - pub span: Span, + pub span: SpanData, pub msg: QueryMsg, } pub enum Effect { diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index daabf481e46..6de36820f0c 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -30,6 +30,7 @@ use rustc::hir::map as hir_map; use rustc::mir::transform::Passes; use rustc::session::{self, config}; use rustc::session::config::{OutputFilenames, OutputTypes}; +use rustc_trans_utils::trans_crate::TransCrate; use std::rc::Rc; use syntax::ast; use syntax::abi::Abi; @@ -105,7 +106,7 @@ fn test_env<F>(source_string: &str, options.unstable_features = UnstableFeatures::Allow; let diagnostic_handler = errors::Handler::with_emitter(true, false, emitter); - let cstore = Rc::new(CStore::new(box ::MetadataLoader)); + let cstore = Rc::new(CStore::new(::DefaultTransCrate::metadata_loader())); let sess = session::build_session_(options, None, diagnostic_handler, @@ -133,7 +134,7 @@ fn test_env<F>(source_string: &str, let arena = DroplessArena::new(); let arenas = ty::GlobalArenas::new(); - let hir_map = hir_map::map_crate(&mut hir_forest, &defs); + let hir_map = hir_map::map_crate(&sess, &*cstore, &mut hir_forest, &defs); // run just enough stuff to build a tcx: let named_region_map = resolve_lifetime::krate(&sess, &*cstore, &hir_map); diff --git a/src/librustc_incremental/calculate_svh/mod.rs b/src/librustc_incremental/calculate_svh/mod.rs deleted file mode 100644 index 0329aa8d674..00000000000 --- a/src/librustc_incremental/calculate_svh/mod.rs +++ /dev/null @@ -1,331 +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 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Calculation of the (misnamed) "strict version hash" for crates and -//! items. This hash is used to tell when the HIR changed in such a -//! way that results from previous compilations may no longer be -//! applicable and hence must be recomputed. It should probably be -//! renamed to the ICH (incremental compilation hash). -//! -//! The hashes for all items are computed once at the beginning of -//! compilation and stored into a map. In addition, a hash is computed -//! of the **entire crate**. -//! -//! Storing the hashes in a map avoids the need to compute them twice -//! (once when loading prior incremental results and once when -//! saving), but it is also important for correctness: at least as of -//! the time of this writing, the typeck passes rewrites entries in -//! the dep-map in-place to accommodate UFCS resolutions. Since name -//! resolution is part of the hash, the result is that hashes computed -//! at the end of compilation would be different from those computed -//! at the beginning. - -use std::cell::RefCell; -use std::hash::Hash; -use rustc::dep_graph::{DepNode, DepKind}; -use rustc::hir; -use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex}; -use rustc::hir::map::DefPathHash; -use rustc::hir::itemlikevisit::ItemLikeVisitor; -use rustc::ich::{Fingerprint, StableHashingContext}; -use rustc::ty::TyCtxt; -use rustc::util::common::record_time; -use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; -use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::accumulate_vec::AccumulateVec; - -pub type IchHasher = StableHasher<Fingerprint>; - -pub struct IncrementalHashesMap { - hashes: FxHashMap<DepNode, Fingerprint>, - - // These are the metadata hashes for the current crate as they were stored - // during the last compilation session. They are only loaded if - // -Z query-dep-graph was specified and are needed for auto-tests using - // the #[rustc_metadata_dirty] and #[rustc_metadata_clean] attributes to - // check whether some metadata hash has changed in between two revisions. - pub prev_metadata_hashes: RefCell<FxHashMap<DefId, Fingerprint>>, -} - -impl IncrementalHashesMap { - pub fn new() -> IncrementalHashesMap { - IncrementalHashesMap { - hashes: FxHashMap(), - prev_metadata_hashes: RefCell::new(FxHashMap()), - } - } - - pub fn insert(&mut self, k: DepNode, v: Fingerprint) { - assert!(self.hashes.insert(k, v).is_none()); - } - - pub fn iter<'a>(&'a self) - -> ::std::collections::hash_map::Iter<'a, DepNode, Fingerprint> { - self.hashes.iter() - } - - pub fn len(&self) -> usize { - self.hashes.len() - } -} - -impl<'a> ::std::ops::Index<&'a DepNode> for IncrementalHashesMap { - type Output = Fingerprint; - - fn index(&self, index: &'a DepNode) -> &Fingerprint { - match self.hashes.get(index) { - Some(fingerprint) => fingerprint, - None => { - bug!("Could not find ICH for {:?}", index); - } - } - } -} - -struct ComputeItemHashesVisitor<'a, 'tcx: 'a> { - tcx: TyCtxt<'a, 'tcx, 'tcx>, - hcx: StableHashingContext<'tcx>, - hashes: IncrementalHashesMap, -} - -impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> { - fn compute_and_store_ich_for_item_like<T>(&mut self, - def_index: DefIndex, - hash_bodies: bool, - item_like: T) - where T: HashStable<StableHashingContext<'tcx>> - { - if !hash_bodies && !self.tcx.sess.opts.build_dep_graph() { - // If we just need the hashes in order to compute the SVH, we don't - // need have two hashes per item. Just the one containing also the - // item's body is sufficient. - return - } - - let def_path_hash = self.hcx.local_def_path_hash(def_index); - - let mut hasher = IchHasher::new(); - self.hcx.while_hashing_hir_bodies(hash_bodies, |hcx| { - item_like.hash_stable(hcx, &mut hasher); - }); - - let bytes_hashed = hasher.bytes_hashed(); - let item_hash = hasher.finish(); - let dep_node = if hash_bodies { - def_path_hash.to_dep_node(DepKind::HirBody) - } else { - def_path_hash.to_dep_node(DepKind::Hir) - }; - debug!("calculate_def_hash: dep_node={:?} hash={:?}", dep_node, item_hash); - self.hashes.insert(dep_node, item_hash); - - let bytes_hashed = - self.tcx.sess.perf_stats.incr_comp_bytes_hashed.get() + bytes_hashed; - self.tcx.sess.perf_stats.incr_comp_bytes_hashed.set(bytes_hashed); - - if hash_bodies { - let in_scope_traits_map = self.tcx.in_scope_traits_map(def_index); - let mut hasher = IchHasher::new(); - in_scope_traits_map.hash_stable(&mut self.hcx, &mut hasher); - let dep_node = def_path_hash.to_dep_node(DepKind::InScopeTraits); - self.hashes.insert(dep_node, hasher.finish()); - } - } - - fn compute_crate_hash(&mut self) { - let krate = self.tcx.hir.krate(); - - let mut crate_state = IchHasher::new(); - - let crate_disambiguator = self.tcx.sess.local_crate_disambiguator(); - "crate_disambiguator".hash(&mut crate_state); - crate_disambiguator.as_str().len().hash(&mut crate_state); - crate_disambiguator.as_str().hash(&mut crate_state); - - // add each item (in some deterministic order) to the overall - // crate hash. - { - let mut item_hashes: Vec<_> = - self.hashes.iter() - .filter_map(|(&item_dep_node, &item_hash)| { - // This `match` determines what kinds of nodes - // go into the SVH: - match item_dep_node.kind { - DepKind::InScopeTraits | - DepKind::Hir | - DepKind::HirBody => { - // We want to incoporate these into the - // SVH. - } - DepKind::AllLocalTraitImpls => { - // These are already covered by hashing - // the HIR. - return None - } - ref other => { - bug!("Found unexpected DepKind during \ - SVH computation: {:?}", - other) - } - } - - Some((item_dep_node, item_hash)) - }) - .collect(); - item_hashes.sort_unstable(); // avoid artificial dependencies on item ordering - item_hashes.hash(&mut crate_state); - } - - krate.attrs.hash_stable(&mut self.hcx, &mut crate_state); - - let crate_hash = crate_state.finish(); - self.hashes.insert(DepNode::new_no_params(DepKind::Krate), crate_hash); - debug!("calculate_crate_hash: crate_hash={:?}", crate_hash); - } - - fn hash_crate_root_module(&mut self, krate: &'tcx hir::Crate) { - let hir::Crate { - ref module, - // Crate attributes are not copied over to the root `Mod`, so hash - // them explicitly here. - ref attrs, - span, - - // These fields are handled separately: - exported_macros: _, - items: _, - trait_items: _, - impl_items: _, - bodies: _, - trait_impls: _, - trait_default_impl: _, - body_ids: _, - } = *krate; - - self.compute_and_store_ich_for_item_like(CRATE_DEF_INDEX, - false, - (module, (span, attrs))); - self.compute_and_store_ich_for_item_like(CRATE_DEF_INDEX, - true, - (module, (span, attrs))); - } - - fn compute_and_store_ich_for_trait_impls(&mut self, krate: &'tcx hir::Crate) - { - let tcx = self.tcx; - - let mut impls: Vec<(DefPathHash, Fingerprint)> = krate - .trait_impls - .iter() - .map(|(&trait_id, impls)| { - let trait_id = tcx.def_path_hash(trait_id); - let mut impls: AccumulateVec<[_; 32]> = impls - .iter() - .map(|&node_id| { - let def_id = tcx.hir.local_def_id(node_id); - tcx.def_path_hash(def_id) - }) - .collect(); - - impls.sort_unstable(); - let mut hasher = StableHasher::new(); - impls.hash_stable(&mut self.hcx, &mut hasher); - (trait_id, hasher.finish()) - }) - .collect(); - - impls.sort_unstable(); - - let mut default_impls: AccumulateVec<[_; 32]> = krate - .trait_default_impl - .iter() - .map(|(&trait_def_id, &impl_node_id)| { - let impl_def_id = tcx.hir.local_def_id(impl_node_id); - (tcx.def_path_hash(trait_def_id), tcx.def_path_hash(impl_def_id)) - }) - .collect(); - - default_impls.sort_unstable(); - - let mut hasher = StableHasher::new(); - impls.hash_stable(&mut self.hcx, &mut hasher); - - self.hashes.insert(DepNode::new_no_params(DepKind::AllLocalTraitImpls), - hasher.finish()); - } -} - -impl<'a, 'tcx: 'a> ItemLikeVisitor<'tcx> for ComputeItemHashesVisitor<'a, 'tcx> { - fn visit_item(&mut self, item: &'tcx hir::Item) { - let def_index = self.tcx.hir.local_def_id(item.id).index; - self.compute_and_store_ich_for_item_like(def_index, - false, - item); - self.compute_and_store_ich_for_item_like(def_index, - true, - item); - } - - fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) { - let def_index = self.tcx.hir.local_def_id(item.id).index; - self.compute_and_store_ich_for_item_like(def_index, - false, - item); - self.compute_and_store_ich_for_item_like(def_index, - true, - item); - } - - fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) { - let def_index = self.tcx.hir.local_def_id(item.id).index; - self.compute_and_store_ich_for_item_like(def_index, - false, - item); - self.compute_and_store_ich_for_item_like(def_index, - true, - item); - } -} - - - -pub fn compute_incremental_hashes_map<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> IncrementalHashesMap { - let _ignore = tcx.dep_graph.in_ignore(); - let krate = tcx.hir.krate(); - - let mut visitor = ComputeItemHashesVisitor { - tcx, - hcx: tcx.create_stable_hashing_context(), - hashes: IncrementalHashesMap::new(), - }; - - record_time(&tcx.sess.perf_stats.incr_comp_hashes_time, || { - visitor.hash_crate_root_module(krate); - krate.visit_all_item_likes(&mut visitor); - - for macro_def in krate.exported_macros.iter() { - let def_index = tcx.hir.local_def_id(macro_def.id).index; - visitor.compute_and_store_ich_for_item_like(def_index, - false, - macro_def); - visitor.compute_and_store_ich_for_item_like(def_index, - true, - macro_def); - } - - visitor.compute_and_store_ich_for_trait_impls(krate); - }); - - tcx.sess.perf_stats.incr_comp_hashes_count.set(visitor.hashes.len() as u64); - - record_time(&tcx.sess.perf_stats.svh_time, || visitor.compute_crate_hash()); - visitor.hashes -} diff --git a/src/librustc_incremental/lib.rs b/src/librustc_incremental/lib.rs index 3c1e02f8a5a..0fba6d8e9c6 100644 --- a/src/librustc_incremental/lib.rs +++ b/src/librustc_incremental/lib.rs @@ -28,14 +28,11 @@ extern crate syntax; extern crate syntax_pos; mod assert_dep_graph; -mod calculate_svh; mod persist; pub use assert_dep_graph::assert_dep_graph; -pub use calculate_svh::compute_incremental_hashes_map; -pub use calculate_svh::IncrementalHashesMap; -pub use calculate_svh::IchHasher; pub use persist::load_dep_graph; +pub use persist::load_dep_graph_new; pub use persist::save_dep_graph; pub use persist::save_trans_partition; pub use persist::save_work_products; diff --git a/src/librustc_incremental/persist/data.rs b/src/librustc_incremental/persist/data.rs index 06acfb5d778..9050702e3ca 100644 --- a/src/librustc_incremental/persist/data.rs +++ b/src/librustc_incremental/persist/data.rs @@ -70,14 +70,6 @@ impl SerializedDepGraph { RustcEncodable, RustcDecodable)] pub struct DepNodeIndex(pub u32); -impl DepNodeIndex { - #[inline] - pub fn new(idx: usize) -> DepNodeIndex { - assert!(idx <= ::std::u32::MAX as usize); - DepNodeIndex(idx as u32) - } -} - impl Idx for DepNodeIndex { #[inline] fn new(idx: usize) -> Self { diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index 126057fd043..a6d39a91863 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -8,18 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Debugging code to test the state of the dependency graph just -//! after it is loaded from disk and just after it has been saved. +//! Debugging code to test fingerprints computed for query results. //! For each node marked with `#[rustc_clean]` or `#[rustc_dirty]`, -//! we will check that a suitable node for that item either appears -//! or does not appear in the dep-graph, as appropriate: +//! we will compare the fingerprint from the current and from the previous +//! compilation session as appropriate: //! //! - `#[rustc_dirty(label="TypeckTables", cfg="rev2")]` if we are -//! in `#[cfg(rev2)]`, then there MUST NOT be a node -//! `DepNode::TypeckTables(X)` where `X` is the def-id of the -//! current node. +//! in `#[cfg(rev2)]`, then the fingerprints associated with +//! `DepNode::TypeckTables(X)` must be DIFFERENT (`X` is the def-id of the +//! current node). //! - `#[rustc_clean(label="TypeckTables", cfg="rev2")]` same as above, -//! except that the node MUST exist. +//! except that the fingerprints must be the SAME. //! //! Errors are reported if we are in the suitable configuration but //! the required condition is not met. @@ -40,9 +39,7 @@ //! previous revision to compare things to. //! -use super::data::DepNodeIndex; -use super::load::DirtyNodes; -use rustc::dep_graph::{DepGraphQuery, DepNode, DepKind}; +use rustc::dep_graph::DepNode; use rustc::hir; use rustc::hir::def_id::DefId; use rustc::hir::itemlikevisit::ItemLikeVisitor; @@ -51,41 +48,22 @@ use rustc::ich::{Fingerprint, ATTR_DIRTY, ATTR_CLEAN, ATTR_DIRTY_METADATA, ATTR_CLEAN_METADATA}; use syntax::ast::{self, Attribute, NestedMetaItem}; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; -use rustc_data_structures::indexed_vec::IndexVec; use syntax_pos::Span; use rustc::ty::TyCtxt; const LABEL: &'static str = "label"; const CFG: &'static str = "cfg"; -pub fn check_dirty_clean_annotations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - nodes: &IndexVec<DepNodeIndex, DepNode>, - dirty_inputs: &DirtyNodes) { +pub fn check_dirty_clean_annotations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { // can't add `#[rustc_dirty]` etc without opting in to this feature if !tcx.sess.features.borrow().rustc_attrs { return; } let _ignore = tcx.dep_graph.in_ignore(); - let dirty_inputs: FxHashSet<DepNode> = - dirty_inputs.keys() - .filter_map(|dep_node_index| { - let dep_node = nodes[*dep_node_index]; - if dep_node.extract_def_id(tcx).is_some() { - Some(dep_node) - } else { - None - } - }) - .collect(); - - let query = tcx.dep_graph.query(); - debug!("query-nodes: {:?}", query.nodes()); let krate = tcx.hir.krate(); let mut dirty_clean_visitor = DirtyCleanVisitor { tcx, - query: &query, - dirty_inputs, checked_attrs: FxHashSet(), }; krate.visit_all_item_likes(&mut dirty_clean_visitor); @@ -105,8 +83,6 @@ pub fn check_dirty_clean_annotations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pub struct DirtyCleanVisitor<'a, 'tcx:'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, - query: &'a DepGraphQuery, - dirty_inputs: FxHashSet<DepNode>, checked_attrs: FxHashSet<ast::AttrId>, } @@ -143,59 +119,28 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { fn assert_dirty(&self, item_span: Span, dep_node: DepNode) { debug!("assert_dirty({:?})", dep_node); - match dep_node.kind { - DepKind::Krate | - DepKind::Hir | - DepKind::HirBody => { - // HIR nodes are inputs, so if we are asserting that the HIR node is - // dirty, we check the dirty input set. - if !self.dirty_inputs.contains(&dep_node) { - let dep_node_str = self.dep_node_str(&dep_node); - self.tcx.sess.span_err( - item_span, - &format!("`{}` not found in dirty set, but should be dirty", - dep_node_str)); - } - } - _ => { - // Other kinds of nodes would be targets, so check if - // the dep-graph contains the node. - if self.query.contains_node(&dep_node) { - let dep_node_str = self.dep_node_str(&dep_node); - self.tcx.sess.span_err( - item_span, - &format!("`{}` found in dep graph, but should be dirty", dep_node_str)); - } - } + let current_fingerprint = self.tcx.dep_graph.fingerprint_of(&dep_node); + let prev_fingerprint = self.tcx.dep_graph.prev_fingerprint_of(&dep_node); + + if current_fingerprint == prev_fingerprint { + let dep_node_str = self.dep_node_str(&dep_node); + self.tcx.sess.span_err( + item_span, + &format!("`{}` should be dirty but is not", dep_node_str)); } } fn assert_clean(&self, item_span: Span, dep_node: DepNode) { debug!("assert_clean({:?})", dep_node); - match dep_node.kind { - DepKind::Krate | - DepKind::Hir | - DepKind::HirBody => { - // For HIR nodes, check the inputs. - if self.dirty_inputs.contains(&dep_node) { - let dep_node_str = self.dep_node_str(&dep_node); - self.tcx.sess.span_err( - item_span, - &format!("`{}` found in dirty-node set, but should be clean", - dep_node_str)); - } - } - _ => { - // Otherwise, check if the dep-node exists. - if !self.query.contains_node(&dep_node) { - let dep_node_str = self.dep_node_str(&dep_node); - self.tcx.sess.span_err( - item_span, - &format!("`{}` not found in dep graph, but should be clean", - dep_node_str)); - } - } + let current_fingerprint = self.tcx.dep_graph.fingerprint_of(&dep_node); + let prev_fingerprint = self.tcx.dep_graph.prev_fingerprint_of(&dep_node); + + if current_fingerprint != prev_fingerprint { + let dep_node_str = self.dep_node_str(&dep_node); + self.tcx.sess.span_err( + item_span, + &format!("`{}` should be clean but is not", dep_node_str)); } } diff --git a/src/librustc_incremental/persist/fs.rs b/src/librustc_incremental/persist/fs.rs index f3f35a50fe0..592b8f1a9eb 100644 --- a/src/librustc_incremental/persist/fs.rs +++ b/src/librustc_incremental/persist/fs.rs @@ -114,15 +114,12 @@ //! unsupported file system and emit a warning in that case. This is not yet //! implemented. -use rustc::hir::def_id::CrateNum; use rustc::hir::svh::Svh; use rustc::session::Session; -use rustc::ty::TyCtxt; use rustc::util::fs as fs_util; use rustc_data_structures::{flock, base_n}; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; -use std::ffi::OsString; use std::fs as std_fs; use std::io; use std::mem; @@ -132,6 +129,7 @@ use std::__rand::{thread_rng, Rng}; const LOCK_FILE_EXT: &'static str = ".lock"; const DEP_GRAPH_FILENAME: &'static str = "dep-graph.bin"; +const DEP_GRAPH_NEW_FILENAME: &'static str = "dep-graph-new.bin"; const WORK_PRODUCTS_FILENAME: &'static str = "work-products.bin"; const METADATA_HASHES_FILENAME: &'static str = "metadata.bin"; @@ -145,6 +143,10 @@ pub fn dep_graph_path(sess: &Session) -> PathBuf { in_incr_comp_dir_sess(sess, DEP_GRAPH_FILENAME) } +pub fn dep_graph_path_new(sess: &Session) -> PathBuf { + in_incr_comp_dir_sess(sess, DEP_GRAPH_NEW_FILENAME) +} + pub fn work_products_path(sess: &Session) -> PathBuf { in_incr_comp_dir_sess(sess, WORK_PRODUCTS_FILENAME) } @@ -153,10 +155,6 @@ pub fn metadata_hash_export_path(sess: &Session) -> PathBuf { in_incr_comp_dir_sess(sess, METADATA_HASHES_FILENAME) } -pub fn metadata_hash_import_path(import_session_dir: &Path) -> PathBuf { - import_session_dir.join(METADATA_HASHES_FILENAME) -} - pub fn lock_file_path(session_dir: &Path) -> PathBuf { let crate_dir = session_dir.parent().unwrap(); @@ -616,70 +614,6 @@ fn string_to_timestamp(s: &str) -> Result<SystemTime, ()> { Ok(UNIX_EPOCH + duration) } -fn crate_path_tcx(tcx: TyCtxt, cnum: CrateNum) -> PathBuf { - crate_path(tcx.sess, &tcx.crate_name(cnum).as_str(), &tcx.crate_disambiguator(cnum).as_str()) -} - -/// Finds the session directory containing the correct metadata hashes file for -/// the given crate. In order to do that it has to compute the crate directory -/// of the given crate, and in there, look for the session directory with the -/// correct SVH in it. -/// Note that we have to match on the exact SVH here, not just the -/// crate's (name, disambiguator) pair. The metadata hashes are only valid for -/// the exact version of the binary we are reading from now (i.e. the hashes -/// are part of the dependency graph of a specific compilation session). -pub fn find_metadata_hashes_for(tcx: TyCtxt, cnum: CrateNum) -> Option<PathBuf> { - let crate_directory = crate_path_tcx(tcx, cnum); - - if !crate_directory.exists() { - return None - } - - let dir_entries = match crate_directory.read_dir() { - Ok(dir_entries) => dir_entries, - Err(e) => { - tcx.sess - .err(&format!("incremental compilation: Could not read crate directory `{}`: {}", - crate_directory.display(), e)); - return None - } - }; - - let target_svh = tcx.crate_hash(cnum); - let target_svh = base_n::encode(target_svh.as_u64(), INT_ENCODE_BASE); - - let sub_dir = find_metadata_hashes_iter(&target_svh, dir_entries.filter_map(|e| { - e.ok().map(|e| e.file_name().to_string_lossy().into_owned()) - })); - - sub_dir.map(|sub_dir_name| crate_directory.join(&sub_dir_name)) -} - -fn find_metadata_hashes_iter<'a, I>(target_svh: &str, iter: I) -> Option<OsString> - where I: Iterator<Item=String> -{ - for sub_dir_name in iter { - if !is_session_directory(&sub_dir_name) || !is_finalized(&sub_dir_name) { - // This is not a usable session directory - continue - } - - let is_match = if let Some(last_dash_pos) = sub_dir_name.rfind("-") { - let candidate_svh = &sub_dir_name[last_dash_pos + 1 .. ]; - target_svh == candidate_svh - } else { - // some kind of invalid directory name - continue - }; - - if is_match { - return Some(OsString::from(sub_dir_name)) - } - } - - None -} - fn crate_path(sess: &Session, crate_name: &str, crate_disambiguator: &str) @@ -1019,52 +953,3 @@ fn test_find_source_directory_in_iter() { PathBuf::from("crate-dir/s-1234-0000-working")].into_iter(), &already_visited), None); } - -#[test] -fn test_find_metadata_hashes_iter() -{ - assert_eq!(find_metadata_hashes_iter("testsvh2", - vec![ - String::from("s-timestamp1-testsvh1"), - String::from("s-timestamp2-testsvh2"), - String::from("s-timestamp3-testsvh3"), - ].into_iter()), - Some(OsString::from("s-timestamp2-testsvh2")) - ); - - assert_eq!(find_metadata_hashes_iter("testsvh2", - vec![ - String::from("s-timestamp1-testsvh1"), - String::from("s-timestamp2-testsvh2"), - String::from("invalid-name"), - ].into_iter()), - Some(OsString::from("s-timestamp2-testsvh2")) - ); - - assert_eq!(find_metadata_hashes_iter("testsvh2", - vec![ - String::from("s-timestamp1-testsvh1"), - String::from("s-timestamp2-testsvh2-working"), - String::from("s-timestamp3-testsvh3"), - ].into_iter()), - None - ); - - assert_eq!(find_metadata_hashes_iter("testsvh1", - vec![ - String::from("s-timestamp1-random1-working"), - String::from("s-timestamp2-random2-working"), - String::from("s-timestamp3-random3-working"), - ].into_iter()), - None - ); - - assert_eq!(find_metadata_hashes_iter("testsvh2", - vec![ - String::from("timestamp1-testsvh2"), - String::from("timestamp2-testsvh2"), - String::from("timestamp3-testsvh2"), - ].into_iter()), - None - ); -} diff --git a/src/librustc_incremental/persist/hash.rs b/src/librustc_incremental/persist/hash.rs deleted file mode 100644 index 8355f319139..00000000000 --- a/src/librustc_incremental/persist/hash.rs +++ /dev/null @@ -1,227 +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 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use rustc::dep_graph::{DepNode, DepKind}; -use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; -use rustc::hir::svh::Svh; -use rustc::ich::Fingerprint; -use rustc::ty::TyCtxt; -use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::flock; -use rustc_serialize::Decodable; -use rustc_serialize::opaque::Decoder; - -use IncrementalHashesMap; -use super::data::*; -use super::fs::*; -use super::file_format; - -use std::hash::Hash; -use std::fmt::Debug; - -pub struct HashContext<'a, 'tcx: 'a> { - pub tcx: TyCtxt<'a, 'tcx, 'tcx>, - incremental_hashes_map: &'a IncrementalHashesMap, - metadata_hashes: FxHashMap<DefId, Fingerprint>, - crate_hashes: FxHashMap<CrateNum, Svh>, -} - -impl<'a, 'tcx> HashContext<'a, 'tcx> { - pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, - incremental_hashes_map: &'a IncrementalHashesMap) - -> Self { - HashContext { - tcx, - incremental_hashes_map, - metadata_hashes: FxHashMap(), - crate_hashes: FxHashMap(), - } - } - - pub fn is_hashable(tcx: TyCtxt, dep_node: &DepNode) -> bool { - match dep_node.kind { - DepKind::Krate | - DepKind::Hir | - DepKind::InScopeTraits | - DepKind::HirBody => - true, - DepKind::MetaData => { - let def_id = dep_node.extract_def_id(tcx).unwrap(); - !def_id.is_local() - } - _ => false, - } - } - - pub fn hash(&mut self, dep_node: &DepNode) -> Option<Fingerprint> { - match dep_node.kind { - DepKind::Krate => { - Some(self.incremental_hashes_map[dep_node]) - } - - // HIR nodes (which always come from our crate) are an input: - DepKind::InScopeTraits | - DepKind::Hir | - DepKind::HirBody => { - Some(self.incremental_hashes_map[dep_node]) - } - - // MetaData from other crates is an *input* to us. - // MetaData nodes from *our* crates are an *output*; we - // don't hash them, but we do compute a hash for them and - // save it for others to use. - DepKind::MetaData => { - let def_id = dep_node.extract_def_id(self.tcx).unwrap(); - if !def_id.is_local() { - Some(self.metadata_hash(def_id, - def_id.krate, - |this| &mut this.metadata_hashes)) - } else { - None - } - } - - _ => { - // Other kinds of nodes represent computed by-products - // that we don't hash directly; instead, they should - // have some transitive dependency on a Hir or - // MetaData node, so we'll just hash that - None - } - } - } - - fn metadata_hash<K, C>(&mut self, - key: K, - cnum: CrateNum, - cache: C) - -> Fingerprint - where K: Hash + Eq + Debug, - C: Fn(&mut Self) -> &mut FxHashMap<K, Fingerprint>, - { - debug!("metadata_hash(key={:?})", key); - - debug_assert!(cnum != LOCAL_CRATE); - loop { - // check whether we have a result cached for this def-id - if let Some(&hash) = cache(self).get(&key) { - return hash; - } - - // check whether we did not find detailed metadata for this - // krate; in that case, we just use the krate's overall hash - if let Some(&svh) = self.crate_hashes.get(&cnum) { - // micro-"optimization": avoid a cache miss if we ask - // for metadata from this particular def-id again. - let fingerprint = svh_to_fingerprint(svh); - cache(self).insert(key, fingerprint); - - return fingerprint; - } - - // otherwise, load the data and repeat. - self.load_data(cnum); - assert!(self.crate_hashes.contains_key(&cnum)); - } - } - - fn load_data(&mut self, cnum: CrateNum) { - debug!("load_data(cnum={})", cnum); - - let svh = self.tcx.crate_hash(cnum); - let old = self.crate_hashes.insert(cnum, svh); - debug!("load_data: svh={}", svh); - assert!(old.is_none(), "loaded data for crate {:?} twice", cnum); - - if let Some(session_dir) = find_metadata_hashes_for(self.tcx, cnum) { - debug!("load_data: session_dir={:?}", session_dir); - - // Lock the directory we'll be reading the hashes from. - let lock_file_path = lock_file_path(&session_dir); - let _lock = match flock::Lock::new(&lock_file_path, - false, // don't wait - false, // don't create the lock-file - false) { // shared lock - Ok(lock) => lock, - Err(err) => { - debug!("Could not acquire lock on `{}` while trying to \ - load metadata hashes: {}", - lock_file_path.display(), - err); - - // Could not acquire the lock. The directory is probably in - // in the process of being deleted. It's OK to just exit - // here. It's the same scenario as if the file had not - // existed in the first place. - return - } - }; - - let hashes_file_path = metadata_hash_import_path(&session_dir); - - match file_format::read_file(self.tcx.sess, &hashes_file_path) - { - Ok(Some(data)) => { - match self.load_from_data(cnum, &data, svh) { - Ok(()) => { } - Err(err) => { - bug!("decoding error in dep-graph from `{}`: {}", - &hashes_file_path.display(), err); - } - } - } - Ok(None) => { - // If the file is not found, that's ok. - } - Err(err) => { - self.tcx.sess.err( - &format!("could not load dep information from `{}`: {}", - hashes_file_path.display(), err)); - } - } - } - } - - fn load_from_data(&mut self, - cnum: CrateNum, - data: &[u8], - expected_svh: Svh) -> Result<(), String> { - debug!("load_from_data(cnum={})", cnum); - - // Load up the hashes for the def-ids from this crate. - let mut decoder = Decoder::new(data, 0); - let svh_in_hashes_file = Svh::decode(&mut decoder)?; - - if svh_in_hashes_file != expected_svh { - // We should not be able to get here. If we do, then - // `fs::find_metadata_hashes_for()` has messed up. - bug!("mismatch between SVH in crate and SVH in incr. comp. hashes") - } - - let serialized_hashes = SerializedMetadataHashes::decode(&mut decoder)?; - for serialized_hash in serialized_hashes.entry_hashes { - // the hashes are stored with just a def-index, which is - // always relative to the old crate; convert that to use - // our internal crate number - let def_id = DefId { krate: cnum, index: serialized_hash.def_index }; - - // record the hash for this dep-node - let old = self.metadata_hashes.insert(def_id, serialized_hash.hash); - debug!("load_from_data: def_id={:?} hash={}", def_id, serialized_hash.hash); - assert!(old.is_none(), "already have hash for {:?}", def_id); - } - - Ok(()) - } -} - -fn svh_to_fingerprint(svh: Svh) -> Fingerprint { - Fingerprint::from_smaller_hash(svh.as_u64()) -} diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs index 9865ea8c285..6d019a25ed3 100644 --- a/src/librustc_incremental/persist/load.rs +++ b/src/librustc_incremental/persist/load.rs @@ -10,22 +10,19 @@ //! Code to save/load the dep-graph from files. -use rustc::dep_graph::{DepNode, WorkProductId, DepKind}; -use rustc::hir::def_id::DefId; +use rustc::dep_graph::{DepNode, WorkProductId, DepKind, PreviousDepGraph}; use rustc::hir::svh::Svh; use rustc::ich::Fingerprint; use rustc::session::Session; use rustc::ty::TyCtxt; +use rustc::util::nodemap::DefIdMap; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use rustc_data_structures::indexed_vec::IndexVec; use rustc_serialize::Decodable as RustcDecodable; use rustc_serialize::opaque::Decoder; use std::path::{Path}; -use IncrementalHashesMap; use super::data::*; -use super::dirty_clean; -use super::hash::*; use super::fs::*; use super::file_format; use super::work_product; @@ -40,16 +37,16 @@ pub type DirtyNodes = FxHashMap<DepNodeIndex, DepNodeIndex>; /// early in compilation, before we've really done any work, but /// actually it doesn't matter all that much.) See `README.md` for /// more general overview. -pub fn load_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - incremental_hashes_map: &IncrementalHashesMap) { +pub fn load_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { + tcx.allocate_metadata_dep_nodes(); + tcx.precompute_in_scope_traits_hashes(); if tcx.sess.incr_session_load_dep_graph() { let _ignore = tcx.dep_graph.in_ignore(); - load_dep_graph_if_exists(tcx, incremental_hashes_map); + load_dep_graph_if_exists(tcx); } } -fn load_dep_graph_if_exists<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - incremental_hashes_map: &IncrementalHashesMap) { +fn load_dep_graph_if_exists<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let dep_graph_path = dep_graph_path(tcx.sess); let dep_graph_data = match load_data(tcx.sess, &dep_graph_path) { Some(p) => p, @@ -62,7 +59,7 @@ fn load_dep_graph_if_exists<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, None => return // no file }; - match decode_dep_graph(tcx, incremental_hashes_map, &dep_graph_data, &work_products_data) { + match decode_dep_graph(tcx, &dep_graph_data, &work_products_data) { Ok(dirty_nodes) => dirty_nodes, Err(err) => { tcx.sess.warn( @@ -105,7 +102,7 @@ fn does_still_exist(tcx: TyCtxt, dep_node: &DepNode) -> bool { DepKind::Hir | DepKind::HirBody | DepKind::InScopeTraits | - DepKind::MetaData => { + DepKind::CrateMetadata => { dep_node.extract_def_id(tcx).is_some() } _ => { @@ -117,7 +114,6 @@ fn does_still_exist(tcx: TyCtxt, dep_node: &DepNode) -> bool { /// Decode the dep graph and load the edges/nodes that are still clean /// into `tcx.dep_graph`. pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - incremental_hashes_map: &IncrementalHashesMap, dep_graph_data: &[u8], work_products_data: &[u8]) -> Result<(), String> @@ -150,7 +146,6 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Compute the set of nodes from the old graph where some input // has changed or been removed. let dirty_raw_nodes = initial_dirty_nodes(tcx, - incremental_hashes_map, &serialized_dep_graph.nodes, &serialized_dep_graph.hashes); let dirty_raw_nodes = transitive_dirty_nodes(&serialized_dep_graph, @@ -190,31 +185,21 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // dirty. reconcile_work_products(tcx, work_products, &clean_work_products); - dirty_clean::check_dirty_clean_annotations(tcx, - &serialized_dep_graph.nodes, - &dirty_raw_nodes); - - load_prev_metadata_hashes(tcx, - &mut *incremental_hashes_map.prev_metadata_hashes.borrow_mut()); Ok(()) } /// Computes which of the original set of def-ids are dirty. Stored in /// a bit vector where the index is the DefPathIndex. fn initial_dirty_nodes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - incremental_hashes_map: &IncrementalHashesMap, nodes: &IndexVec<DepNodeIndex, DepNode>, serialized_hashes: &[(DepNodeIndex, Fingerprint)]) -> DirtyNodes { - let mut hcx = HashContext::new(tcx, incremental_hashes_map); let mut dirty_nodes = FxHashMap(); for &(dep_node_index, prev_hash) in serialized_hashes { let dep_node = nodes[dep_node_index]; if does_still_exist(tcx, &dep_node) { - let current_hash = hcx.hash(&dep_node).unwrap_or_else(|| { - bug!("Cannot find current ICH for input that still exists?") - }); + let current_hash = tcx.dep_graph.fingerprint_of(&dep_node); if current_hash == prev_hash { debug!("initial_dirty_nodes: {:?} is clean (hash={:?})", @@ -310,11 +295,12 @@ fn delete_dirty_work_product(tcx: TyCtxt, work_product::delete_workproduct_files(tcx.sess, &swp.work_product); } -fn load_prev_metadata_hashes(tcx: TyCtxt, - output: &mut FxHashMap<DefId, Fingerprint>) { +pub fn load_prev_metadata_hashes(tcx: TyCtxt) -> DefIdMap<Fingerprint> { + let mut output = DefIdMap(); + if !tcx.sess.opts.debugging_opts.query_dep_graph { // Previous metadata hashes are only needed for testing. - return + return output } debug!("load_prev_metadata_hashes() - Loading previous metadata hashes"); @@ -324,7 +310,7 @@ fn load_prev_metadata_hashes(tcx: TyCtxt, if !file_path.exists() { debug!("load_prev_metadata_hashes() - Couldn't find file containing \ hashes at `{}`", file_path.display()); - return + return output } debug!("load_prev_metadata_hashes() - File: {}", file_path.display()); @@ -334,12 +320,12 @@ fn load_prev_metadata_hashes(tcx: TyCtxt, Ok(None) => { debug!("load_prev_metadata_hashes() - File produced by incompatible \ compiler version: {}", file_path.display()); - return + return output } Err(err) => { debug!("load_prev_metadata_hashes() - Error reading file `{}`: {}", file_path.display(), err); - return + return output } }; @@ -363,6 +349,8 @@ fn load_prev_metadata_hashes(tcx: TyCtxt, debug!("load_prev_metadata_hashes() - successfully loaded {} hashes", serialized_hashes.index_map.len()); + + output } fn process_edge<'a, 'tcx, 'edges>( @@ -421,7 +409,7 @@ fn process_edge<'a, 'tcx, 'edges>( // clean target because removing the input would have dirtied the input // node and transitively dirtied the target. debug_assert!(match nodes[source].kind { - DepKind::Hir | DepKind::HirBody | DepKind::MetaData => { + DepKind::Hir | DepKind::HirBody | DepKind::CrateMetadata => { does_still_exist(tcx, &nodes[source]) } _ => true, @@ -438,3 +426,38 @@ fn process_edge<'a, 'tcx, 'edges>( } } } + +pub fn load_dep_graph_new(sess: &Session) -> PreviousDepGraph { + use rustc::dep_graph::SerializedDepGraph as SerializedDepGraphNew; + + let empty = PreviousDepGraph::new(SerializedDepGraphNew::new()); + + if sess.opts.incremental.is_none() { + return empty + } + + if let Some(bytes) = load_data(sess, &dep_graph_path_new(sess)) { + let mut decoder = Decoder::new(&bytes, 0); + let prev_commandline_args_hash = u64::decode(&mut decoder) + .expect("Error reading commandline arg hash from cached dep-graph"); + + if prev_commandline_args_hash != sess.opts.dep_tracking_hash() { + if sess.opts.debugging_opts.incremental_info { + eprintln!("incremental: completely ignoring cache because of \ + differing commandline arguments"); + } + // We can't reuse the cache, purge it. + debug!("load_dep_graph_new: differing commandline arg hashes"); + + // No need to do any further work + return empty + } + + let dep_graph = SerializedDepGraphNew::decode(&mut decoder) + .expect("Error reading cached dep-graph"); + + PreviousDepGraph::new(dep_graph) + } else { + empty + } +} diff --git a/src/librustc_incremental/persist/mod.rs b/src/librustc_incremental/persist/mod.rs index fb330813226..688d8add57e 100644 --- a/src/librustc_incremental/persist/mod.rs +++ b/src/librustc_incremental/persist/mod.rs @@ -15,7 +15,6 @@ mod data; mod dirty_clean; mod fs; -mod hash; mod load; mod preds; mod save; @@ -26,6 +25,7 @@ pub use self::fs::prepare_session_directory; pub use self::fs::finalize_session_directory; pub use self::fs::in_incr_comp_dir; pub use self::load::load_dep_graph; +pub use self::load::load_dep_graph_new; pub use self::save::save_dep_graph; pub use self::save::save_work_products; pub use self::work_product::save_trans_partition; diff --git a/src/librustc_incremental/persist/preds/mod.rs b/src/librustc_incremental/persist/preds/mod.rs index 5483134523c..a552a27c62a 100644 --- a/src/librustc_incremental/persist/preds/mod.rs +++ b/src/librustc_incremental/persist/preds/mod.rs @@ -10,10 +10,10 @@ use rustc::dep_graph::{DepGraphQuery, DepNode, DepKind}; use rustc::ich::Fingerprint; +use rustc::ty::TyCtxt; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::graph::{Graph, NodeIndex}; -use super::hash::*; mod compress; @@ -40,15 +40,13 @@ pub struct Predecessors<'query> { } impl<'q> Predecessors<'q> { - pub fn new(query: &'q DepGraphQuery, hcx: &mut HashContext) -> Self { - let tcx = hcx.tcx; - + pub fn new(tcx: TyCtxt, query: &'q DepGraphQuery) -> Self { // Find the set of "start nodes". These are nodes that we will // possibly query later. let is_output = |node: &DepNode| -> bool { match node.kind { DepKind::WorkProduct => true, - DepKind::MetaData => { + DepKind::CrateMetadata => { // We do *not* create dep-nodes for the current crate's // metadata anymore, just for metadata that we import/read // from other crates. @@ -66,7 +64,7 @@ impl<'q> Predecessors<'q> { // Reduce the graph to the most important nodes. let compress::Reduction { graph, input_nodes } = compress::reduce_graph(&query.graph, - |n| HashContext::is_hashable(tcx, n), + |n| n.kind.is_input(), |n| is_output(n)); let mut hashes = FxHashMap(); @@ -74,7 +72,7 @@ impl<'q> Predecessors<'q> { let input = *graph.node_data(input_index); debug!("computing hash for input node `{:?}`", input); hashes.entry(input) - .or_insert_with(|| hcx.hash(input).unwrap()); + .or_insert_with(|| tcx.dep_graph.fingerprint_of(&input)); } if tcx.sess.opts.debugging_opts.query_dep_graph { @@ -89,7 +87,7 @@ impl<'q> Predecessors<'q> { for node in hir_nodes { hashes.entry(node) - .or_insert_with(|| hcx.hash(node).unwrap()); + .or_insert_with(|| tcx.dep_graph.fingerprint_of(&node)); } } diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs index 65fbaf1ad04..fd699229f1b 100644 --- a/src/librustc_incremental/persist/save.rs +++ b/src/librustc_incremental/persist/save.rs @@ -15,26 +15,27 @@ use rustc::ich::Fingerprint; use rustc::middle::cstore::EncodedMetadataHashes; use rustc::session::Session; use rustc::ty::TyCtxt; +use rustc::util::common::time; +use rustc::util::nodemap::DefIdMap; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::graph; -use rustc_data_structures::indexed_vec::IndexVec; +use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use rustc_serialize::Encodable as RustcEncodable; use rustc_serialize::opaque::Encoder; use std::io::{self, Cursor, Write}; use std::fs::{self, File}; use std::path::PathBuf; -use IncrementalHashesMap; use super::data::*; -use super::hash::*; use super::preds::*; use super::fs::*; use super::dirty_clean; use super::file_format; use super::work_product; +use super::load::load_prev_metadata_hashes; + pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - incremental_hashes_map: IncrementalHashesMap, metadata_hashes: &EncodedMetadataHashes, svh: Svh) { debug!("save_dep_graph()"); @@ -44,15 +45,14 @@ pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, return; } - let query = tcx.dep_graph.query(); - - if tcx.sess.opts.debugging_opts.incremental_info { - eprintln!("incremental: {} nodes in dep-graph", query.graph.len_nodes()); - eprintln!("incremental: {} edges in dep-graph", query.graph.len_edges()); - } + // We load the previous metadata hashes now before overwriting the file + // (if we need them for testing). + let prev_metadata_hashes = if tcx.sess.opts.debugging_opts.query_dep_graph { + load_prev_metadata_hashes(tcx) + } else { + DefIdMap() + }; - let mut hcx = HashContext::new(tcx, &incremental_hashes_map); - let preds = Predecessors::new(&query, &mut hcx); let mut current_metadata_hashes = FxHashMap(); // IMPORTANT: We are saving the metadata hashes *before* the dep-graph, @@ -69,13 +69,29 @@ pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, e)); } - save_in(sess, - dep_graph_path(sess), - |e| encode_dep_graph(tcx, &preds, e)); + time(sess.time_passes(), "persist dep-graph (old)", || { + let query = tcx.dep_graph.query(); + + if tcx.sess.opts.debugging_opts.incremental_info { + eprintln!("incremental: {} nodes in dep-graph", query.graph.len_nodes()); + eprintln!("incremental: {} edges in dep-graph", query.graph.len_edges()); + } + + let preds = Predecessors::new(tcx, &query); + save_in(sess, + dep_graph_path(sess), + |e| encode_dep_graph(tcx, &preds, e)); + }); - let prev_metadata_hashes = incremental_hashes_map.prev_metadata_hashes.borrow(); + time(sess.time_passes(), "persist dep-graph (new)", || { + save_in(sess, + dep_graph_path_new(sess), + |e| encode_dep_graph_new(tcx, e)); + }); + + dirty_clean::check_dirty_clean_annotations(tcx); dirty_clean::check_dirty_clean_metadata(tcx, - &*prev_metadata_hashes, + &prev_metadata_hashes, ¤t_metadata_hashes); } @@ -166,6 +182,19 @@ fn save_in<F>(sess: &Session, path_buf: PathBuf, encode: F) } } +fn encode_dep_graph_new(tcx: TyCtxt, + encoder: &mut Encoder) + -> io::Result<()> { + // First encode the commandline arguments hash + tcx.sess.opts.dep_tracking_hash().encode(encoder)?; + + // Encode the graph data. + let serialized_graph = tcx.dep_graph.serialize(); + serialized_graph.encode(encoder)?; + + Ok(()) +} + pub fn encode_dep_graph(tcx: TyCtxt, preds: &Predecessors, encoder: &mut Encoder) diff --git a/src/librustc_lint/bad_style.rs b/src/librustc_lint/bad_style.rs index d4b8f0a4924..cbc012a65fa 100644 --- a/src/librustc_lint/bad_style.rs +++ b/src/librustc_lint/bad_style.rs @@ -278,7 +278,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase { fn check_lifetime_def(&mut self, cx: &LateContext, t: &hir::LifetimeDef) { self.check_snake_case(cx, "lifetime", - &t.lifetime.name.as_str(), + &t.lifetime.name.name().as_str(), Some(t.lifetime.span)); } diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 439cc3a4b84..b97920dd18b 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -153,6 +153,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { }; let mut fn_warned = false; + let mut op_warned = false; if cx.tcx.sess.features.borrow().fn_must_use { let maybe_def = match expr.node { hir::ExprCall(ref callee, _) => { @@ -172,9 +173,24 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { let def_id = def.def_id(); fn_warned = check_must_use(cx, def_id, s.span, "return value of "); } + + if let hir::ExprBinary(bin_op, ..) = expr.node { + match bin_op.node { + // Hardcoding the comparison operators here seemed more + // expedient than the refactoring that would be needed to + // look up the `#[must_use]` attribute which does exist on + // the comparison trait methods + hir::BiEq | hir::BiLt | hir::BiLe | hir::BiNe | hir::BiGe | hir::BiGt => { + let msg = "unused comparison which must be used"; + cx.span_lint(UNUSED_MUST_USE, expr.span, msg); + op_warned = true; + }, + _ => {}, + } + } } - if !(ty_warned || fn_warned) { + if !(ty_warned || fn_warned || op_warned) { cx.span_lint(UNUSED_RESULTS, s.span, "unused result"); } diff --git a/src/librustc_llvm/Cargo.toml b/src/librustc_llvm/Cargo.toml index 1ed2cbab65f..de5add56b76 100644 --- a/src/librustc_llvm/Cargo.toml +++ b/src/librustc_llvm/Cargo.toml @@ -18,4 +18,4 @@ rustc_cratesio_shim = { path = "../librustc_cratesio_shim" } [build-dependencies] build_helper = { path = "../build_helper" } -gcc = "0.3.50" +cc = "1.0" diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index 393aa7fa43b..dde7a38efc7 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern crate gcc; +extern crate cc; extern crate build_helper; use std::process::Command; @@ -136,7 +136,7 @@ fn main() { let mut cmd = Command::new(&llvm_config); cmd.arg("--cxxflags"); let cxxflags = output(&mut cmd); - let mut cfg = gcc::Build::new(); + let mut cfg = cc::Build::new(); cfg.warnings(false); for flag in cxxflags.split_whitespace() { // Ignore flags like `-m64` when we're doing a cross build diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index f785d7bd407..8eacc21ab00 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -55,9 +55,14 @@ macro_rules! provide { let ($def_id, $other) = def_id_arg.into_args(); assert!(!$def_id.is_local()); - let def_path_hash = $tcx.def_path_hash($def_id); - let dep_node = def_path_hash.to_dep_node(::rustc::dep_graph::DepKind::MetaData); - + let def_path_hash = $tcx.def_path_hash(DefId { + krate: $def_id.krate, + index: CRATE_DEF_INDEX + }); + let dep_node = def_path_hash + .to_dep_node(::rustc::dep_graph::DepKind::CrateMetadata); + // The DepNodeIndex of the DepNode::CrateMetadata should be + // cached somewhere, so that we can use read_index(). $tcx.dep_graph.read(dep_node); let $cdata = $tcx.crate_data_as_rc_any($def_id.krate); @@ -379,6 +384,16 @@ impl CrateStore for cstore::CStore { self.get_crate_data(cnum).name } + fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> Symbol + { + self.get_crate_data(cnum).disambiguator() + } + + fn crate_hash_untracked(&self, cnum: CrateNum) -> hir::svh::Svh + { + self.get_crate_data(cnum).hash() + } + /// Returns the `DefKey` for a given `DefId`. This indicates the /// parent `DefId` as well as some idea of what kind of data the /// `DefId` refers to. diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs index 063cbc77559..902e2de841f 100644 --- a/src/librustc_mir/borrow_check.rs +++ b/src/librustc_mir/borrow_check.rs @@ -173,14 +173,23 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> DataflowResultsConsumer<'b, 'gcx> let span = stmt.source_info.span; match stmt.kind { StatementKind::Assign(ref lhs, ref rhs) => { + // NOTE: NLL RFC calls for *shallow* write; using Deep + // for short-term compat w/ AST-borrowck. Also, switch + // to shallow requires to dataflow: "if this is an + // assignment `lv = <rvalue>`, then any loan for some + // path P of which `lv` is a prefix is killed." self.mutate_lvalue(ContextKind::AssignLhs.new(location), - (lhs, span), JustWrite, flow_state); + (lhs, span), Deep, JustWrite, flow_state); + self.consume_rvalue(ContextKind::AssignRhs.new(location), (rhs, span), location, flow_state); } StatementKind::SetDiscriminant { ref lvalue, variant_index: _ } => { self.mutate_lvalue(ContextKind::SetDiscrim.new(location), - (lvalue, span), JustWrite, flow_state); + (lvalue, span), + Shallow(Some(ArtificialField::Discriminant)), + JustWrite, + flow_state); } StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => { for (o, output) in asm.outputs.iter().zip(outputs) { @@ -192,6 +201,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> DataflowResultsConsumer<'b, 'gcx> } else { self.mutate_lvalue(ContextKind::InlineAsm.new(location), (output, span), + Deep, if o.is_rw { WriteAndRead } else { JustWrite }, flow_state); } @@ -209,15 +219,15 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> DataflowResultsConsumer<'b, 'gcx> StatementKind::Nop | StatementKind::Validate(..) | StatementKind::StorageLive(..) => { - // ignored by borrowck + // `Nop`, `Validate`, and `StorageLive` are irrelevant + // to borrow check. } StatementKind::StorageDead(local) => { - // causes non-drop values to be dropped. - self.consume_lvalue(ContextKind::StorageDead.new(location), - ConsumeKind::Consume, - (&Lvalue::Local(local), span), - flow_state) + self.access_lvalue(ContextKind::StorageDead.new(location), + (&Lvalue::Local(local), span), + (Shallow(None), Write(WriteKind::StorageDead)), + flow_state); } } } @@ -246,7 +256,10 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> DataflowResultsConsumer<'b, 'gcx> target: _, unwind: _ } => { self.mutate_lvalue(ContextKind::DropAndReplace.new(loc), - (drop_lvalue, span), JustWrite, flow_state); + (drop_lvalue, span), + Deep, + JustWrite, + flow_state); self.consume_operand(ContextKind::DropAndReplace.new(loc), ConsumeKind::Drop, (new_value, span), flow_state); @@ -262,7 +275,10 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> DataflowResultsConsumer<'b, 'gcx> } if let Some((ref dest, _/*bb*/)) = *destination { self.mutate_lvalue(ContextKind::CallDest.new(loc), - (dest, span), JustWrite, flow_state); + (dest, span), + Deep, + JustWrite, + flow_state); } } TerminatorKind::Assert { ref cond, expected: _, ref msg, target: _, cleanup: _ } => { @@ -309,29 +325,121 @@ enum ConsumeKind { Drop, Consume } #[derive(Copy, Clone, PartialEq, Eq, Debug)] enum Control { Continue, Break } +use self::ShallowOrDeep::{Shallow, Deep}; +use self::ReadOrWrite::{Read, Write}; + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +enum ArtificialField { + Discriminant, + ArrayLength, +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +enum ShallowOrDeep { + /// From the RFC: "A *shallow* access means that the immediate + /// fields reached at LV are accessed, but references or pointers + /// found within are not dereferenced. Right now, the only access + /// that is shallow is an assignment like `x = ...;`, which would + /// be a *shallow write* of `x`." + Shallow(Option<ArtificialField>), + + /// From the RFC: "A *deep* access means that all data reachable + /// through the given lvalue may be invalidated or accesses by + /// this action." + Deep, +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +enum ReadOrWrite { + /// From the RFC: "A *read* means that the existing data may be + /// read, but will not be changed." + Read(ReadKind), + + /// From the RFC: "A *write* means that the data may be mutated to + /// new values or otherwise invalidated (for example, it could be + /// de-initialized, as in a move operation). + Write(WriteKind), +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +enum ReadKind { + Borrow(BorrowKind), + Copy, +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +enum WriteKind { + StorageDead, + MutableBorrow(BorrowKind), + Mutate, + Move, +} + impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> { + fn access_lvalue(&mut self, + context: Context, + lvalue_span: (&Lvalue<'gcx>, Span), + kind: (ShallowOrDeep, ReadOrWrite), + flow_state: &InProgress<'b, 'gcx>) { + // FIXME: also need to check permissions (e.g. reject mut + // borrow of immutable ref, moves through non-`Box`-ref) + let (sd, rw) = kind; + self.each_borrow_involving_path( + context, (sd, lvalue_span.0), flow_state, |this, _index, borrow| { + match (rw, borrow.kind) { + (Read(_), BorrowKind::Shared) => { + Control::Continue + } + (Read(kind), BorrowKind::Unique) | + (Read(kind), BorrowKind::Mut) => { + match kind { + ReadKind::Copy => + this.report_use_while_mutably_borrowed( + context, lvalue_span, borrow), + ReadKind::Borrow(bk) => + this.report_conflicting_borrow( + context, lvalue_span, + (lvalue_span.0, bk), (&borrow.lvalue, borrow.kind)), + } + Control::Break + } + (Write(kind), _) => { + match kind { + WriteKind::MutableBorrow(bk) => + this.report_conflicting_borrow( + context, lvalue_span, + (lvalue_span.0, bk), (&borrow.lvalue, borrow.kind)), + WriteKind::StorageDead | + WriteKind::Mutate => + this.report_illegal_mutation_of_borrowed( + context, lvalue_span, borrow), + WriteKind::Move => + this.report_move_out_while_borrowed( + context, lvalue_span, borrow), + } + Control::Break + } + } + }); + } + fn mutate_lvalue(&mut self, context: Context, lvalue_span: (&Lvalue<'gcx>, Span), + kind: ShallowOrDeep, mode: MutateMode, flow_state: &InProgress<'b, 'gcx>) { // Write of P[i] or *P, or WriteAndRead of any P, requires P init'd. match mode { MutateMode::WriteAndRead => { - self.check_if_path_is_moved(context, lvalue_span, flow_state); + self.check_if_path_is_moved(context, "update", lvalue_span, flow_state); } MutateMode::JustWrite => { self.check_if_assigned_path_is_moved(context, lvalue_span, flow_state); } } - // check we don't invalidate any outstanding loans - self.each_borrow_involving_path(context, - lvalue_span.0, flow_state, |this, _index, _data| { - this.report_illegal_mutation_of_borrowed(context, - lvalue_span); - Control::Break - }); + self.access_lvalue(context, lvalue_span, (kind, Write(WriteKind::Mutate)), flow_state); // check for reassignments to immutable local variables self.check_if_reassignment_to_immutable_state(context, lvalue_span, flow_state); @@ -340,11 +448,17 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> fn consume_rvalue(&mut self, context: Context, (rvalue, span): (&Rvalue<'gcx>, Span), - location: Location, + _location: Location, flow_state: &InProgress<'b, 'gcx>) { match *rvalue { Rvalue::Ref(_/*rgn*/, bk, ref lvalue) => { - self.borrow(context, location, bk, (lvalue, span), flow_state) + let access_kind = match bk { + BorrowKind::Shared => (Deep, Read(ReadKind::Borrow(bk))), + BorrowKind::Unique | + BorrowKind::Mut => (Deep, Write(WriteKind::MutableBorrow(bk))), + }; + self.access_lvalue(context, (lvalue, span), access_kind, flow_state); + self.check_if_path_is_moved(context, "borrow", (lvalue, span), flow_state); } Rvalue::Use(ref operand) | @@ -356,8 +470,14 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> Rvalue::Len(ref lvalue) | Rvalue::Discriminant(ref lvalue) => { - // len(_)/discriminant(_) merely read, not consume. - self.check_if_path_is_moved(context, (lvalue, span), flow_state); + let af = match *rvalue { + Rvalue::Len(..) => ArtificialField::ArrayLength, + Rvalue::Discriminant(..) => ArtificialField::Discriminant, + _ => unreachable!(), + }; + self.access_lvalue( + context, (lvalue, span), (Shallow(Some(af)), Read(ReadKind::Copy)), flow_state); + self.check_if_path_is_moved(context, "use", (lvalue, span), flow_state); } Rvalue::BinaryOp(_bin_op, ref operand1, ref operand2) | @@ -388,8 +508,9 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> (operand, span): (&Operand<'gcx>, Span), flow_state: &InProgress<'b, 'gcx>) { match *operand { - Operand::Consume(ref lvalue) => - self.consume_lvalue(context, consume_via_drop, (lvalue, span), flow_state), + Operand::Consume(ref lvalue) => { + self.consume_lvalue(context, consume_via_drop, (lvalue, span), flow_state) + } Operand::Constant(_) => {} } } @@ -405,26 +526,10 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> self.fake_infer_ctxt.type_moves_by_default(self.param_env, ty, DUMMY_SP); if moves_by_default { // move of lvalue: check if this is move of already borrowed path - self.each_borrow_involving_path( - context, lvalue_span.0, flow_state, |this, _idx, borrow| { - if !borrow.compatible_with(BorrowKind::Mut) { - this.report_move_out_while_borrowed(context, lvalue_span); - Control::Break - } else { - Control::Continue - } - }); + self.access_lvalue(context, lvalue_span, (Deep, Write(WriteKind::Move)), flow_state); } else { // copy of lvalue: check if this is "copy of frozen path" (FIXME: see check_loans.rs) - self.each_borrow_involving_path( - context, lvalue_span.0, flow_state, |this, _idx, borrow| { - if !borrow.compatible_with(BorrowKind::Shared) { - this.report_use_while_mutably_borrowed(context, lvalue_span); - Control::Break - } else { - Control::Continue - } - }); + self.access_lvalue(context, lvalue_span, (Deep, Read(ReadKind::Copy)), flow_state); } // Finally, check if path was already moved. @@ -435,22 +540,10 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> // skip this check in that case). } ConsumeKind::Consume => { - self.check_if_path_is_moved(context, lvalue_span, flow_state); + self.check_if_path_is_moved(context, "use", lvalue_span, flow_state); } } } - - fn borrow(&mut self, - context: Context, - location: Location, - bk: BorrowKind, - lvalue_span: (&Lvalue<'gcx>, Span), - flow_state: &InProgress<'b, 'gcx>) { - debug!("borrow location: {:?} lvalue: {:?} span: {:?}", - location, lvalue_span.0, lvalue_span.1); - self.check_if_path_is_moved(context, lvalue_span, flow_state); - self.check_for_conflicting_loans(context, location, bk, lvalue_span, flow_state); - } } impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> { @@ -487,13 +580,26 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> if flow_state.inits.curr_state.contains(&mpi) { // may already be assigned before reaching this statement; // report error. - self.report_illegal_reassignment(context, (lvalue, span)); + // FIXME: Not ideal, it only finds the assignment that lexically comes first + let assigned_lvalue = &move_data.move_paths[mpi].lvalue; + let assignment_stmt = self.mir.basic_blocks().iter().filter_map(|bb| { + bb.statements.iter().find(|stmt| { + if let StatementKind::Assign(ref lv, _) = stmt.kind { + *lv == *assigned_lvalue + } else { + false + } + }) + }).next().unwrap(); + self.report_illegal_reassignment( + context, (lvalue, span), assignment_stmt.source_info.span); } } } fn check_if_path_is_moved(&mut self, context: Context, + desired_action: &str, lvalue_span: (&Lvalue<'gcx>, Span), flow_state: &InProgress<'b, 'gcx>) { // FIXME: analogous code in check_loans first maps `lvalue` to @@ -505,7 +611,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> if let Some(mpi) = self.move_path_for_lvalue(context, move_data, lvalue) { if maybe_uninits.curr_state.contains(&mpi) { // find and report move(s) that could cause this to be uninitialized - self.report_use_of_moved(context, lvalue_span); + self.report_use_of_moved(context, desired_action, lvalue_span); } else { // sanity check: initialized on *some* path, right? assert!(flow_state.inits.curr_state.contains(&mpi)); @@ -572,8 +678,8 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> // check_loans.rs first maps // `base` to its base_path. - self.check_if_path_is_moved(context, - (base, span), flow_state); + self.check_if_path_is_moved( + context, "assignment", (base, span), flow_state); // (base initialized; no need to // recur further) @@ -590,72 +696,18 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> } } } - - fn check_for_conflicting_loans(&mut self, - context: Context, - _location: Location, - _bk: BorrowKind, - lvalue_span: (&Lvalue<'gcx>, Span), - flow_state: &InProgress<'b, 'gcx>) { - // NOTE FIXME: The analogous code in old borrowck - // check_loans.rs is careful to iterate over every *issued* - // loan, as opposed to just the in scope ones. - // - // (Or if you prefer, all the *other* iterations over loans - // only consider loans that are in scope of some given - // region::Scope) - // - // The (currently skeletal) code here does not encode such a - // distinction, which means it is almost certainly over - // looking something. - // - // (It is probably going to reject code that should be - // accepted, I suspect, by treated issued-but-out-of-scope - // loans as issued-and-in-scope, and thus causing them to - // interfere with other loans.) - // - // However, I just want to get something running, especially - // since I am trying to move into new territory with NLL, so - // lets get this going first, and then address the issued vs - // in-scope distinction later. - - let state = &flow_state.borrows; - let data = &state.base_results.operator().borrows(); - - debug!("check_for_conflicting_loans location: {:?}", _location); - - // does any loan generated here conflict with a previously issued loan? - let mut loans_generated = 0; - for (g, gen) in state.elems_generated().map(|g| (g, &data[g])) { - loans_generated += 1; - for (i, issued) in state.elems_incoming().map(|i| (i, &data[i])) { - debug!("check_for_conflicting_loans gen: {:?} issued: {:?} conflicts: {}", - (g, gen, self.base_path(&gen.lvalue), - self.restrictions(&gen.lvalue).collect::<Vec<_>>()), - (i, issued, self.base_path(&issued.lvalue), - self.restrictions(&issued.lvalue).collect::<Vec<_>>()), - self.conflicts_with(gen, issued)); - if self.conflicts_with(gen, issued) { - self.report_conflicting_borrow(context, lvalue_span, gen, issued); - } - } - } - - // MIR statically ensures each statement gens *at most one* - // loan; mutual conflict (within a statement) can't arise. - // - // As safe-guard, assert that above property actually holds. - assert!(loans_generated <= 1); - } } +} impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> { fn each_borrow_involving_path<F>(&mut self, _context: Context, - lvalue: &Lvalue<'gcx>, + access_lvalue: (ShallowOrDeep, &Lvalue<'gcx>), flow_state: &InProgress<'b, 'gcx>, mut op: F) where F: FnMut(&mut Self, BorrowIndex, &BorrowData<'gcx>) -> Control { + let (access, lvalue) = access_lvalue; + // FIXME: analogous code in check_loans first maps `lvalue` to // its base_path. @@ -664,228 +716,182 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> // check for loan restricting path P being used. Accounts for // borrows of P, P.a.b, etc. - for i in flow_state.borrows.elems_incoming() { - // FIXME: check_loans.rs filtered this to "in scope" - // loans; i.e. it took a scope S and checked that each - // restriction's kill_scope was a superscope of S. + 'next_borrow: for i in flow_state.borrows.elems_incoming() { let borrowed = &data[i]; - for restricted in self.restrictions(&borrowed.lvalue) { - if restricted == lvalue { + + // Is `lvalue` (or a prefix of it) already borrowed? If + // so, that's relevant. + // + // FIXME: Differs from AST-borrowck; includes drive-by fix + // to #38899. Will probably need back-compat mode flag. + for accessed_prefix in self.prefixes(lvalue, PrefixSet::All) { + if *accessed_prefix == borrowed.lvalue { + // FIXME: pass in prefix here too? And/or enum + // describing case we are in? let ctrl = op(self, i, borrowed); if ctrl == Control::Break { return; } } } - } - // check for loans (not restrictions) on any base path. - // e.g. Rejects `{ let x = &mut a.b; let y = a.b.c; }`, - // since that moves out of borrowed path `a.b`. - // - // Limiting to loans (not restrictions) keeps this one - // working: `{ let x = &mut a.b; let y = a.c; }` - let mut cursor = lvalue; - loop { - // FIXME: check_loans.rs invoked `op` *before* cursor - // shift here. Might just work (and even avoid redundant - // errors?) given code above? But for now, I want to try - // doing what I think is more "natural" check. - for i in flow_state.borrows.elems_incoming() { - let borrowed = &data[i]; - if borrowed.lvalue == *cursor { + // Is `lvalue` a prefix (modulo access type) of the + // `borrowed.lvalue`? If so, that's relevant. + + let prefix_kind = match access { + Shallow(Some(ArtificialField::Discriminant)) | + Shallow(Some(ArtificialField::ArrayLength)) => { + // 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 lvalue (at least in MIR as it is + // currently.) + continue 'next_borrow; + } + Shallow(None) => PrefixSet::Shallow, + Deep => PrefixSet::Supporting, + }; + + for borrowed_prefix in self.prefixes(&borrowed.lvalue, prefix_kind) { + if borrowed_prefix == lvalue { + // FIXME: pass in prefix here too? And/or enum + // describing case we are in? let ctrl = op(self, i, borrowed); if ctrl == Control::Break { return; } } } - - match *cursor { - Lvalue::Local(_) | Lvalue::Static(_) => break, - Lvalue::Projection(ref proj) => cursor = &proj.base, - } } } } -mod restrictions { - use super::MirBorrowckCtxt; +use self::prefixes::PrefixSet; + +/// From the NLL RFC: "The deep [aka 'supporting'] prefixes for an +/// lvalue are formed by stripping away fields and derefs, except that +/// we stop when we reach the deref of a shared reference. [...] " +/// +/// "Shallow prefixes are found by stripping away fields, but stop at +/// any dereference. So: writing a path like `a` is illegal if `a.b` +/// is borrowed. But: writing `a` is legal if `*a` is borrowed, +/// whether or not `a` is a shared or mutable reference. [...] " +mod prefixes { + use super::{MirBorrowckCtxt}; use rustc::hir; use rustc::ty::{self, TyCtxt}; use rustc::mir::{Lvalue, Mir, ProjectionElem}; - pub(super) struct Restrictions<'c, 'tcx: 'c> { + pub(super) struct Prefixes<'c, 'tcx: 'c> { mir: &'c Mir<'tcx>, tcx: TyCtxt<'c, 'tcx, 'tcx>, - lvalue_stack: Vec<&'c Lvalue<'tcx>>, + kind: PrefixSet, + next: Option<&'c Lvalue<'tcx>>, + } + + #[derive(Copy, Clone, PartialEq, Eq, Debug)] + pub(super) enum PrefixSet { + All, + Shallow, + Supporting, } impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> { - pub(super) fn restrictions<'d>(&self, - lvalue: &'d Lvalue<'gcx>) - -> Restrictions<'d, 'gcx> where 'b: 'd + pub(super) fn prefixes<'d>(&self, + lvalue: &'d Lvalue<'gcx>, + kind: PrefixSet) + -> Prefixes<'d, 'gcx> where 'b: 'd { - let lvalue_stack = if self.has_restrictions(lvalue) { vec![lvalue] } else { vec![] }; - Restrictions { lvalue_stack: lvalue_stack, mir: self.mir, tcx: self.tcx } + Prefixes { next: Some(lvalue), kind, mir: self.mir, tcx: self.tcx } } + } + + impl<'c, 'tcx> Iterator for Prefixes<'c, 'tcx> { + type Item = &'c Lvalue<'tcx>; + fn next(&mut self) -> Option<Self::Item> { + let mut cursor = match self.next { + None => return None, + Some(lvalue) => lvalue, + }; - fn has_restrictions(&self, lvalue: &Lvalue<'gcx>) -> bool { - let mut cursor = lvalue; - loop { + // Post-processing `lvalue`: Enqueue any remaining + // work. Also, `lvalue` may not be a prefix itself, but + // may hold one further down (e.g. we never return + // downcasts here, but may return a base of a downcast). + + 'cursor: loop { let proj = match *cursor { - Lvalue::Local(_) => return true, - Lvalue::Static(_) => return false, + Lvalue::Local(_) | // search yielded this leaf + Lvalue::Static(_) => { + self.next = None; + return Some(cursor); + } + Lvalue::Projection(ref proj) => proj, }; + match proj.elem { - ProjectionElem::Index(..) | - ProjectionElem::ConstantIndex { .. } | + ProjectionElem::Field(_/*field*/, _/*ty*/) => { + // FIXME: add union handling + self.next = Some(&proj.base); + return Some(cursor); + } ProjectionElem::Downcast(..) | ProjectionElem::Subslice { .. } | - ProjectionElem::Field(_/*field*/, _/*ty*/) => { + ProjectionElem::ConstantIndex { .. } | + ProjectionElem::Index(_) => { cursor = &proj.base; - continue; + continue 'cursor; } ProjectionElem::Deref => { - let ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx); - match ty.sty { - ty::TyRawPtr(_) => { - return false; - } - ty::TyRef(_, ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => { - // FIXME: do I need to check validity of - // region here though? (I think the original - // check_loans code did, like readme says) - return false; - } - ty::TyRef(_, ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => { - cursor = &proj.base; - continue; - } - ty::TyAdt(..) if ty.is_box() => { - cursor = &proj.base; - continue; - } - _ => { - panic!("unknown type fed to Projection Deref."); - } - } + // (handled below) } } - } - } - } - impl<'c, 'tcx> Iterator for Restrictions<'c, 'tcx> { - type Item = &'c Lvalue<'tcx>; - fn next(&mut self) -> Option<Self::Item> { - 'pop: loop { - let lvalue = match self.lvalue_stack.pop() { - None => return None, - Some(lvalue) => lvalue, - }; + assert_eq!(proj.elem, ProjectionElem::Deref); - // `lvalue` may not be a restriction itself, but may - // hold one further down (e.g. we never return - // downcasts here, but may return a base of a - // downcast). - // - // Also, we need to enqueue any additional - // subrestrictions that it implies, since we can only - // return from from this call alone. - - let mut cursor = lvalue; - 'cursor: loop { - let proj = match *cursor { - Lvalue::Local(_) => return Some(cursor), // search yielded this leaf - Lvalue::Static(_) => continue 'pop, // fruitless leaf; try next on stack - Lvalue::Projection(ref proj) => proj, - }; - - match proj.elem { - ProjectionElem::Field(_/*field*/, _/*ty*/) => { - // FIXME: add union handling - self.lvalue_stack.push(&proj.base); - return Some(cursor); - } - ProjectionElem::Downcast(..) | - ProjectionElem::Subslice { .. } | - ProjectionElem::ConstantIndex { .. } | - ProjectionElem::Index(_) => { - cursor = &proj.base; - continue 'cursor; - } - ProjectionElem::Deref => { - // (handled below) - } + match self.kind { + PrefixSet::Shallow => { + // shallow prefixes are found by stripping away + // fields, but stop at *any* dereference. + // So we can just stop the traversal now. + self.next = None; + return Some(cursor); } + PrefixSet::All => { + // all prefixes: just blindly enqueue the base + // of the projection + self.next = Some(&proj.base); + return Some(cursor); + } + PrefixSet::Supporting => { + // fall through! + } + } - assert_eq!(proj.elem, ProjectionElem::Deref); - - let ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx); - match ty.sty { - ty::TyRawPtr(_) => { - // borrowck ignores raw ptrs; treat analogous to imm borrow - continue 'pop; - } - // R-Deref-Imm-Borrowed - ty::TyRef(_/*rgn*/, ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => { - // immutably-borrowed referents do not - // have recursively-implied restrictions - // (because preventing actions on `*LV` - // does nothing about aliases like `*LV1`) - - // FIXME: do I need to check validity of - // `_r` here though? (I think the original - // check_loans code did, like the readme - // says) - - // (And do I *really* not have to - // recursively process the `base` as a - // further search here? Leaving this `if - // false` here as a hint to look at this - // again later. - // - // Ah, it might be because the - // restrictions are distinct from the path - // substructure. Note that there is a - // separate loop over the path - // substructure in fn - // each_borrow_involving_path, for better - // or for worse. - - if false { - cursor = &proj.base; - continue 'cursor; - } else { - continue 'pop; - } - } - - // R-Deref-Mut-Borrowed - ty::TyRef(_/*rgn*/, ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => { - // mutably-borrowed referents are - // themselves restricted. - - // FIXME: do I need to check validity of - // `_r` here though? (I think the original - // check_loans code did, like the readme - // says) - - // schedule base for future iteration. - self.lvalue_stack.push(&proj.base); - return Some(cursor); // search yielded interior node - } + assert_eq!(self.kind, PrefixSet::Supporting); + // supporting prefixes: strip away fields and + // derefs, except we stop at the deref of a shared + // reference. + + let ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx); + match ty.sty { + ty::TyRawPtr(_) | + ty::TyRef(_/*rgn*/, ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => { + // don't continue traversing over derefs of raw pointers or shared borrows. + self.next = None; + return Some(cursor); + } - // R-Deref-Send-Pointer - ty::TyAdt(..) if ty.is_box() => { - // borrowing interior of a box implies that - // its base can no longer be mutated (o/w box - // storage would be freed) - self.lvalue_stack.push(&proj.base); - return Some(cursor); // search yielded interior node - } + ty::TyRef(_/*rgn*/, ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => { + self.next = Some(&proj.base); + return Some(cursor); + } - _ => panic!("unknown type fed to Projection Deref."), + ty::TyAdt(..) if ty.is_box() => { + self.next = Some(&proj.base); + return Some(cursor); } + + _ => panic!("unknown type fed to Projection Deref."), } } } @@ -895,71 +901,119 @@ mod restrictions { impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> { fn report_use_of_moved(&mut self, _context: Context, + desired_action: &str, (lvalue, span): (&Lvalue, Span)) { - let mut err = self.tcx.cannot_act_on_uninitialized_variable( - span, "use", &self.describe_lvalue(lvalue), Origin::Mir); - // FIXME: add span_label for use of uninitialized variable - err.emit(); + self.tcx.cannot_act_on_uninitialized_variable(span, + desired_action, + &self.describe_lvalue(lvalue), + Origin::Mir) + .span_label(span, format!("use of possibly uninitialized `{}`", + self.describe_lvalue(lvalue))) + .emit(); } fn report_move_out_while_borrowed(&mut self, _context: Context, - (lvalue, span): (&Lvalue, Span)) { - let mut err = self.tcx.cannot_move_when_borrowed( - span, &self.describe_lvalue(lvalue), Origin::Mir); - // FIXME 1: add span_label for "borrow of `()` occurs here" - // FIXME 2: add span_label for "move out of `{}` occurs here" - err.emit(); + (lvalue, span): (&Lvalue, Span), + borrow: &BorrowData) { + self.tcx.cannot_move_when_borrowed(span, + &self.describe_lvalue(lvalue), + Origin::Mir) + .span_label(self.retrieve_borrow_span(borrow), + format!("borrow of `{}` occurs here", + self.describe_lvalue(&borrow.lvalue))) + .span_label(span, format!("move out of `{}` occurs here", + self.describe_lvalue(lvalue))) + .emit(); } fn report_use_while_mutably_borrowed(&mut self, _context: Context, - (lvalue, span): (&Lvalue, Span)) { + (lvalue, span): (&Lvalue, Span), + borrow : &BorrowData) { + let described_lvalue = self.describe_lvalue(lvalue); + let borrow_span = self.retrieve_borrow_span(borrow); + let mut err = self.tcx.cannot_use_when_mutably_borrowed( - span, &self.describe_lvalue(lvalue), Origin::Mir); - // FIXME 1: add span_label for "borrow of `()` occurs here" - // FIXME 2: add span_label for "use of `{}` occurs here" + span, &described_lvalue, Origin::Mir); + + err.span_label(borrow_span, format!("borrow of `{}` occurs here", described_lvalue)); + err.span_label(span, format!("use of borrowed `{}`", described_lvalue)); + err.emit(); } fn report_conflicting_borrow(&mut self, _context: Context, (lvalue, span): (&Lvalue, Span), - loan1: &BorrowData, - loan2: &BorrowData) { + loan1: (&Lvalue, BorrowKind), + loan2: (&Lvalue, BorrowKind)) { + let (loan1_lvalue, loan1_kind) = loan1; + let (loan2_lvalue, loan2_kind) = loan2; // FIXME: obviously falsifiable. Generalize for non-eq lvalues later. - assert_eq!(loan1.lvalue, loan2.lvalue); + assert_eq!(loan1_lvalue, loan2_lvalue); // FIXME: supply non-"" `opt_via` when appropriate - let mut err = match (loan1.kind, "immutable", "mutable", - loan2.kind, "immutable", "mutable") { + let mut err = match (loan1_kind, "immutable", "mutable", + loan2_kind, "immutable", "mutable") { (BorrowKind::Shared, lft, _, BorrowKind::Mut, _, rgt) | - (BorrowKind::Mut, _, lft, BorrowKind::Shared, rgt, _) | - (BorrowKind::Mut, _, lft, BorrowKind::Mut, _, rgt) => + (BorrowKind::Mut, _, lft, BorrowKind::Shared, rgt, _) => self.tcx.cannot_reborrow_already_borrowed( span, &self.describe_lvalue(lvalue), "", lft, "it", rgt, "", Origin::Mir), - _ => self.tcx.cannot_mutably_borrow_multiply( - span, &self.describe_lvalue(lvalue), "", Origin::Mir), + (BorrowKind::Mut, _, _, BorrowKind::Mut, _, _) => + self.tcx.cannot_mutably_borrow_multiply( + span, &self.describe_lvalue(lvalue), "", Origin::Mir), + + (BorrowKind::Unique, _, _, BorrowKind::Unique, _, _) => + self.tcx.cannot_uniquely_borrow_by_two_closures( + span, &self.describe_lvalue(lvalue), Origin::Mir), + + (BorrowKind::Unique, _, _, _, _, _) => + self.tcx.cannot_uniquely_borrow_by_one_closure( + span, &self.describe_lvalue(lvalue), "it", "", Origin::Mir), + + (_, _, _, BorrowKind::Unique, _, _) => + self.tcx.cannot_reborrow_already_uniquely_borrowed( + span, &self.describe_lvalue(lvalue), "it", "", Origin::Mir), + + (BorrowKind::Shared, _, _, BorrowKind::Shared, _, _) => + unreachable!(), + // FIXME: add span labels for first and second mutable borrows, as well as // end point for first. }; err.emit(); } - fn report_illegal_mutation_of_borrowed(&mut self, _: Context, (lvalue, span): (&Lvalue, Span)) { + fn report_illegal_mutation_of_borrowed(&mut self, + _: Context, + (lvalue, span): (&Lvalue, Span), + loan: &BorrowData) { + let describe_lvalue = self.describe_lvalue(lvalue); + let borrow_span = self.retrieve_borrow_span(loan); + let mut err = self.tcx.cannot_assign_to_borrowed( span, &self.describe_lvalue(lvalue), Origin::Mir); - // FIXME: add span labels for borrow and assignment points + + err.span_label(borrow_span, format!("borrow of `{}` occurs here", describe_lvalue)); + err.span_label(span, format!("assignment to borrowed `{}` occurs here", describe_lvalue)); + err.emit(); } - fn report_illegal_reassignment(&mut self, _context: Context, (lvalue, span): (&Lvalue, Span)) { - let mut err = self.tcx.cannot_reassign_immutable( - span, &self.describe_lvalue(lvalue), Origin::Mir); - // FIXME: add span labels for borrow and assignment points - err.emit(); + fn report_illegal_reassignment(&mut self, + _context: Context, + (lvalue, span): (&Lvalue, Span), + assigned_span: Span) { + self.tcx.cannot_reassign_immutable(span, + &self.describe_lvalue(lvalue), + Origin::Mir) + .span_label(span, "re-assignment of immutable variable") + .span_label(assigned_span, format!("first assignment to `{}`", + self.describe_lvalue(lvalue))) + .emit(); } fn report_assignment_to_static(&mut self, _context: Context, (lvalue, span): (&Lvalue, Span)) { @@ -998,7 +1052,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> ProjectionElem::Downcast(..) => ("", format!(""), None), // (dont emit downcast info) ProjectionElem::Field(field, _ty) => - ("", format!(".{}", field.index()), None), + ("", format!(".{}", field.index()), None), // FIXME: report name of field ProjectionElem::Index(index) => ("", format!(""), Some(index)), ProjectionElem::ConstantIndex { offset, min_length, from_end: true } => @@ -1024,28 +1078,16 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> } } } -} -impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> { - // FIXME: needs to be able to express errors analogous to check_loans.rs - fn conflicts_with(&self, loan1: &BorrowData<'gcx>, loan2: &BorrowData<'gcx>) -> bool { - if loan1.compatible_with(loan2.kind) { return false; } - - let loan2_base_path = self.base_path(&loan2.lvalue); - for restricted in self.restrictions(&loan1.lvalue) { - if restricted != loan2_base_path { continue; } - return true; - } - - let loan1_base_path = self.base_path(&loan1.lvalue); - for restricted in self.restrictions(&loan2.lvalue) { - if restricted != loan1_base_path { continue; } - return true; - } - - return false; + // Retrieve span of given borrow from the current MIR representation + fn retrieve_borrow_span(&self, borrow: &BorrowData) -> Span { + self.mir.basic_blocks()[borrow.location.block] + .statements[borrow.location.statement_index] + .source_info.span } +} +impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> { // FIXME (#16118): function intended to allow the borrow checker // to be less precise in its handling of Box while still allowing // moves out of a Box. They should be removed when/if we stop @@ -1092,8 +1134,8 @@ enum ContextKind { CallOperand, CallDest, Assert, - StorageDead, Yield, + StorageDead, } impl ContextKind { @@ -1225,26 +1267,8 @@ impl<BD> FlowInProgress<BD> where BD: BitDenotation { self.curr_state.subtract(&self.stmt_kill); } - fn elems_generated(&self) -> indexed_set::Elems<BD::Idx> { - let univ = self.base_results.sets().bits_per_block(); - self.stmt_gen.elems(univ) - } - fn elems_incoming(&self) -> indexed_set::Elems<BD::Idx> { let univ = self.base_results.sets().bits_per_block(); self.curr_state.elems(univ) } } - -impl<'tcx> BorrowData<'tcx> { - fn compatible_with(&self, bk: BorrowKind) -> bool { - match (self.kind, bk) { - (BorrowKind::Shared, BorrowKind::Shared) => true, - - (BorrowKind::Mut, _) | - (BorrowKind::Unique, _) | - (_, BorrowKind::Mut) | - (_, BorrowKind::Unique) => false, - } - } -} diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs index 0e412fb27ca..1fc96dbf451 100644 --- a/src/librustc_mir/build/block.rs +++ b/src/librustc_mir/build/block.rs @@ -21,22 +21,32 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ast_block: &'tcx hir::Block, source_info: SourceInfo) -> BlockAnd<()> { - let Block { region_scope, opt_destruction_scope, span, stmts, expr, targeted_by_break } = + let Block { + region_scope, + opt_destruction_scope, + span, + stmts, + expr, + targeted_by_break, + safety_mode + } = self.hir.mirror(ast_block); self.in_opt_scope(opt_destruction_scope.map(|de|(de, source_info)), block, move |this| { - this.in_scope((region_scope, source_info), block, move |this| { + this.in_scope((region_scope, source_info), LintLevel::Inherited, block, move |this| { if targeted_by_break { // This is a `break`-able block (currently only `catch { ... }`) let exit_block = this.cfg.start_new_block(); let block_exit = this.in_breakable_scope( None, exit_block, destination.clone(), |this| { - this.ast_block_stmts(destination, block, span, stmts, expr) + this.ast_block_stmts(destination, block, span, stmts, expr, + safety_mode) }); this.cfg.terminate(unpack!(block_exit), source_info, TerminatorKind::Goto { target: exit_block }); exit_block.unit() } else { - this.ast_block_stmts(destination, block, span, stmts, expr) + this.ast_block_stmts(destination, block, span, stmts, expr, + safety_mode) } }) }) @@ -47,7 +57,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { mut block: BasicBlock, span: Span, stmts: Vec<StmtRef<'tcx>>, - expr: Option<ExprRef<'tcx>>) + expr: Option<ExprRef<'tcx>>, + safety_mode: BlockSafety) -> BlockAnd<()> { let this = self; @@ -69,6 +80,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // First we build all the statements in the block. let mut let_scope_stack = Vec::with_capacity(8); let outer_visibility_scope = this.visibility_scope; + let outer_push_unsafe_count = this.push_unsafe_count; + let outer_unpushed_unsafe = this.unpushed_unsafe; + this.update_visibility_scope_for_safety_mode(span, safety_mode); + let source_info = this.source_info(span); for stmt in stmts { let Stmt { kind, opt_destruction_scope } = this.hir.mirror(stmt); @@ -76,13 +91,20 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { StmtKind::Expr { scope, expr } => { unpack!(block = this.in_opt_scope( opt_destruction_scope.map(|de|(de, source_info)), block, |this| { - this.in_scope((scope, source_info), block, |this| { + let si = (scope, source_info); + this.in_scope(si, LintLevel::Inherited, block, |this| { let expr = this.hir.mirror(expr); this.stmt_expr(block, expr) }) })); } - StmtKind::Let { remainder_scope, init_scope, pattern, initializer } => { + StmtKind::Let { + remainder_scope, + init_scope, + pattern, + initializer, + lint_level + } => { // Enter the remainder scope, i.e. the bindings' destruction scope. this.push_scope((remainder_scope, source_info)); let_scope_stack.push(remainder_scope); @@ -90,13 +112,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // Declare the bindings, which may create a visibility scope. let remainder_span = remainder_scope.span(this.hir.tcx(), &this.hir.region_scope_tree); - let scope = this.declare_bindings(None, remainder_span, &pattern); + let scope = this.declare_bindings(None, remainder_span, lint_level, &pattern); // Evaluate the initializer, if present. if let Some(init) = initializer { unpack!(block = this.in_opt_scope( opt_destruction_scope.map(|de|(de, source_info)), block, move |this| { - this.in_scope((init_scope, source_info), block, move |this| { + let scope = (init_scope, source_info); + this.in_scope(scope, lint_level, block, move |this| { // FIXME #30046 ^~~~ this.expr_into_pattern(block, pattern, init) }) @@ -129,6 +152,48 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } // Restore the original visibility scope. this.visibility_scope = outer_visibility_scope; + this.push_unsafe_count = outer_push_unsafe_count; + this.unpushed_unsafe = outer_unpushed_unsafe; block.unit() } + + /// If we are changing the safety mode, create a new visibility scope + fn update_visibility_scope_for_safety_mode(&mut self, + span: Span, + safety_mode: BlockSafety) + { + debug!("update_visibility_scope_for({:?}, {:?})", span, safety_mode); + let new_unsafety = match safety_mode { + BlockSafety::Safe => None, + BlockSafety::ExplicitUnsafe(node_id) => { + assert_eq!(self.push_unsafe_count, 0); + match self.unpushed_unsafe { + Safety::Safe => {} + _ => return + } + self.unpushed_unsafe = Safety::ExplicitUnsafe(node_id); + Some(Safety::ExplicitUnsafe(node_id)) + } + BlockSafety::PushUnsafe => { + self.push_unsafe_count += 1; + Some(Safety::BuiltinUnsafe) + } + BlockSafety::PopUnsafe => { + self.push_unsafe_count = + self.push_unsafe_count.checked_sub(1).unwrap_or_else(|| { + span_bug!(span, "unsafe count underflow") + }); + if self.push_unsafe_count == 0 { + Some(self.unpushed_unsafe) + } else { + None + } + } + }; + + if let Some(unsafety) = new_unsafety { + self.visibility_scope = self.new_visibility_scope( + span, LintLevel::Inherited, Some(unsafety)); + } + } } diff --git a/src/librustc_mir/build/expr/as_constant.rs b/src/librustc_mir/build/expr/as_constant.rs index a86b7f4d239..a57f1b95494 100644 --- a/src/librustc_mir/build/expr/as_constant.rs +++ b/src/librustc_mir/build/expr/as_constant.rs @@ -29,7 +29,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let Expr { ty, temp_lifetime: _, span, kind } = expr; match kind { - ExprKind::Scope { region_scope: _, value } => + ExprKind::Scope { region_scope: _, lint_level: _, value } => this.as_constant(value), ExprKind::Literal { literal } => Constant { span: span, ty: ty, literal: literal }, diff --git a/src/librustc_mir/build/expr/as_lvalue.rs b/src/librustc_mir/build/expr/as_lvalue.rs index 9cbaff2c113..69d0dd99228 100644 --- a/src/librustc_mir/build/expr/as_lvalue.rs +++ b/src/librustc_mir/build/expr/as_lvalue.rs @@ -39,8 +39,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let expr_span = expr.span; let source_info = this.source_info(expr_span); match expr.kind { - ExprKind::Scope { region_scope, value } => { - this.in_scope((region_scope, source_info), block, |this| { + ExprKind::Scope { region_scope, lint_level, value } => { + this.in_scope((region_scope, source_info), lint_level, block, |this| { this.as_lvalue(block, value) }) } diff --git a/src/librustc_mir/build/expr/as_operand.rs b/src/librustc_mir/build/expr/as_operand.rs index 0a72ce8d05e..ea6e4342098 100644 --- a/src/librustc_mir/build/expr/as_operand.rs +++ b/src/librustc_mir/build/expr/as_operand.rs @@ -55,10 +55,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { debug!("expr_as_operand(block={:?}, expr={:?})", block, expr); let this = self; - if let ExprKind::Scope { region_scope, value } = expr.kind { + if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind { let source_info = this.source_info(expr.span); let region_scope = (region_scope, source_info); - return this.in_scope(region_scope, block, |this| { + return this.in_scope(region_scope, lint_level, block, |this| { this.as_operand(block, scope, value) }); } diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index f2607b164de..d17f00b489c 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -58,9 +58,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let source_info = this.source_info(expr_span); match expr.kind { - ExprKind::Scope { region_scope, value } => { + ExprKind::Scope { region_scope, lint_level, value } => { let region_scope = (region_scope, source_info); - this.in_scope(region_scope, block, |this| this.as_rvalue(block, scope, value)) + this.in_scope(region_scope, lint_level, block, + |this| this.as_rvalue(block, scope, value)) } ExprKind::Repeat { value, count } => { let value_operand = unpack!(block = this.as_operand(block, scope, value)); diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs index 7826769600b..ba422a81831 100644 --- a/src/librustc_mir/build/expr/as_temp.rs +++ b/src/librustc_mir/build/expr/as_temp.rs @@ -41,8 +41,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let expr_span = expr.span; let source_info = this.source_info(expr_span); - if let ExprKind::Scope { region_scope, value } = expr.kind { - return this.in_scope((region_scope, source_info), block, |this| { + if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind { + return this.in_scope((region_scope, source_info), lint_level, block, |this| { this.as_temp(block, temp_lifetime, value) }); } diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index ec06e474980..cdbcb43370f 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -38,9 +38,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let source_info = this.source_info(expr_span); match expr.kind { - ExprKind::Scope { region_scope, value } => { + ExprKind::Scope { region_scope, lint_level, value } => { let region_scope = (region_scope, source_info); - this.in_scope(region_scope, block, |this| this.into(destination, block, value)) + this.in_scope(region_scope, lint_level, block, + |this| this.into(destination, block, value)) } ExprKind::Block { body: ast_block } => { this.ast_block(destination, block, ast_block, source_info) @@ -227,9 +228,22 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let val = args.next().expect("1 argument to `move_val_init`"); assert!(args.next().is_none(), ">2 arguments to `move_val_init`"); - let topmost_scope = this.topmost_scope(); - let ptr = unpack!(block = this.as_temp(block, Some(topmost_scope), ptr)); - this.into(&Lvalue::Local(ptr).deref(), block, val) + let ptr = this.hir.mirror(ptr); + let ptr_ty = ptr.ty; + // Create an *internal* temp for the pointer, so that unsafety + // checking won't complain about the raw pointer assignment. + let ptr_temp = this.local_decls.push(LocalDecl { + mutability: Mutability::Mut, + ty: ptr_ty, + name: None, + source_info, + lexical_scope: source_info.scope, + internal: true, + is_user_variable: false + }); + let ptr_temp = Lvalue::Local(ptr_temp); + let block = unpack!(this.into(&ptr_temp, block, ptr)); + this.into(&ptr_temp.deref(), block, val) } else { let args: Vec<_> = args.into_iter() diff --git a/src/librustc_mir/build/expr/stmt.rs b/src/librustc_mir/build/expr/stmt.rs index 84468d5d6dc..3cfb0ff4010 100644 --- a/src/librustc_mir/build/expr/stmt.rs +++ b/src/librustc_mir/build/expr/stmt.rs @@ -22,9 +22,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // Handle a number of expressions that don't need a destination at all. This // avoids needing a mountain of temporary `()` variables. match expr.kind { - ExprKind::Scope { region_scope, value } => { + ExprKind::Scope { region_scope, lint_level, value } => { let value = this.hir.mirror(value); - this.in_scope((region_scope, source_info), block, |this| { + this.in_scope((region_scope, source_info), lint_level, block, |this| { this.stmt_expr(block, value) }) } diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index f560fa426e2..f04dede6e40 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -46,8 +46,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // Get the arm bodies and their scopes, while declaring bindings. let arm_bodies: Vec<_> = arms.iter().map(|arm| { + // BUG: use arm lint level let body = self.hir.mirror(arm.body.clone()); - let scope = self.declare_bindings(None, body.span, &arm.patterns[0]); + let scope = self.declare_bindings(None, body.span, + LintLevel::Inherited, + &arm.patterns[0]); (body, scope.unwrap_or(self.visibility_scope)) }).collect(); @@ -171,11 +174,22 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { pub fn declare_bindings(&mut self, mut var_scope: Option<VisibilityScope>, scope_span: Span, + lint_level: LintLevel, pattern: &Pattern<'tcx>) -> Option<VisibilityScope> { + assert!(!(var_scope.is_some() && lint_level.is_explicit()), + "can't have both a var and a lint scope at the same time"); self.visit_bindings(pattern, &mut |this, mutability, name, var, span, ty| { if var_scope.is_none() { - var_scope = Some(this.new_visibility_scope(scope_span)); + var_scope = Some(this.new_visibility_scope(scope_span, + LintLevel::Inherited, + None)); + // If we have lints, create a new visibility scope + // that marks the lints for the locals. + if lint_level.is_explicit() { + this.visibility_scope = + this.new_visibility_scope(scope_span, lint_level, None); + } } let source_info = SourceInfo { span, @@ -183,6 +197,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { }; this.declare_binding(source_info, mutability, name, var, ty); }); + // Pop any scope we created for the locals. + if let Some(var_scope) = var_scope { + self.visibility_scope = var_scope; + } var_scope } @@ -712,6 +730,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ty: var_ty.clone(), name: Some(name), source_info, + lexical_scope: self.visibility_scope, internal: false, is_user_variable: true, }); diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index be6f8c9e56c..68ef646184c 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -11,6 +11,7 @@ use build; use hair::cx::Cx; +use hair::LintLevel; use rustc::hir; use rustc::hir::def_id::DefId; use rustc::middle::region; @@ -71,14 +72,14 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t // is a constant "initializer" expression. match expr.node { hir::ExprClosure(_, _, body, _, _) => body, - _ => hir::BodyId { node_id: expr.id } + _ => hir::BodyId { node_id: expr.id }, } } hir::map::NodeVariant(variant) => return create_constructor_shim(tcx, id, &variant.node.data), hir::map::NodeStructCtor(ctor) => return create_constructor_shim(tcx, id, ctor), - _ => unsupported() + _ => unsupported(), }; let src = MirSource::from_node(tcx, id); @@ -108,6 +109,12 @@ 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 explicit_arguments = body.arguments @@ -126,7 +133,8 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t (None, fn_sig.output()) }; - build::construct_fn(cx, id, arguments, abi, return_ty, yield_ty, body) + build::construct_fn(cx, id, arguments, safety, abi, + return_ty, yield_ty, body) } else { build::construct_const(cx, body_id) }; @@ -270,6 +278,13 @@ struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { /// see the `scope` module for more details scopes: Vec<scope::Scope<'tcx>>, + /// The current unsafe block in scope, even if it is hidden by + /// a PushUnsafeBlock + unpushed_unsafe: Safety, + + /// The number of `push_unsafe_block` levels in scope + push_unsafe_count: usize, + /// the current set of breakables; see the `scope` module for more /// details breakable_scopes: Vec<scope::BreakableScope<'tcx>>, @@ -277,6 +292,7 @@ struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { /// the vector of all scopes that we have created thus far; /// we track this for debuginfo later visibility_scopes: IndexVec<VisibilityScope, VisibilityScopeData>, + visibility_scope_info: IndexVec<VisibilityScope, VisibilityScopeInfo>, visibility_scope: VisibilityScope, /// Maps node ids of variable bindings to the `Local`s created for them. @@ -358,6 +374,7 @@ macro_rules! unpack { fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, fn_id: ast::NodeId, arguments: A, + safety: Safety, abi: Abi, return_ty: Ty<'gcx>, yield_ty: Option<Ty<'gcx>>, @@ -372,14 +389,17 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, let mut builder = Builder::new(hir.clone(), span, arguments.len(), + safety, return_ty); let call_site_scope = region::Scope::CallSite(body.value.hir_id.local_id); let arg_scope = region::Scope::Arguments(body.value.hir_id.local_id); let mut block = START_BLOCK; let source_info = builder.source_info(span); - unpack!(block = builder.in_scope((call_site_scope, source_info), block, |builder| { - unpack!(block = builder.in_scope((arg_scope, source_info), block, |builder| { + let call_site_s = (call_site_scope, source_info); + unpack!(block = builder.in_scope(call_site_s, LintLevel::Inherited, block, |builder| { + let arg_scope_s = (arg_scope, source_info); + unpack!(block = builder.in_scope(arg_scope_s, LintLevel::Inherited, block, |builder| { builder.args_and_body(block, &arguments, arg_scope, &body.value) })); // Attribute epilogue to function's closing brace @@ -440,7 +460,7 @@ fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>, 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 mut builder = Builder::new(hir.clone(), span, 0, ty); + let mut builder = Builder::new(hir.clone(), span, 0, Safety::Safe, ty); let mut block = START_BLOCK; let expr = builder.hir.mirror(ast_expr); @@ -456,11 +476,12 @@ fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>, } fn construct_error<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>, - body_id: hir::BodyId) - -> Mir<'tcx> { - let span = hir.tcx().hir.span(hir.tcx().hir.body_owner(body_id)); + 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 ty = hir.tcx().types.err; - let mut builder = Builder::new(hir, span, 0, ty); + let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty); let source_info = builder.source_info(span); builder.cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable); builder.finish(vec![], ty, None) @@ -470,8 +491,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { fn new(hir: Cx<'a, 'gcx, 'tcx>, span: Span, arg_count: usize, + safety: Safety, return_ty: Ty<'tcx>) -> Builder<'a, 'gcx, 'tcx> { + let lint_level = LintLevel::Explicit(hir.root_lint_level); let mut builder = Builder { hir, cfg: CFG { basic_blocks: IndexVec::new() }, @@ -480,6 +503,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { scopes: vec![], visibility_scopes: IndexVec::new(), visibility_scope: ARGUMENT_VISIBILITY_SCOPE, + visibility_scope_info: IndexVec::new(), + push_unsafe_count: 0, + unpushed_unsafe: safety, breakable_scopes: vec![], local_decls: IndexVec::from_elem_n(LocalDecl::new_return_pointer(return_ty, span), 1), @@ -490,7 +516,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { }; assert_eq!(builder.cfg.start_new_block(), START_BLOCK); - assert_eq!(builder.new_visibility_scope(span), ARGUMENT_VISIBILITY_SCOPE); + assert_eq!( + builder.new_visibility_scope(span, lint_level, Some(safety)), + ARGUMENT_VISIBILITY_SCOPE); builder.visibility_scopes[ARGUMENT_VISIBILITY_SCOPE].parent_scope = None; builder @@ -509,6 +537,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { Mir::new(self.cfg.basic_blocks, self.visibility_scopes, + ClearOnDecode::Set(self.visibility_scope_info), IndexVec::new(), return_ty, yield_ty, @@ -543,6 +572,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { scope: ARGUMENT_VISIBILITY_SCOPE, span: pattern.map_or(self.fn_span, |pat| pat.span) }, + lexical_scope: ARGUMENT_VISIBILITY_SCOPE, name, internal: false, is_user_variable: false, @@ -557,7 +587,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { if let Some(pattern) = pattern { let pattern = self.hir.pattern_from_hir(pattern); - scope = self.declare_bindings(scope, ast_body.span, &pattern); + scope = self.declare_bindings(scope, ast_body.span, + LintLevel::Inherited, &pattern); unpack!(block = self.lvalue_into_pattern(block, pattern, &lvalue)); } diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index bac884b4d01..03273419432 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -88,8 +88,10 @@ should go to. */ use build::{BlockAnd, BlockAndExtension, Builder, CFG}; +use hair::LintLevel; use rustc::middle::region; use rustc::ty::{Ty, TyCtxt}; +use rustc::hir::def_id::LOCAL_CRATE; use rustc::mir::*; use rustc::mir::transform::MirSource; use syntax_pos::{Span}; @@ -304,15 +306,38 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// to build its contents, popping the scope afterwards. pub fn in_scope<F, R>(&mut self, region_scope: (region::Scope, SourceInfo), + lint_level: LintLevel, mut block: BasicBlock, f: F) -> BlockAnd<R> where F: FnOnce(&mut Builder<'a, 'gcx, 'tcx>) -> BlockAnd<R> { debug!("in_scope(region_scope={:?}, block={:?})", region_scope, block); + let visibility_scope = self.visibility_scope; + let tcx = self.hir.tcx(); + if let LintLevel::Explicit(node_id) = lint_level { + 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( + self.visibility_scope_info[visibility_scope].lint_root + ); + let current_hir_id = + tcx.hir.definitions().node_to_hir_id(node_id); + sets.lint_level_set(parent_hir_id) == + sets.lint_level_set(current_hir_id) + }); + + if !same_lint_scopes { + self.visibility_scope = + self.new_visibility_scope(region_scope.1.span, lint_level, + None); + } + } self.push_scope(region_scope); let rv = unpack!(block = f(self)); unpack!(block = self.pop_scope(region_scope, block)); + self.visibility_scope = visibility_scope; debug!("in_scope: exiting region_scope={:?} block={:?}", region_scope, block); block.and(rv) } @@ -474,13 +499,29 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } /// Creates a new visibility scope, nested in the current one. - pub fn new_visibility_scope(&mut self, span: Span) -> VisibilityScope { + pub fn new_visibility_scope(&mut self, + span: Span, + lint_level: LintLevel, + safety: Option<Safety>) -> VisibilityScope { let parent = self.visibility_scope; - let scope = VisibilityScope::new(self.visibility_scopes.len()); - self.visibility_scopes.push(VisibilityScopeData { + debug!("new_visibility_scope({:?}, {:?}, {:?}) - parent({:?})={:?}", + span, lint_level, safety, + parent, self.visibility_scope_info.get(parent)); + let scope = self.visibility_scopes.push(VisibilityScopeData { span, parent_scope: Some(parent), }); + let scope_info = VisibilityScopeInfo { + lint_root: if let LintLevel::Explicit(lint_root) = lint_level { + lint_root + } else { + self.visibility_scope_info[parent].lint_root + }, + safety: safety.unwrap_or_else(|| { + self.visibility_scope_info[parent].safety + }) + }; + self.visibility_scope_info.push(scope_info); scope } @@ -514,8 +555,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // The outermost scope (`scopes[0]`) will be the `CallSiteScope`. // We want `scopes[1]`, which is the `ParameterScope`. assert!(self.scopes.len() >= 2); - assert!(match self.scopes[1].region_scope { - region::Scope::Arguments(_) => true, + assert!(match self.scopes[1].region_scope.data() { + region::ScopeData::Arguments(_) => true, _ => false, }); self.scopes[1].region_scope diff --git a/src/librustc_mir/diagnostics.rs b/src/librustc_mir/diagnostics.rs index 26436d54ac8..2c4afb0aa0e 100644 --- a/src/librustc_mir/diagnostics.rs +++ b/src/librustc_mir/diagnostics.rs @@ -195,6 +195,40 @@ instead of using a `const fn`, or refactoring the code to a functional style to avoid mutation if possible. "##, +E0133: r##" +Unsafe code was used outside of an unsafe function or block. + +Erroneous code example: + +```compile_fail,E0133 +unsafe fn f() { return; } // This is the unsafe code + +fn main() { + f(); // error: call to unsafe function requires unsafe function or block +} +``` + +Using unsafe functionality is potentially dangerous and disallowed by safety +checks. Examples: + +* Dereferencing raw pointers +* Calling functions via FFI +* Calling functions marked unsafe + +These safety checks can be relaxed for a section of the code by wrapping the +unsafe instructions with an `unsafe` block. For instance: + +``` +unsafe fn f() { return; } + +fn main() { + unsafe { f(); } // ok! +} +``` + +See also https://doc.rust-lang.org/book/first-edition/unsafe.html +"##, + E0381: r##" It is not allowed to use or capture an uninitialized variable. For example: diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs index f6b847d6d6d..6f6258f52f7 100644 --- a/src/librustc_mir/hair/cx/block.rs +++ b/src/librustc_mir/hair/cx/block.rs @@ -14,6 +14,8 @@ use hair::cx::to_ref::ToRef; use rustc::middle::region::{self, BlockRemainder}; use rustc::hir; +use rustc_data_structures::indexed_vec::Idx; + impl<'tcx> Mirror<'tcx> for &'tcx hir::Block { type Output = Block<'tcx>; @@ -30,6 +32,16 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Block { span: self.span, stmts, expr: self.expr.to_ref(), + safety_mode: match self.rules { + hir::BlockCheckMode::DefaultBlock => + BlockSafety::Safe, + hir::BlockCheckMode::UnsafeBlock(..) => + BlockSafety::ExplicitUnsafe(self.id), + hir::BlockCheckMode::PushUnsafeBlock(..) => + BlockSafety::PushUnsafe, + hir::BlockCheckMode::PopUnsafeBlock(..) => + BlockSafety::PopUnsafe + }, } } } @@ -61,7 +73,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, hir::DeclLocal(ref local) => { let remainder_scope = region::Scope::Remainder(BlockRemainder { block: block_id, - first_statement_index: index as u32, + first_statement_index: region::FirstStatementIndex::new(index), }); let pattern = cx.pattern_from_hir(&local.pat); @@ -71,6 +83,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, init_scope: region::Scope::Node(hir_id.local_id), pattern, initializer: local.init.to_ref(), + lint_level: cx.lint_level_of(local.id), }, opt_destruction_scope: opt_dxn_ext, }))); diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 45449103c80..f5a53e2aa8e 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -48,22 +48,24 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { kind: ExprKind::Scope { region_scope: expr_scope, value: expr.to_ref(), + lint_level: cx.lint_level_of(self.id), }, }; // Finally, create a destruction scope, if any. if let Some(region_scope) = - cx.region_scope_tree.opt_destruction_scope(self.hir_id.local_id) { - expr = Expr { - temp_lifetime, - ty: expr.ty, - span: self.span, - kind: ExprKind::Scope { - region_scope, - value: expr.to_ref(), - }, - }; - } + cx.region_scope_tree.opt_destruction_scope(self.hir_id.local_id) { + expr = Expr { + temp_lifetime, + ty: expr.ty, + span: self.span, + kind: ExprKind::Scope { + region_scope, + value: expr.to_ref(), + lint_level: LintLevel::Inherited, + }, + }; + } // OK, all done! expr @@ -619,6 +621,8 @@ fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, arm: &'tcx hir::Arm) patterns: arm.pats.iter().map(|p| cx.pattern_from_hir(p)).collect(), guard: arm.guard.to_ref(), body: arm.body.to_ref(), + // BUG: fix this + lint_level: LintLevel::Inherited, } } diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index f5e15979006..4434df0ac3e 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -20,13 +20,14 @@ use rustc::mir::transform::MirSource; use rustc::middle::const_val::{ConstEvalErr, ConstVal}; use rustc_const_eval::ConstContext; use rustc_data_structures::indexed_vec::Idx; -use rustc::hir::def_id::DefId; +use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::hir::map::blocks::FnLikeNode; use rustc::middle::region; use rustc::infer::InferCtxt; use rustc::ty::subst::Subst; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::subst::Substs; +use syntax::ast; use syntax::symbol::Symbol; use rustc::hir; use rustc_const_math::{ConstInt, ConstUsize}; @@ -37,6 +38,7 @@ pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { tcx: TyCtxt<'a, 'gcx, 'tcx>, infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + pub root_lint_level: ast::NodeId, pub param_env: ty::ParamEnv<'gcx>, /// Identity `Substs` for use with const-evaluation. @@ -57,7 +59,8 @@ pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { } impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { - pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, src: MirSource) -> Cx<'a, 'gcx, 'tcx> { + pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + src: MirSource) -> Cx<'a, 'gcx, 'tcx> { let constness = match src { MirSource::Const(_) | MirSource::Static(..) => hir::Constness::Const, @@ -87,9 +90,11 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { // Constants and const fn's always need overflow checks. check_overflow |= constness == hir::Constness::Const; + let lint_level = lint_level_for_hir_id(tcx, src_id); Cx { tcx, infcx, + root_lint_level: lint_level, param_env: tcx.param_env(src_def_id), identity_substs: Substs::identity_for_item(tcx.global_tcx(), src_def_id), region_scope_tree: tcx.region_scope_tree(src_def_id), @@ -99,6 +104,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { check_overflow, } } + } impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { @@ -229,6 +235,19 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { ty.needs_drop(self.tcx.global_tcx(), param_env) } + fn lint_level_of(&self, node_id: ast::NodeId) -> LintLevel { + 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() + }); + + if has_lint_level { + LintLevel::Explicit(node_id) + } else { + LintLevel::Inherited + } + } + pub fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { self.tcx } @@ -242,6 +261,31 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { } } +fn lint_level_for_hir_id(tcx: TyCtxt, mut id: ast::NodeId) -> ast::NodeId { + // Right now we insert a `with_ignore` node in the dep graph here to + // ignore the fact that `lint_levels` below depends on the entire crate. + // For now this'll prevent false positives of recompiling too much when + // anything changes. + // + // Once red/green incremental compilation lands we should be able to + // remove this because while the crate changes often the lint level map + // will change rarely. + tcx.dep_graph.with_ignore(|| { + let sets = tcx.lint_levels(LOCAL_CRATE); + loop { + 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); + if next == id { + bug!("lint traversal reached the root of the crate"); + } + id = next; + } + }) +} + mod block; mod expr; mod to_ref; diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index 3162242de66..09a31f9ab8f 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -29,6 +29,21 @@ pub mod cx; pub use rustc_const_eval::pattern::{BindingMode, Pattern, PatternKind, FieldPattern}; +#[derive(Copy, Clone, Debug)] +pub enum LintLevel { + Inherited, + Explicit(ast::NodeId) +} + +impl LintLevel { + pub fn is_explicit(self) -> bool { + match self { + LintLevel::Inherited => false, + LintLevel::Explicit(_) => true + } + } +} + #[derive(Clone, Debug)] pub struct Block<'tcx> { pub targeted_by_break: bool, @@ -37,6 +52,15 @@ pub struct Block<'tcx> { pub span: Span, pub stmts: Vec<StmtRef<'tcx>>, pub expr: Option<ExprRef<'tcx>>, + pub safety_mode: BlockSafety, +} + +#[derive(Copy, Clone, Debug)] +pub enum BlockSafety { + Safe, + ExplicitUnsafe(ast::NodeId), + PushUnsafe, + PopUnsafe } #[derive(Clone, Debug)] @@ -73,7 +97,10 @@ pub enum StmtKind<'tcx> { pattern: Pattern<'tcx>, /// let pat = <INIT> ... - initializer: Option<ExprRef<'tcx>> + initializer: Option<ExprRef<'tcx>>, + + /// the lint level for this let-statement + lint_level: LintLevel, }, } @@ -111,6 +138,7 @@ pub struct Expr<'tcx> { pub enum ExprKind<'tcx> { Scope { region_scope: region::Scope, + lint_level: LintLevel, value: ExprRef<'tcx>, }, Box { @@ -275,6 +303,7 @@ pub struct Arm<'tcx> { pub patterns: Vec<Pattern<'tcx>>, pub guard: Option<ExprRef<'tcx>>, pub body: ExprRef<'tcx>, + pub lint_level: LintLevel, } #[derive(Copy, Clone, Debug)] diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 31480457723..a3a986918a4 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -140,6 +140,7 @@ fn temp_decl(mutability: Mutability, ty: Ty, span: Span) -> LocalDecl { LocalDecl { mutability, ty, name: None, source_info: SourceInfo { scope: ARGUMENT_VISIBILITY_SCOPE, span }, + lexical_scope: ARGUMENT_VISIBILITY_SCOPE, internal: false, is_user_variable: false } @@ -195,6 +196,7 @@ fn build_drop_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, IndexVec::from_elem_n( VisibilityScopeData { span: span, parent_scope: None }, 1 ), + ClearOnDecode::Clear, IndexVec::new(), sig.output(), None, @@ -342,6 +344,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> { IndexVec::from_elem_n( VisibilityScopeData { span: self.span, parent_scope: None }, 1 ), + ClearOnDecode::Clear, IndexVec::new(), self.sig.output(), None, @@ -804,6 +807,7 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, IndexVec::from_elem_n( VisibilityScopeData { span: span, parent_scope: None }, 1 ), + ClearOnDecode::Clear, IndexVec::new(), sig.output(), None, @@ -876,6 +880,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>, IndexVec::from_elem_n( VisibilityScopeData { span: span, parent_scope: None }, 1 ), + ClearOnDecode::Clear, IndexVec::new(), sig.output(), None, diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs new file mode 100644 index 00000000000..49ce3622399 --- /dev/null +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -0,0 +1,387 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::indexed_vec::IndexVec; + +use rustc::ty::maps::Providers; +use rustc::ty::{self, TyCtxt}; +use rustc::hir; +use rustc::hir::def::Def; +use rustc::hir::def_id::DefId; +use rustc::hir::map::{DefPathData, Node}; +use rustc::lint::builtin::{SAFE_EXTERN_STATICS, UNUSED_UNSAFE}; +use rustc::mir::*; +use rustc::mir::visit::{LvalueContext, Visitor}; + +use syntax::ast; + +use std::rc::Rc; + + +pub struct UnsafetyChecker<'a, 'tcx: 'a> { + mir: &'a Mir<'tcx>, + visibility_scope_info: &'a IndexVec<VisibilityScope, VisibilityScopeInfo>, + violations: Vec<UnsafetyViolation>, + source_info: SourceInfo, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + used_unsafe: FxHashSet<ast::NodeId>, +} + +impl<'a, 'gcx, 'tcx> UnsafetyChecker<'a, 'tcx> { + fn new(mir: &'a Mir<'tcx>, + visibility_scope_info: &'a IndexVec<VisibilityScope, VisibilityScopeInfo>, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + param_env: ty::ParamEnv<'tcx>) -> Self { + Self { + mir, + visibility_scope_info, + violations: vec![], + source_info: SourceInfo { + span: mir.span, + scope: ARGUMENT_VISIBILITY_SCOPE + }, + tcx, + param_env, + used_unsafe: FxHashSet(), + } + } +} + +impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { + fn visit_terminator(&mut self, + block: BasicBlock, + terminator: &Terminator<'tcx>, + location: Location) + { + self.source_info = terminator.source_info; + match terminator.kind { + TerminatorKind::Goto { .. } | + TerminatorKind::SwitchInt { .. } | + TerminatorKind::Drop { .. } | + TerminatorKind::Yield { .. } | + TerminatorKind::Assert { .. } | + TerminatorKind::DropAndReplace { .. } | + TerminatorKind::GeneratorDrop | + TerminatorKind::Resume | + TerminatorKind::Return | + TerminatorKind::Unreachable => { + // safe (at least as emitted during MIR construction) + } + + TerminatorKind::Call { ref func, .. } => { + let func_ty = func.ty(self.mir, self.tcx); + let sig = func_ty.fn_sig(self.tcx); + if let hir::Unsafety::Unsafe = sig.unsafety() { + self.require_unsafe("call to unsafe function") + } + } + } + self.super_terminator(block, terminator, location); + } + + fn visit_statement(&mut self, + block: BasicBlock, + statement: &Statement<'tcx>, + location: Location) + { + self.source_info = statement.source_info; + match statement.kind { + StatementKind::Assign(..) | + StatementKind::SetDiscriminant { .. } | + StatementKind::StorageLive(..) | + StatementKind::StorageDead(..) | + StatementKind::EndRegion(..) | + StatementKind::Validate(..) | + StatementKind::Nop => { + // safe (at least as emitted during MIR construction) + } + + StatementKind::InlineAsm { .. } => { + self.require_unsafe("use of inline assembly") + }, + } + self.super_statement(block, statement, location); + } + + fn visit_rvalue(&mut self, + rvalue: &Rvalue<'tcx>, + location: Location) + { + if let &Rvalue::Aggregate( + box AggregateKind::Closure(def_id, _), + _ + ) = rvalue { + let unsafety_violations = self.tcx.unsafety_violations(def_id); + self.register_violations(&unsafety_violations); + } + self.super_rvalue(rvalue, location); + } + + fn visit_lvalue(&mut self, + lvalue: &Lvalue<'tcx>, + context: LvalueContext<'tcx>, + location: Location) { + match lvalue { + &Lvalue::Projection(box Projection { + ref base, ref elem + }) => { + let old_source_info = self.source_info; + if let &Lvalue::Local(local) = base { + if self.mir.local_decls[local].internal { + // Internal locals are used in the `move_val_init` desugaring. + // We want to check unsafety against the source info of the + // desugaring, rather than the source info of the RHS. + self.source_info = self.mir.local_decls[local].source_info; + } + } + let base_ty = base.ty(self.mir, self.tcx).to_ty(self.tcx); + match base_ty.sty { + ty::TyRawPtr(..) => { + self.require_unsafe("dereference of raw pointer") + } + ty::TyAdt(adt, _) if adt.is_union() => { + if context == LvalueContext::Store || + context == LvalueContext::Drop + { + let elem_ty = match elem { + &ProjectionElem::Field(_, ty) => ty, + _ => span_bug!( + self.source_info.span, + "non-field projection {:?} from union?", + lvalue) + }; + if elem_ty.moves_by_default(self.tcx, self.param_env, + self.source_info.span) { + self.require_unsafe( + "assignment to non-`Copy` union field") + } else { + // write to non-move union, safe + } + } else { + self.require_unsafe("access to union field") + } + } + _ => {} + } + self.source_info = old_source_info; + } + &Lvalue::Local(..) => { + // locals are safe + } + &Lvalue::Static(box Static { def_id, ty: _ }) => { + if self.is_static_mut(def_id) { + self.require_unsafe("use of mutable static"); + } else if self.tcx.is_foreign_item(def_id) { + let source_info = self.source_info; + let lint_root = + self.visibility_scope_info[source_info.scope].lint_root; + self.register_violations(&[UnsafetyViolation { + source_info, + description: "use of extern static", + lint_node_id: Some(lint_root) + }]); + } + } + } + self.super_lvalue(lvalue, context, location); + } +} + +impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { + fn is_static_mut(&self, def_id: DefId) -> bool { + if let Some(node) = self.tcx.hir.get_if_local(def_id) { + match node { + Node::NodeItem(&hir::Item { + node: hir::ItemStatic(_, hir::MutMutable, _), .. + }) => true, + Node::NodeForeignItem(&hir::ForeignItem { + node: hir::ForeignItemStatic(_, mutbl), .. + }) => mutbl, + _ => false + } + } else { + match self.tcx.describe_def(def_id) { + Some(Def::Static(_, mutbl)) => mutbl, + _ => false + } + } + } + fn require_unsafe(&mut self, + description: &'static str) + { + let source_info = self.source_info; + self.register_violations(&[UnsafetyViolation { + source_info, description, lint_node_id: None + }]); + } + + fn register_violations(&mut self, violations: &[UnsafetyViolation]) { + match self.visibility_scope_info[self.source_info.scope].safety { + Safety::Safe => { + for violation in violations { + if !self.violations.contains(violation) { + self.violations.push(violation.clone()) + } + } + } + Safety::BuiltinUnsafe | Safety::FnUnsafe => {} + Safety::ExplicitUnsafe(node_id) => { + if !violations.is_empty() { + self.used_unsafe.insert(node_id); + } + } + } + } +} + +pub(crate) fn provide(providers: &mut Providers) { + *providers = Providers { + unsafety_violations, + ..*providers + }; +} + +struct UnusedUnsafeVisitor<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + used_unsafe: FxHashSet<ast::NodeId> +} + +impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'a, 'tcx> { + fn nested_visit_map<'this>(&'this mut self) -> + hir::intravisit::NestedVisitorMap<'this, 'tcx> + { + hir::intravisit::NestedVisitorMap::None + } + + fn visit_block(&mut self, block: &'tcx hir::Block) { + hir::intravisit::walk_block(self, block); + + if let hir::UnsafeBlock(hir::UserProvided) = block.rules { + if !self.used_unsafe.contains(&block.id) { + self.report_unused_unsafe(block); + } + } + } +} + +impl<'a, 'tcx> UnusedUnsafeVisitor<'a, 'tcx> { + /// Return the NodeId for an enclosing scope that is also `unsafe` + fn is_enclosed(&self, id: ast::NodeId) -> Option<(String, ast::NodeId)> { + let parent_id = self.tcx.hir.get_parent_node(id); + if parent_id != id { + if self.used_unsafe.contains(&parent_id) { + Some(("block".to_string(), parent_id)) + } else if let Some(hir::map::NodeItem(&hir::Item { + node: hir::ItemFn(_, hir::Unsafety::Unsafe, _, _, _, _), + .. + })) = self.tcx.hir.find(parent_id) { + Some(("fn".to_string(), parent_id)) + } else { + self.is_enclosed(parent_id) + } + } else { + None + } + } + + fn report_unused_unsafe(&self, block: &'tcx hir::Block) { + let mut db = self.tcx.struct_span_lint_node(UNUSED_UNSAFE, + block.id, + block.span, + "unnecessary `unsafe` block"); + db.span_label(block.span, "unnecessary `unsafe` block"); + if let Some((kind, id)) = self.is_enclosed(block.id) { + db.span_note(self.tcx.hir.span(id), + &format!("because it's nested under this `unsafe` {}", kind)); + } + db.emit(); + } +} + +fn check_unused_unsafe<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId, + used_unsafe: FxHashSet<ast::NodeId>) +{ + let body_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 { + Some(body) => body, + None => { + debug!("check_unused_unsafe({:?}) - no body found", def_id); + return + } + }; + let body = tcx.hir.body(body_id); + debug!("check_unused_unsafe({:?}, body={:?}, used_unsafe={:?})", + def_id, body, used_unsafe); + + hir::intravisit::Visitor::visit_body( + &mut UnusedUnsafeVisitor { tcx, used_unsafe }, + body); +} + +fn unsafety_violations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> + Rc<[UnsafetyViolation]> +{ + debug!("unsafety_violations({:?})", def_id); + + // NB: this borrow is valid because all the consumers of + // `mir_const` force this. + let mir = &tcx.mir_const(def_id).borrow(); + + let visibility_scope_info = match mir.visibility_scope_info { + ClearOnDecode::Set(ref data) => data, + ClearOnDecode::Clear => { + debug!("unsafety_violations: {:?} - remote, skipping", def_id); + return Rc::new([]) + } + }; + + let param_env = tcx.param_env(def_id); + let mut checker = UnsafetyChecker::new( + mir, visibility_scope_info, tcx, param_env); + checker.visit_mir(mir); + + check_unused_unsafe(tcx, def_id, checker.used_unsafe); + checker.violations.into() +} + +pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { + debug!("check_unsafety({:?})", def_id); + match tcx.def_key(def_id).disambiguated_data.data { + // closures are handled by their parent fn. + DefPathData::ClosureExpr => return, + _ => {} + }; + + for &UnsafetyViolation { + source_info, description, lint_node_id + } in &*tcx.unsafety_violations(def_id) { + // Report an error. + if let Some(lint_node_id) = lint_node_id { + tcx.lint_node(SAFE_EXTERN_STATICS, + lint_node_id, + source_info.span, + &format!("{} requires unsafe function or \ + block (error E0133)", description)); + } else { + struct_span_err!( + tcx.sess, source_info.span, E0133, + "{} requires unsafe function or block", description) + .span_label(source_info.span, description) + .emit(); + } + } +} diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 78fe7b26ebf..729fe46ef37 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -301,6 +301,7 @@ fn replace_result_variable<'tcx>(ret_ty: Ty<'tcx>, ty: ret_ty, name: None, source_info: source_info(mir), + lexical_scope: ARGUMENT_VISIBILITY_SCOPE, internal: false, is_user_variable: false, }; @@ -443,14 +444,15 @@ fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn insert_switch<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &mut Mir<'tcx>, cases: Vec<(u32, BasicBlock)>, - transform: &TransformVisitor<'a, 'tcx>) { - let return_block = insert_return_block(mir); + transform: &TransformVisitor<'a, 'tcx>, + default: TerminatorKind<'tcx>) { + let default_block = insert_term_block(mir, default); let switch = TerminatorKind::SwitchInt { discr: Operand::Consume(transform.make_field(transform.state_field, tcx.types.u32)), switch_ty: tcx.types.u32, values: Cow::from(cases.iter().map(|&(i, _)| ConstInt::U32(i)).collect::<Vec<_>>()), - targets: cases.iter().map(|&(_, d)| d).chain(once(return_block)).collect(), + targets: cases.iter().map(|&(_, d)| d).chain(once(default_block)).collect(), }; let source_info = source_info(mir); @@ -542,7 +544,7 @@ fn create_generator_drop_shim<'a, 'tcx>( // The returned state (1) and the poisoned state (2) falls through to // the default case which is just to return - insert_switch(tcx, &mut mir, cases, &transform); + insert_switch(tcx, &mut mir, cases, &transform, TerminatorKind::Return); for block in mir.basic_blocks_mut() { let kind = &mut block.terminator_mut().kind; @@ -558,6 +560,7 @@ fn create_generator_drop_shim<'a, 'tcx>( ty: tcx.mk_nil(), name: None, source_info, + lexical_scope: ARGUMENT_VISIBILITY_SCOPE, internal: false, is_user_variable: false, }; @@ -573,6 +576,7 @@ fn create_generator_drop_shim<'a, 'tcx>( }), name: None, source_info, + lexical_scope: ARGUMENT_VISIBILITY_SCOPE, internal: false, is_user_variable: false, }; @@ -588,18 +592,18 @@ fn create_generator_drop_shim<'a, 'tcx>( mir } -fn insert_return_block<'tcx>(mir: &mut Mir<'tcx>) -> BasicBlock { - let return_block = BasicBlock::new(mir.basic_blocks().len()); +fn insert_term_block<'tcx>(mir: &mut Mir<'tcx>, kind: TerminatorKind<'tcx>) -> BasicBlock { + let term_block = BasicBlock::new(mir.basic_blocks().len()); let source_info = source_info(mir); mir.basic_blocks_mut().push(BasicBlockData { statements: Vec::new(), terminator: Some(Terminator { source_info, - kind: TerminatorKind::Return, + kind, }), is_cleanup: false, }); - return_block + term_block } fn insert_panic_block<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -659,7 +663,7 @@ fn create_generator_resume_function<'a, 'tcx>( // Panic when resumed on the poisoned (2) state cases.insert(2, (2, insert_panic_block(tcx, mir, AssertMessage::GeneratorResumedAfterPanic))); - insert_switch(tcx, mir, cases, &transform); + insert_switch(tcx, mir, cases, &transform, TerminatorKind::Unreachable); make_generator_state_argument_indirect(tcx, def_id, mir); @@ -680,7 +684,7 @@ fn source_info<'a, 'tcx>(mir: &Mir<'tcx>) -> SourceInfo { } fn insert_clean_drop<'a, 'tcx>(mir: &mut Mir<'tcx>) -> BasicBlock { - let return_block = insert_return_block(mir); + let return_block = insert_term_block(mir, TerminatorKind::Return); // Create a block to destroy an unresumed generators. This can only destroy upvars. let drop_clean = BasicBlock::new(mir.basic_blocks().len()); diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index e0f2a40ab07..7245b2daa12 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -26,6 +26,7 @@ use transform; pub mod add_validation; pub mod clean_end_regions; +pub mod check_unsafety; pub mod simplify_branches; pub mod simplify; pub mod erase_regions; @@ -46,6 +47,7 @@ pub mod nll; pub(crate) fn provide(providers: &mut Providers) { self::qualify_consts::provide(providers); + self::check_unsafety::provide(providers); *providers = Providers { mir_keys, mir_const, @@ -116,6 +118,7 @@ fn mir_validated<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx // directly need the result or `mir_const_qualif`, so we can just force it. ty::queries::mir_const_qualif::force(tcx, DUMMY_SP, def_id); } + ty::queries::unsafety_violations::force(tcx, DUMMY_SP, def_id); let mut mir = tcx.mir_const(def_id).steal(); transform::run_suite(tcx, source, MIR_VALIDATED, &mut mir); diff --git a/src/librustc_mir/transform/nll.rs b/src/librustc_mir/transform/nll/mod.rs index bd02788df16..bd02788df16 100644 --- a/src/librustc_mir/transform/nll.rs +++ b/src/librustc_mir/transform/nll/mod.rs diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index ca6eda5c2d7..339ea8a414b 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -380,10 +380,10 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>, let mut promoter = Promoter { promoted: Mir::new( IndexVec::new(), - Some(VisibilityScopeData { - span, - parent_scope: None - }).into_iter().collect(), + // FIXME: maybe try to filter this to avoid blowing up + // memory usage? + mir.visibility_scopes.clone(), + mir.visibility_scope_info.clone(), IndexVec::new(), ty, None, diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index ffe444933a3..efb5b031809 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -122,14 +122,6 @@ impl<'a> AstValidator<'a> { } impl<'a> Visitor<'a> for AstValidator<'a> { - fn visit_lifetime(&mut self, lt: &'a Lifetime) { - if lt.ident.name == "'_" { - self.err_handler().span_err(lt.span, &format!("invalid lifetime name `{}`", lt.ident)); - } - - visit::walk_lifetime(self, lt) - } - fn visit_expr(&mut self, expr: &'a Expr) { match expr.node { ExprKind::While(.., Some(ident)) | diff --git a/src/librustc_privacy/Cargo.toml b/src/librustc_privacy/Cargo.toml index 439fa661e0a..c65312e9a83 100644 --- a/src/librustc_privacy/Cargo.toml +++ b/src/librustc_privacy/Cargo.toml @@ -10,5 +10,6 @@ crate-type = ["dylib"] [dependencies] rustc = { path = "../librustc" } +rustc_typeck = { path = "../librustc_typeck" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 0d5ad6f47c9..e7a1dd6b043 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -17,6 +17,7 @@ #[macro_use] extern crate rustc; #[macro_use] extern crate syntax; +extern crate rustc_typeck; extern crate syntax_pos; use rustc::hir::{self, PatKind}; @@ -658,65 +659,6 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> { } false } - - fn check_item(&mut self, item_id: ast::NodeId) -> &mut Self { - self.current_item = self.tcx.hir.local_def_id(item_id); - self.span = self.tcx.hir.span(item_id); - self - } - - // Convenience methods for checking item interfaces - fn ty(&mut self) -> &mut Self { - self.tcx.type_of(self.current_item).visit_with(self); - self - } - - fn generics(&mut self) -> &mut Self { - for def in &self.tcx.generics_of(self.current_item).types { - if def.has_default { - self.tcx.type_of(def.def_id).visit_with(self); - } - } - self - } - - fn predicates(&mut self) -> &mut Self { - let predicates = self.tcx.predicates_of(self.current_item); - for predicate in &predicates.predicates { - predicate.visit_with(self); - match predicate { - &ty::Predicate::Trait(poly_predicate) => { - self.check_trait_ref(poly_predicate.skip_binder().trait_ref); - }, - &ty::Predicate::Projection(poly_predicate) => { - let tcx = self.tcx; - self.check_trait_ref( - poly_predicate.skip_binder().projection_ty.trait_ref(tcx) - ); - }, - _ => (), - }; - } - self - } - - fn impl_trait_ref(&mut self) -> &mut Self { - if let Some(impl_trait_ref) = self.tcx.impl_trait_ref(self.current_item) { - self.check_trait_ref(impl_trait_ref); - } - self.tcx.predicates_of(self.current_item).visit_with(self); - self - } - - fn check_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) -> bool { - if !self.item_is_accessible(trait_ref.def_id) { - let msg = format!("trait `{}` is private", trait_ref); - self.tcx.sess.span_err(self.span, &msg); - return true; - } - - trait_ref.super_visit_with(self) - } } impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { @@ -733,6 +675,35 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { self.tables = orig_tables; } + fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty) { + self.span = hir_ty.span; + if let Some(ty) = self.tables.node_id_to_type_opt(hir_ty.hir_id) { + // Types in bodies. + if ty.visit_with(self) { + return; + } + } else { + // Types in signatures. + // FIXME: This is very ineffective. Ideally each HIR type should be converted + // into a semantic type only once and the result should be cached somehow. + if rustc_typeck::hir_ty_to_ty(self.tcx, hir_ty).visit_with(self) { + return; + } + } + + intravisit::walk_ty(self, hir_ty); + } + + fn visit_trait_ref(&mut self, trait_ref: &'tcx hir::TraitRef) { + if !self.item_is_accessible(trait_ref.path.def.def_id()) { + let msg = format!("trait `{:?}` is private", trait_ref.path); + self.tcx.sess.span_err(self.span, &msg); + return; + } + + intravisit::walk_trait_ref(self, trait_ref); + } + // Check types of expressions fn visit_expr(&mut self, expr: &'tcx hir::Expr) { if self.check_expr_pat_type(expr.hir_id, expr.span) { @@ -807,63 +778,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { item.id, &mut self.tables, self.empty_tables); - - match item.node { - hir::ItemExternCrate(..) | hir::ItemMod(..) | - hir::ItemUse(..) | hir::ItemGlobalAsm(..) => {} - hir::ItemConst(..) | hir::ItemStatic(..) | - hir::ItemTy(..) | hir::ItemFn(..) => { - self.check_item(item.id).generics().predicates().ty(); - } - hir::ItemTrait(.., ref trait_item_refs) => { - self.check_item(item.id).generics().predicates(); - for trait_item_ref in trait_item_refs { - let check = self.check_item(trait_item_ref.id.node_id); - check.generics().predicates(); - if trait_item_ref.kind != hir::AssociatedItemKind::Type || - trait_item_ref.defaultness.has_value() { - check.ty(); - } - } - } - hir::ItemEnum(ref def, _) => { - self.check_item(item.id).generics().predicates(); - for variant in &def.variants { - for field in variant.node.data.fields() { - self.check_item(field.id).ty(); - } - } - } - hir::ItemForeignMod(ref foreign_mod) => { - for foreign_item in &foreign_mod.items { - self.check_item(foreign_item.id).generics().predicates().ty(); - } - } - hir::ItemStruct(ref struct_def, _) | - hir::ItemUnion(ref struct_def, _) => { - self.check_item(item.id).generics().predicates(); - for field in struct_def.fields() { - self.check_item(field.id).ty(); - } - } - hir::ItemDefaultImpl(..) => { - self.check_item(item.id).impl_trait_ref(); - } - hir::ItemImpl(.., ref trait_ref, _, ref impl_item_refs) => { - { - let check = self.check_item(item.id); - check.ty().generics().predicates(); - if trait_ref.is_some() { - check.impl_trait_ref(); - } - } - for impl_item_ref in impl_item_refs { - let impl_item = self.tcx.hir.impl_item(impl_item_ref.id); - self.check_item(impl_item.id).generics().predicates().ty(); - } - } - } - self.current_item = self.tcx.hir.local_def_id(item.id); intravisit::walk_item(self, item); self.tables = orig_tables; @@ -924,8 +838,13 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { } } ty::TyProjection(ref proj) => { - let tcx = self.tcx; - if self.check_trait_ref(proj.trait_ref(tcx)) { + let trait_ref = proj.trait_ref(self.tcx); + if !self.item_is_accessible(trait_ref.def_id) { + let msg = format!("trait `{}` is private", trait_ref); + self.tcx.sess.span_err(self.span, &msg); + return true; + } + if trait_ref.super_visit_with(self) { return true; } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 691329c608c..36cd69f91b9 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -605,7 +605,7 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder { ItemKind::Use(..) => { // don't suggest placing a use before the prelude // import or other generated ones - if item.span == DUMMY_SP { + if item.span.ctxt().outer().expn_info().is_none() { self.span = Some(item.span.with_hi(item.span.lo())); self.found_use = true; return; @@ -615,11 +615,22 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder { ItemKind::ExternCrate(_) => {} // but place them before the first other item _ => if self.span.map_or(true, |span| item.span < span ) { - self.span = Some(item.span.with_hi(item.span.lo())); + if item.span.ctxt().outer().expn_info().is_none() { + // don't insert between attributes and an item + if item.attrs.is_empty() { + self.span = Some(item.span.with_hi(item.span.lo())); + } else { + // 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.with_hi(attr.span.lo())); + } + } + } + } }, } } - assert!(self.span.is_some(), "a file can't have no items and emit suggestions"); } } @@ -3553,8 +3564,7 @@ impl<'a> Resolver<'a> { }; visit::walk_crate(&mut finder, krate); if !candidates.is_empty() { - let span = finder.span.expect("did not find module"); - show_candidates(&mut err, span, &candidates, better, finder.found_use); + show_candidates(&mut err, finder.span, &candidates, better, finder.found_use); } err.emit(); } @@ -3748,7 +3758,8 @@ fn import_candidate_to_paths(suggestion: &ImportSuggestion) -> (Span, String, St /// entities with that name in all crates. This method allows outputting the /// results of this search in a programmer-friendly way fn show_candidates(err: &mut DiagnosticBuilder, - span: Span, + // This is `None` if all placement locations are inside expansions + span: Option<Span>, candidates: &[ImportSuggestion], better: bool, found_use: bool) { @@ -3766,18 +3777,27 @@ fn show_candidates(err: &mut DiagnosticBuilder, }; let msg = format!("possible {}candidate{} into scope", better, msg_diff); - for candidate in &mut path_strings { - // produce an additional newline to separate the new use statement - // from the directly following item. - let additional_newline = if found_use { - "" - } else { - "\n" - }; - *candidate = format!("use {};\n{}", candidate, additional_newline); - } + if let Some(span) = span { + for candidate in &mut path_strings { + // produce an additional newline to separate the new use statement + // from the directly following item. + let additional_newline = if found_use { + "" + } else { + "\n" + }; + *candidate = format!("use {};\n{}", candidate, additional_newline); + } - err.span_suggestions(span, &msg, path_strings); + err.span_suggestions(span, &msg, path_strings); + } else { + let mut msg = msg; + msg.push(':'); + for candidate in path_strings { + msg.push('\n'); + msg.push_str(&candidate); + } + } } /// A somewhat inefficient routine to obtain the name of a module. diff --git a/src/librustc_trans/Cargo.toml b/src/librustc_trans/Cargo.toml index 6f1f5b4a123..482350d04b5 100644 --- a/src/librustc_trans/Cargo.toml +++ b/src/librustc_trans/Cargo.toml @@ -32,4 +32,4 @@ syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } [target."cfg(windows)".dependencies] -gcc = "0.3.50" +cc = "1.0" diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 08266e86f97..619ea59ff1a 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern crate rustc_trans_utils; - use super::archive::{ArchiveBuilder, ArchiveConfig}; use super::linker::Linker; use super::command::Command; @@ -20,17 +18,14 @@ use rustc::session::config::{self, NoDebugInfo, OutputFilenames, OutputType, Pri use rustc::session::filesearch; use rustc::session::search_paths::PathKind; use rustc::session::Session; -use rustc::middle::cstore::{LinkMeta, NativeLibrary, LibSource, NativeLibraryKind}; +use rustc::middle::cstore::{NativeLibrary, LibSource, NativeLibraryKind}; use rustc::middle::dependency_format::Linkage; use {CrateTranslation, CrateInfo}; use rustc::util::common::time; use rustc::util::fs::fix_windows_verbatim_for_gcc; -use rustc::dep_graph::{DepKind, DepNode}; use rustc::hir::def_id::CrateNum; -use rustc::hir::svh::Svh; use rustc_back::tempdir::TempDir; use rustc_back::{PanicStrategy, RelroLevel}; -use rustc_incremental::IncrementalHashesMap; use context::get_reloc_model; use llvm; @@ -89,17 +84,9 @@ pub const RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET: usize = pub const RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET: usize = RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET + 8; -pub use self::rustc_trans_utils::link::{find_crate_name, filename_for_input, - default_output_for_target, invalid_output_for_target}; - -pub fn build_link_meta(incremental_hashes_map: &IncrementalHashesMap) -> LinkMeta { - let krate_dep_node = &DepNode::new_no_params(DepKind::Krate); - let r = LinkMeta { - crate_hash: Svh::new(incremental_hashes_map[krate_dep_node].to_smaller_hash()), - }; - info!("{:?}", r); - return r; -} +pub use rustc_trans_utils::link::{find_crate_name, filename_for_input, default_output_for_target, + invalid_output_for_target, build_link_meta, out_filename, + check_file_is_writeable}; // The third parameter is for env vars, used on windows to set up the // path for MSVC to find its DLLs, and gcc to find its bundled @@ -138,7 +125,7 @@ pub fn get_linker(sess: &Session) -> (String, Command, Vec<(OsString, OsString)> #[cfg(windows)] pub fn msvc_link_exe_cmd(sess: &Session) -> (Command, Vec<(OsString, OsString)>) { - use gcc::windows_registry; + use cc::windows_registry; let target = &sess.opts.target_triple; let tool = windows_registry::find_tool(target, "link.exe"); @@ -227,13 +214,6 @@ pub fn link_binary(sess: &Session, out_filenames } -fn is_writeable(p: &Path) -> bool { - match p.metadata() { - Err(..) => true, - Ok(m) => !m.permissions().readonly() - } -} - fn filename_for_metadata(sess: &Session, crate_name: &str, outputs: &OutputFilenames) -> PathBuf { let out_filename = outputs.single_output_file.clone() .unwrap_or(outputs @@ -297,32 +277,6 @@ pub fn ignored_for_lto(info: &CrateInfo, cnum: CrateNum) -> bool { info.is_no_builtins.contains(&cnum) || info.compiler_builtins == Some(cnum) } -fn out_filename(sess: &Session, - crate_type: config::CrateType, - outputs: &OutputFilenames, - crate_name: &str) - -> PathBuf { - let default_filename = filename_for_input(sess, crate_type, crate_name, outputs); - let out_filename = outputs.outputs.get(&OutputType::Exe) - .and_then(|s| s.to_owned()) - .or_else(|| outputs.single_output_file.clone()) - .unwrap_or(default_filename); - - check_file_is_writeable(&out_filename, sess); - - out_filename -} - -// Make sure files are writeable. Mac, FreeBSD, and Windows system linkers -// check this already -- however, the Linux linker will happily overwrite a -// read-only file. We should be consistent. -fn check_file_is_writeable(file: &Path, sess: &Session) { - if !is_writeable(file) { - sess.fatal(&format!("output file {} is not writeable -- check its \ - permissions", file.display())); - } -} - fn link_binary_output(sess: &Session, trans: &CrateTranslation, crate_type: config::CrateType, @@ -555,7 +509,7 @@ fn link_rlib<'a>(sess: &'a Session, // of when we do and don't keep .#module-name#.bc files around. let user_wants_numbered_bitcode = sess.opts.output_types.contains_key(&OutputType::Bitcode) && - sess.opts.cg.codegen_units > 1; + sess.opts.codegen_units > 1; if !sess.opts.cg.save_temps && !user_wants_numbered_bitcode { remove(sess, &bc_filename); } diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index ef6bf2504f3..6b980a37ac7 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -939,10 +939,10 @@ fn produce_final_output_artifacts(sess: &Session, let needs_crate_object = crate_output.outputs.contains_key(&OutputType::Exe); let keep_numbered_bitcode = needs_crate_bitcode || - (user_wants_bitcode && sess.opts.cg.codegen_units > 1); + (user_wants_bitcode && sess.opts.codegen_units > 1); let keep_numbered_objects = needs_crate_object || - (user_wants_objects && sess.opts.cg.codegen_units > 1); + (user_wants_objects && sess.opts.codegen_units > 1); for module in compiled_modules.modules.iter() { let module_name = Some(&module.name[..]); @@ -1520,6 +1520,11 @@ fn start_executing_work(tcx: TyCtxt, total_llvm_time); } + // Regardless of what order these modules completed in, report them to + // the backend in the same order every time to ensure that we're handing + // out deterministic results. + compiled_modules.sort_by(|a, b| a.name.cmp(&b.name)); + let compiled_metadata_module = compiled_metadata_module .expect("Metadata module not compiled?"); @@ -1853,7 +1858,7 @@ impl OngoingCrateTranslation { // FIXME: time_llvm_passes support - does this use a global context or // something? - if sess.opts.cg.codegen_units == 1 && sess.time_llvm_passes() { + if sess.opts.codegen_units == 1 && sess.time_llvm_passes() { unsafe { llvm::LLVMRustPrintPassTimings(); } } diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index ba15f3522ac..774acc81343 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -41,12 +41,12 @@ use rustc::middle::trans::{Linkage, Visibility, Stats}; use rustc::middle::cstore::{EncodedMetadata, EncodedMetadataHashes}; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::maps::Providers; +use rustc::dep_graph::{DepNode, DepKind}; use rustc::middle::cstore::{self, LinkMeta, LinkagePreference}; -use rustc::hir::map as hir_map; use rustc::util::common::{time, print_time_passes_entry}; use rustc::session::config::{self, NoDebugInfo}; use rustc::session::Session; -use rustc_incremental::{self, IncrementalHashesMap}; +use rustc_incremental; use abi; use allocator; use mir::lvalue::LvalueRef; @@ -94,6 +94,8 @@ use syntax::ast; use mir::lvalue::Alignment; +pub use rustc_trans_utils::{find_exported_symbols, check_for_rustc_errors_attr}; + pub struct StatRecorder<'a, 'tcx: 'a> { ccx: &'a CrateContext<'a, 'tcx>, name: Option<String>, @@ -659,20 +661,6 @@ pub fn set_link_section(ccx: &CrateContext, } } -// check for the #[rustc_error] annotation, which forces an -// error in trans. This is used to write compile-fail tests -// that actually test that compilation succeeds without -// reporting an error. -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); - - if tcx.has_attr(main_def_id, "rustc_error") { - tcx.sess.span_fatal(span, "compilation successful"); - } - } -} - /// Create the `main` function which will initialize the rust runtime and call /// users main function. fn maybe_create_entry_wrapper(ccx: &CrateContext) { @@ -884,63 +872,16 @@ fn iter_globals(llmod: llvm::ModuleRef) -> ValueIter { } } -/// The context provided lists a set of reachable ids as calculated by -/// middle::reachable, but this contains far more ids and symbols than we're -/// actually exposing from the object file. This function will filter the set in -/// the context to the set of ids which correspond to symbols that are exposed -/// from the object file being generated. -/// -/// This list is later used by linkers to determine the set of symbols needed to -/// be exposed from a dynamic library and it's also encoded into the metadata. -pub fn find_exported_symbols(tcx: TyCtxt) -> NodeSet { - tcx.reachable_set(LOCAL_CRATE).0.iter().cloned().filter(|&id| { - // Next, we want to ignore some FFI functions that are not exposed from - // this crate. Reachable FFI functions can be lumped into two - // categories: - // - // 1. Those that are included statically via a static library - // 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 - // needs to be passed on to the linker and encoded in the metadata. - // - // 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(id) { - hir_map::NodeForeignItem(..) => { - let def_id = tcx.hir.local_def_id(id); - tcx.is_statically_included_foreign_item(def_id) - } - - // Only consider nodes that actually have exported symbols. - hir_map::NodeItem(&hir::Item { - node: hir::ItemStatic(..), .. }) | - hir_map::NodeItem(&hir::Item { - node: hir::ItemFn(..), .. }) | - hir_map::NodeImplItem(&hir::ImplItem { - node: hir::ImplItemKind::Method(..), .. }) => { - let def_id = tcx.hir.local_def_id(id); - let generics = tcx.generics_of(def_id); - let attributes = tcx.get_attrs(def_id); - (generics.parent_types == 0 && generics.types.is_empty()) && - // Functions marked with #[inline] are only ever translated - // with "internal" linkage and are never exported. - !attr::requests_inline(&attributes) - } - - _ => false - } - }).collect() -} - pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - incremental_hashes_map: IncrementalHashesMap, rx: mpsc::Receiver<Box<Any + Send>>) -> OngoingCrateTranslation { + check_for_rustc_errors_attr(tcx); - let link_meta = link::build_link_meta(&incremental_hashes_map); + + let crate_hash = tcx.dep_graph + .fingerprint_of(&DepNode::new_no_params(DepKind::Krate)); + let link_meta = link::build_link_meta(crate_hash); let exported_symbol_node_ids = find_exported_symbols(tcx); let shared_ccx = SharedCrateContext::new(tcx); @@ -980,7 +921,6 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ongoing_translation.translation_finished(tcx); assert_and_save_dep_graph(tcx, - incremental_hashes_map, metadata_incr_hashes, link_meta); @@ -1113,7 +1053,6 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ongoing_translation.check_for_errors(tcx.sess); assert_and_save_dep_graph(tcx, - incremental_hashes_map, metadata_incr_hashes, link_meta); ongoing_translation @@ -1124,7 +1063,6 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, thread_local!(static DISPOSITIONS: RefCell<Vec<(String, Disposition)>> = Default::default()); fn assert_and_save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - incremental_hashes_map: IncrementalHashesMap, metadata_incr_hashes: EncodedMetadataHashes, link_meta: LinkMeta) { time(tcx.sess.time_passes(), @@ -1134,7 +1072,6 @@ fn assert_and_save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, time(tcx.sess.time_passes(), "serialize dep graph", || rustc_incremental::save_dep_graph(tcx, - incremental_hashes_map, &metadata_incr_hashes, link_meta.crate_hash)); } @@ -1225,7 +1162,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>( let strategy = if tcx.sess.opts.debugging_opts.incremental.is_some() { PartitioningStrategy::PerModule } else { - PartitioningStrategy::FixedUnitCount(tcx.sess.opts.cg.codegen_units) + PartitioningStrategy::FixedUnitCount(tcx.sess.opts.codegen_units) }; let codegen_units = time(time_passes, "codegen unit partitioning", || { @@ -1238,7 +1175,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>( .collect::<Vec<_>>() }); - assert!(tcx.sess.opts.cg.codegen_units == codegen_units.len() || + assert!(tcx.sess.opts.codegen_units == codegen_units.len() || tcx.sess.opts.debugging_opts.incremental.is_some()); let translation_items: DefIdSet = items.iter().filter_map(|trans_item| { diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 57e9f1d091b..796dfd4417c 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -50,6 +50,7 @@ extern crate rustc_incremental; extern crate rustc_llvm as llvm; extern crate rustc_platform_intrinsics as intrinsics; extern crate rustc_const_math; +extern crate rustc_trans_utils; extern crate rustc_demangle; extern crate jobserver; extern crate num_cpus; @@ -60,7 +61,7 @@ extern crate syntax_pos; extern crate rustc_errors as errors; extern crate serialize; #[cfg(windows)] -extern crate gcc; // Used to locate MSVC, not gcc :) +extern crate cc; // Used to locate MSVC pub use base::trans_crate; @@ -137,6 +138,63 @@ mod type_; mod type_of; mod value; +use std::sync::mpsc; +use std::any::Any; +use rustc::ty::{self, TyCtxt}; +use rustc::session::Session; +use rustc::session::config::OutputFilenames; +use rustc::middle::cstore::MetadataLoader; +use rustc::dep_graph::DepGraph; + +pub struct LlvmTransCrate(()); + +impl LlvmTransCrate { + pub fn new() -> Self { + LlvmTransCrate(()) + } +} + +impl rustc_trans_utils::trans_crate::TransCrate for LlvmTransCrate { + type MetadataLoader = metadata::LlvmMetadataLoader; + type OngoingCrateTranslation = back::write::OngoingCrateTranslation; + type TranslatedCrate = CrateTranslation; + + fn metadata_loader() -> Box<MetadataLoader> { + box metadata::LlvmMetadataLoader + } + + fn provide_local(providers: &mut ty::maps::Providers) { + provide_local(providers); + } + + fn provide_extern(providers: &mut ty::maps::Providers) { + provide_extern(providers); + } + + fn trans_crate<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + rx: mpsc::Receiver<Box<Any + Send>> + ) -> Self::OngoingCrateTranslation { + base::trans_crate(tcx, rx) + } + + fn join_trans( + trans: Self::OngoingCrateTranslation, + sess: &Session, + dep_graph: &DepGraph + ) -> Self::TranslatedCrate { + trans.join(sess, dep_graph) + } + + fn link_binary(sess: &Session, trans: &Self::TranslatedCrate, outputs: &OutputFilenames) { + back::link::link_binary(sess, trans, outputs, &trans.crate_name.as_str()); + } + + fn dump_incremental_data(trans: &Self::TranslatedCrate) { + back::write::dump_incremental_data(trans); + } +} + pub struct ModuleTranslation { /// The name of the module. When the crate may be saved between /// compilations, incremental compilation requires that name be diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs index 2be7a81b1cd..62ccd55b483 100644 --- a/src/librustc_trans/monomorphize.rs +++ b/src/librustc_trans/monomorphize.rs @@ -112,7 +112,8 @@ fn resolve_associated_item<'a, 'tcx>( def_id, trait_id, rcvr_substs); let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs); - let vtbl = tcx.trans_fulfill_obligation(DUMMY_SP, ty::Binder(trait_ref)); + let vtbl = tcx.trans_fulfill_obligation( + DUMMY_SP, ty::ParamEnv::empty(traits::Reveal::All), ty::Binder(trait_ref)); // Now that we know which impl is being used, we can dispatch to // the actual function: @@ -226,7 +227,8 @@ pub fn custom_coerce_unsize_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, substs: tcx.mk_substs_trait(source_ty, &[target_ty]) }); - match tcx.trans_fulfill_obligation(DUMMY_SP, trait_ref) { + match tcx.trans_fulfill_obligation( + DUMMY_SP, ty::ParamEnv::empty(traits::Reveal::All), trait_ref) { traits::VtableImpl(traits::VtableImplData { impl_def_id, .. }) => { tcx.coerce_unsized_info(impl_def_id).custom_kind.unwrap() } diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs index 9b617c35d93..7c29186f465 100644 --- a/src/librustc_trans/partitioning.rs +++ b/src/librustc_trans/partitioning.rs @@ -108,11 +108,12 @@ use rustc::dep_graph::{DepNode, WorkProductId}; use rustc::hir::def_id::DefId; use rustc::hir::map::DefPathData; use rustc::middle::trans::{Linkage, Visibility}; +use rustc::ich::Fingerprint; use rustc::session::config::NUMBERED_CODEGEN_UNIT_MARKER; use rustc::ty::{self, TyCtxt, InstanceDef}; use rustc::ty::item_path::characteristic_def_id_of_type; use rustc::util::nodemap::{FxHashMap, FxHashSet}; -use rustc_incremental::IchHasher; +use rustc_data_structures::stable_hasher::StableHasher; use std::collections::hash_map::Entry; use std::hash::Hash; use syntax::ast::NodeId; @@ -155,7 +156,7 @@ pub trait CodegenUnitExt<'tcx> { } fn compute_symbol_name_hash<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> u64 { - let mut state = IchHasher::new(); + let mut state: StableHasher<Fingerprint> = StableHasher::new(); let all_items = self.items_in_deterministic_order(tcx); for (item, (linkage, visibility)) in all_items { let symbol_name = item.symbol_name(tcx); diff --git a/src/librustc_trans_utils/Cargo.toml b/src/librustc_trans_utils/Cargo.toml index f026d4fcbc2..bedbea00688 100644 --- a/src/librustc_trans_utils/Cargo.toml +++ b/src/librustc_trans_utils/Cargo.toml @@ -10,6 +10,12 @@ crate-type = ["dylib"] test = false [dependencies] -rustc = { path = "../librustc" } +ar = "0.3.0" +flate2 = "0.2" +owning_ref = "0.3.3" +log = "0.3" + syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } +rustc = { path = "../librustc" } +rustc_back = { path = "../librustc_back" } diff --git a/src/librustc_trans_utils/lib.rs b/src/librustc_trans_utils/lib.rs index 5e8abe59ad9..6873befd2bf 100644 --- a/src/librustc_trans_utils/lib.rs +++ b/src/librustc_trans_utils/lib.rs @@ -29,8 +29,89 @@ #![cfg_attr(stage0, feature(const_fn))] +extern crate ar; +extern crate flate2; +extern crate owning_ref; +#[macro_use] +extern crate log; + +#[macro_use] extern crate rustc; +extern crate rustc_back; extern crate syntax; extern crate syntax_pos; +use rustc::ty::TyCtxt; +use rustc::hir; +use rustc::hir::def_id::LOCAL_CRATE; +use rustc::hir::map as hir_map; +use rustc::util::nodemap::NodeSet; + +use syntax::attr; + pub mod link; +pub mod trans_crate; + +/// check for the #[rustc_error] annotation, which forces an +/// error in trans. This is used to write compile-fail tests +/// that actually test that compilation succeeds without +/// 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); + + if tcx.has_attr(main_def_id, "rustc_error") { + tcx.sess.span_fatal(span, "compilation successful"); + } + } +} + +/// The context provided lists a set of reachable ids as calculated by +/// middle::reachable, but this contains far more ids and symbols than we're +/// actually exposing from the object file. This function will filter the set in +/// the context to the set of ids which correspond to symbols that are exposed +/// from the object file being generated. +/// +/// This list is later used by linkers to determine the set of symbols needed to +/// be exposed from a dynamic library and it's also encoded into the metadata. +pub fn find_exported_symbols(tcx: TyCtxt) -> NodeSet { + tcx.reachable_set(LOCAL_CRATE).0.iter().cloned().filter(|&id| { + // Next, we want to ignore some FFI functions that are not exposed from + // this crate. Reachable FFI functions can be lumped into two + // categories: + // + // 1. Those that are included statically via a static library + // 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 + // needs to be passed on to the linker and encoded in the metadata. + // + // 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(id) { + hir_map::NodeForeignItem(..) => { + let def_id = tcx.hir.local_def_id(id); + tcx.is_statically_included_foreign_item(def_id) + } + + // Only consider nodes that actually have exported symbols. + hir_map::NodeItem(&hir::Item { + node: hir::ItemStatic(..), .. }) | + hir_map::NodeItem(&hir::Item { + node: hir::ItemFn(..), .. }) | + hir_map::NodeImplItem(&hir::ImplItem { + node: hir::ImplItemKind::Method(..), .. }) => { + let def_id = tcx.hir.local_def_id(id); + let generics = tcx.generics_of(def_id); + let attributes = tcx.get_attrs(def_id); + (generics.parent_types == 0 && generics.types.is_empty()) && + // Functions marked with #[inline] are only ever translated + // with "internal" linkage and are never exported. + !attr::requests_inline(&attributes) + } + + _ => false + } + }).collect() +} diff --git a/src/librustc_trans_utils/link.rs b/src/librustc_trans_utils/link.rs index aa8637fabe8..47484488fb8 100644 --- a/src/librustc_trans_utils/link.rs +++ b/src/librustc_trans_utils/link.rs @@ -8,13 +8,56 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use rustc::ich::Fingerprint; use rustc::session::config::{self, OutputFilenames, Input, OutputType}; use rustc::session::Session; -use rustc::middle::cstore; -use std::path::PathBuf; +use rustc::middle::cstore::{self, LinkMeta}; +use rustc::hir::svh::Svh; +use std::path::{Path, PathBuf}; use syntax::ast; use syntax_pos::Span; +pub fn out_filename(sess: &Session, + crate_type: config::CrateType, + outputs: &OutputFilenames, + crate_name: &str) + -> PathBuf { + let default_filename = filename_for_input(sess, crate_type, crate_name, outputs); + let out_filename = outputs.outputs.get(&OutputType::Exe) + .and_then(|s| s.to_owned()) + .or_else(|| outputs.single_output_file.clone()) + .unwrap_or(default_filename); + + check_file_is_writeable(&out_filename, sess); + + out_filename +} + +// Make sure files are writeable. Mac, FreeBSD, and Windows system linkers +// check this already -- however, the Linux linker will happily overwrite a +// read-only file. We should be consistent. +pub fn check_file_is_writeable(file: &Path, sess: &Session) { + if !is_writeable(file) { + sess.fatal(&format!("output file {} is not writeable -- check its \ + permissions", file.display())); + } +} + +fn is_writeable(p: &Path) -> bool { + match p.metadata() { + Err(..) => true, + Ok(m) => !m.permissions().readonly() + } +} + +pub fn build_link_meta(crate_hash: Fingerprint) -> LinkMeta { + let r = LinkMeta { + crate_hash: Svh::new(crate_hash.to_smaller_hash()), + }; + info!("{:?}", r); + return r; +} + pub fn find_crate_name(sess: Option<&Session>, attrs: &[ast::Attribute], input: &Input) -> String { diff --git a/src/librustc_trans_utils/trans_crate.rs b/src/librustc_trans_utils/trans_crate.rs new file mode 100644 index 00000000000..f51a463fcc2 --- /dev/null +++ b/src/librustc_trans_utils/trans_crate.rs @@ -0,0 +1,249 @@ +// Copyright 2014-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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The Rust compiler. +//! +//! # Note +//! +//! This API is completely unstable and subject to change. + +#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", + html_favicon_url = "https://doc.rust-lang.org/favicon.ico", + html_root_url = "https://doc.rust-lang.org/nightly/")] +#![deny(warnings)] + +#![feature(box_syntax)] + +use std::any::Any; +use std::io::prelude::*; +use std::io::{self, Cursor}; +use std::fs::File; +use std::path::Path; +use std::sync::mpsc; + +use owning_ref::{ErasedBoxRef, OwningRef}; +use ar::{Archive, Builder, Header}; +use flate2::Compression; +use flate2::write::DeflateEncoder; + +use syntax::symbol::Symbol; +use rustc::hir::def_id::LOCAL_CRATE; +use rustc::session::Session; +use rustc::session::config::{CrateType, OutputFilenames}; +use rustc::ty::TyCtxt; +use rustc::ty::maps::Providers; +use rustc::middle::cstore::EncodedMetadata; +use rustc::middle::cstore::MetadataLoader as MetadataLoaderTrait; +use rustc::dep_graph::{DepGraph, DepNode, DepKind}; +use rustc_back::target::Target; +use link::{build_link_meta, out_filename}; + +pub trait TransCrate { + type MetadataLoader: MetadataLoaderTrait; + type OngoingCrateTranslation; + type TranslatedCrate; + + fn metadata_loader() -> Box<MetadataLoaderTrait>; + fn provide_local(_providers: &mut Providers); + fn provide_extern(_providers: &mut Providers); + fn trans_crate<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + rx: mpsc::Receiver<Box<Any + Send>> + ) -> Self::OngoingCrateTranslation; + fn join_trans( + trans: Self::OngoingCrateTranslation, + sess: &Session, + dep_graph: &DepGraph + ) -> Self::TranslatedCrate; + fn link_binary(sess: &Session, trans: &Self::TranslatedCrate, outputs: &OutputFilenames); + fn dump_incremental_data(trans: &Self::TranslatedCrate); +} + +pub struct DummyTransCrate; + +impl TransCrate for DummyTransCrate { + type MetadataLoader = DummyMetadataLoader; + type OngoingCrateTranslation = (); + type TranslatedCrate = (); + + fn metadata_loader() -> Box<MetadataLoaderTrait> { + box DummyMetadataLoader(()) + } + + fn provide_local(_providers: &mut Providers) { + bug!("DummyTransCrate::provide_local"); + } + + fn provide_extern(_providers: &mut Providers) { + bug!("DummyTransCrate::provide_extern"); + } + + fn trans_crate<'a, 'tcx>( + _tcx: TyCtxt<'a, 'tcx, 'tcx>, + _rx: mpsc::Receiver<Box<Any + Send>> + ) -> Self::OngoingCrateTranslation { + bug!("DummyTransCrate::trans_crate"); + } + + fn join_trans( + _trans: Self::OngoingCrateTranslation, + _sess: &Session, + _dep_graph: &DepGraph + ) -> Self::TranslatedCrate { + bug!("DummyTransCrate::join_trans"); + } + + fn link_binary(_sess: &Session, _trans: &Self::TranslatedCrate, _outputs: &OutputFilenames) { + bug!("DummyTransCrate::link_binary"); + } + + fn dump_incremental_data(_trans: &Self::TranslatedCrate) { + bug!("DummyTransCrate::dump_incremental_data"); + } +} + +pub struct DummyMetadataLoader(()); + +impl MetadataLoaderTrait for DummyMetadataLoader { + fn get_rlib_metadata( + &self, + _target: &Target, + _filename: &Path + ) -> Result<ErasedBoxRef<[u8]>, String> { + bug!("DummyMetadataLoader::get_rlib_metadata"); + } + + fn get_dylib_metadata( + &self, + _target: &Target, + _filename: &Path + ) -> Result<ErasedBoxRef<[u8]>, String> { + bug!("DummyMetadataLoader::get_dylib_metadata"); + } +} + +pub struct NoLlvmMetadataLoader; + +impl MetadataLoaderTrait for NoLlvmMetadataLoader { + fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<ErasedBoxRef<[u8]>, String> { + let file = File::open(filename) + .map_err(|e| format!("metadata file open err: {:?}", e))?; + let mut archive = Archive::new(file); + + while let Some(entry_result) = archive.next_entry() { + let mut entry = entry_result + .map_err(|e| format!("metadata section read err: {:?}", e))?; + if entry.header().identifier() == "rust.metadata.bin" { + let mut buf = Vec::new(); + io::copy(&mut entry, &mut buf).unwrap(); + let buf: OwningRef<Vec<u8>, [u8]> = OwningRef::new(buf).into(); + return Ok(buf.map_owner_box().erase_owner()); + } + } + + Err("Couldnt find metadata section".to_string()) + } + + fn get_dylib_metadata( + &self, + _target: &Target, + _filename: &Path, + ) -> Result<ErasedBoxRef<[u8]>, String> { + // FIXME: Support reading dylibs from llvm enabled rustc + self.get_rlib_metadata(_target, _filename) + } +} + +pub struct MetadataOnlyTransCrate; +pub struct OngoingCrateTranslation { + metadata: EncodedMetadata, + metadata_version: Vec<u8>, + crate_name: Symbol, +} +pub struct TranslatedCrate(OngoingCrateTranslation); + +impl MetadataOnlyTransCrate { + #[allow(dead_code)] + pub fn new() -> Self { + MetadataOnlyTransCrate + } +} + +impl TransCrate for MetadataOnlyTransCrate { + type MetadataLoader = NoLlvmMetadataLoader; + type OngoingCrateTranslation = OngoingCrateTranslation; + type TranslatedCrate = TranslatedCrate; + + fn metadata_loader() -> Box<MetadataLoaderTrait> { + box NoLlvmMetadataLoader + } + + fn provide_local(_providers: &mut Providers) {} + fn provide_extern(_providers: &mut Providers) {} + + fn trans_crate<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + _rx: mpsc::Receiver<Box<Any + Send>> + ) -> Self::OngoingCrateTranslation { + ::check_for_rustc_errors_attr(tcx); + let _ = tcx.link_args(LOCAL_CRATE); + let _ = tcx.native_libraries(LOCAL_CRATE); + tcx.sess.abort_if_errors(); + + let crate_hash = tcx.dep_graph + .fingerprint_of(&DepNode::new_no_params(DepKind::Krate)); + let link_meta = build_link_meta(crate_hash); + let exported_symbols = ::find_exported_symbols(tcx); + let (metadata, _hashes) = tcx.encode_metadata(&link_meta, &exported_symbols); + + OngoingCrateTranslation { + metadata: metadata, + metadata_version: tcx.metadata_encoding_version().to_vec(), + crate_name: tcx.crate_name(LOCAL_CRATE), + } + } + + fn join_trans( + trans: Self::OngoingCrateTranslation, + _sess: &Session, + _dep_graph: &DepGraph, + ) -> Self::TranslatedCrate { + TranslatedCrate(trans) + } + + fn link_binary(sess: &Session, trans: &Self::TranslatedCrate, outputs: &OutputFilenames) { + for &crate_type in sess.opts.crate_types.iter() { + if crate_type != CrateType::CrateTypeRlib && crate_type != CrateType::CrateTypeDylib { + continue; + } + let output_name = + out_filename(sess, crate_type, &outputs, &trans.0.crate_name.as_str()); + let mut compressed = trans.0.metadata_version.clone(); + let metadata = if crate_type == CrateType::CrateTypeDylib { + DeflateEncoder::new(&mut compressed, Compression::Fast) + .write_all(&trans.0.metadata.raw_data) + .unwrap(); + &compressed + } else { + &trans.0.metadata.raw_data + }; + let mut builder = Builder::new(File::create(&output_name).unwrap()); + let header = Header::new("rust.metadata.bin".to_string(), metadata.len() as u64); + builder.append(&header, Cursor::new(metadata)).unwrap(); + } + + if !sess.opts.crate_types.contains(&CrateType::CrateTypeRlib) + && !sess.opts.crate_types.contains(&CrateType::CrateTypeDylib) { + sess.fatal("Executables are not supported by the metadata-only backend."); + } + } + + fn dump_incremental_data(_trans: &Self::TranslatedCrate) {} +} diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 5256bb22781..54fd070e93c 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -76,6 +76,8 @@ pub trait AstConv<'gcx, 'tcx> { /// used to help suppress derived errors typeck might otherwise /// report. fn set_tainted_by_errors(&self); + + fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, span: Span); } struct ConvertedBinding<'tcx> { @@ -155,11 +157,16 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { item_segment: &hir::PathSegment) -> &'tcx Substs<'tcx> { + let (substs, assoc_bindings) = - self.create_substs_for_ast_path(span, - def_id, - &item_segment.parameters, - None); + item_segment.with_parameters(|parameters| { + self.create_substs_for_ast_path( + span, + def_id, + parameters, + item_segment.infer_types, + None) + }); assoc_bindings.first().map(|b| self.prohibit_projection(b.span)); @@ -175,6 +182,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { span: Span, def_id: DefId, parameters: &hir::PathParameters, + infer_types: bool, self_ty: Option<Ty<'tcx>>) -> (&'tcx Substs<'tcx>, Vec<ConvertedBinding<'tcx>>) { @@ -202,7 +210,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // Check the number of type parameters supplied by the user. let ty_param_defs = &decl_generics.types[self_ty.is_some() as usize..]; - if !parameters.infer_types || num_types_provided > ty_param_defs.len() { + if !infer_types || num_types_provided > ty_param_defs.len() { check_type_argument_count(tcx, span, num_types_provided, ty_param_defs); } @@ -238,7 +246,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { if i < num_types_provided { // A provided type parameter. self.ast_ty_to_ty(¶meters.types[i]) - } else if parameters.infer_types { + } else if infer_types { // No type parameters were provided, we can infer all. let ty_var = if !default_needs_object_self(def) { self.ty_infer_for_def(def, substs, span) @@ -388,7 +396,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let trait_def = self.tcx().trait_def(trait_def_id); if !self.tcx().sess.features.borrow().unboxed_closures && - trait_segment.parameters.parenthesized != trait_def.paren_sugar { + trait_segment.with_parameters(|p| p.parenthesized) != trait_def.paren_sugar { // For now, require that parenthetical notation be used only with `Fn()` etc. let msg = if trait_def.paren_sugar { "the precise format of `Fn`-family traits' type parameters is subject to change. \ @@ -400,10 +408,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { span, GateIssue::Language, msg); } - self.create_substs_for_ast_path(span, - trait_def_id, - &trait_segment.parameters, - Some(self_ty)) + trait_segment.with_parameters(|parameters| { + self.create_substs_for_ast_path(span, + trait_def_id, + parameters, + trait_segment.infer_types, + Some(self_ty)) + }) } fn trait_defines_associated_type_named(&self, @@ -874,25 +885,27 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { pub fn prohibit_type_params(&self, segments: &[hir::PathSegment]) { for segment in segments { - for typ in &segment.parameters.types { - struct_span_err!(self.tcx().sess, typ.span, E0109, - "type parameters are not allowed on this type") - .span_label(typ.span, "type parameter not allowed") - .emit(); - break; - } - for lifetime in &segment.parameters.lifetimes { - struct_span_err!(self.tcx().sess, lifetime.span, E0110, - "lifetime parameters are not allowed on this type") - .span_label(lifetime.span, - "lifetime parameter not allowed on this type") - .emit(); - break; - } - for binding in &segment.parameters.bindings { - self.prohibit_projection(binding.span); - break; - } + segment.with_parameters(|parameters| { + for typ in ¶meters.types { + struct_span_err!(self.tcx().sess, typ.span, E0109, + "type parameters are not allowed on this type") + .span_label(typ.span, "type parameter not allowed") + .emit(); + break; + } + for lifetime in ¶meters.lifetimes { + struct_span_err!(self.tcx().sess, lifetime.span, E0110, + "lifetime parameters are not allowed on this type") + .span_label(lifetime.span, + "lifetime parameter not allowed on this type") + .emit(); + break; + } + for binding in ¶meters.bindings { + self.prohibit_projection(binding.span); + break; + } + }) } } @@ -975,6 +988,16 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } } Def::Err => { + for segment in &path.segments { + segment.with_parameters(|parameters| { + for ty in ¶meters.types { + self.ast_ty_to_ty(ty); + } + for binding in ¶meters.bindings { + self.ast_ty_to_ty(&binding.ty); + } + }); + } self.set_tainted_by_errors(); return self.tcx().types.err; } @@ -1115,6 +1138,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } }; + self.record_ty(ast_ty.hir_id, result_ty, ast_ty.span); result_ty } @@ -1124,8 +1148,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { -> Ty<'tcx> { match ty.node { - hir::TyInfer if expected_ty.is_some() => expected_ty.unwrap(), - hir::TyInfer => self.ty_infer(ty.span), + hir::TyInfer if expected_ty.is_some() => { + self.record_ty(ty.hir_id, expected_ty.unwrap(), ty.span); + expected_ty.unwrap() + } _ => self.ast_ty_to_ty(ty), } } @@ -1214,19 +1240,22 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let expected_ret_ty = expected_sig.as_ref().map(|e| e.output()); - let is_infer = match decl.output { - hir::Return(ref output) if output.node == hir::TyInfer => true, - hir::DefaultReturn(..) => true, - _ => false - }; - let output_ty = match decl.output { - _ if is_infer && expected_ret_ty.is_some() => - expected_ret_ty.unwrap(), - _ if is_infer => self.ty_infer(decl.output.span()), - hir::Return(ref output) => - self.ast_ty_to_ty(&output), - hir::DefaultReturn(..) => bug!(), + hir::Return(ref output) => { + if let (&hir::TyInfer, Some(expected_ret_ty)) = (&output.node, expected_ret_ty) { + self.record_ty(output.hir_id, expected_ret_ty, output.span); + expected_ret_ty + } else { + self.ast_ty_to_ty(&output) + } + } + hir::DefaultReturn(span) => { + if let Some(expected_ret_ty) = expected_ret_ty { + expected_ret_ty + } else { + self.ty_infer(span) + } + } }; debug!("ty_of_closure: output_ty={:?}", output_ty); @@ -1298,15 +1327,16 @@ fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, if Some(trait_did) == tcx.lang_items().send_trait() || Some(trait_did) == tcx.lang_items().sync_trait() { let segments = &bound.trait_ref.path.segments; - let parameters = &segments[segments.len() - 1].parameters; - if !parameters.types.is_empty() { - check_type_argument_count(tcx, bound.trait_ref.path.span, - parameters.types.len(), &[]); - } - if !parameters.lifetimes.is_empty() { - report_lifetime_number_error(tcx, bound.trait_ref.path.span, - parameters.lifetimes.len(), 0); - } + segments[segments.len() - 1].with_parameters(|parameters| { + if !parameters.types.is_empty() { + check_type_argument_count(tcx, bound.trait_ref.path.span, + parameters.types.len(), &[]); + } + if !parameters.lifetimes.is_empty() { + report_lifetime_number_error(tcx, bound.trait_ref.path.span, + parameters.lifetimes.len(), 0); + } + }); true } else { false diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index cbf58209d05..d942b2d1230 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -787,11 +787,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { for field in variant.fields .iter() .filter(|field| !used_fields.contains_key(&field.name)) { - struct_span_err!(tcx.sess, span, E0027, - "pattern does not mention field `{}`", - field.name) - .span_label(span, format!("missing field `{}`", field.name)) - .emit(); + let mut diag = struct_span_err!(tcx.sess, span, E0027, + "pattern does not mention field `{}`", + field.name); + diag.span_label(span, format!("missing field `{}`", field.name)); + if variant.ctor_kind == CtorKind::Fn { + diag.note("trying to match a tuple variant with a struct variant pattern"); + } + diag.emit(); } } } diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index cfcdbcc1195..94422f93e59 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -187,7 +187,11 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { } // Consider coercing the subtype to a DST - let unsize = self.coerce_unsized(a, b); + // + // NOTE: this is wrapped in a `commit_if_ok` because it creates + // a "spurious" type variable, and we don't want to have that + // type variable in memory if the coercion fails. + let unsize = self.commit_if_ok(|_| self.coerce_unsized(a, b)); if unsize.is_ok() { debug!("coerce: unsize successful"); return unsize; diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 65900dc3f36..7110a1ba81d 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -261,6 +261,39 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } None } + (_, &ty::TyRef(_, checked)) => { + // We have `&T`, check if what was expected was `T`. If so, + // we may want to suggest adding a `*`, or removing + // a `&`. + // + // (But, also check check the `expn_info()` to see if this is + // a macro; if so, it's hard to extract the text and make a good + // suggestion, so don't bother.) + if self.infcx.can_sub(self.param_env, checked.ty, &expected).is_ok() && + expr.span.ctxt().outer().expn_info().is_none() { + match expr.node { + // Maybe remove `&`? + hir::ExprAddrOf(_, ref expr) => { + if let Ok(code) = self.tcx.sess.codemap().span_to_snippet(expr.span) { + return Some(format!("try with `{}`", code)); + } + } + + // Maybe add `*`? Only if `T: Copy`. + _ => { + if !self.infcx.type_moves_by_default(self.param_env, + checked.ty, + expr.span) { + let sp = self.sess().codemap().call_span_if_macro(expr.span); + if let Ok(code) = self.tcx.sess.codemap().span_to_snippet(sp) { + return Some(format!("try with `*{}`", code)); + } + } + }, + } + } + None + } _ => None, } } diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 852134bbee3..a9830dd5dde 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -300,7 +300,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { if i < parent_substs.len() { parent_substs.region_at(i) } else if let Some(lifetime) - = provided.lifetimes.get(i - parent_substs.len()) { + = provided.as_ref().and_then(|p| p.lifetimes.get(i - parent_substs.len())) { AstConv::ast_region_to_region(self.fcx, lifetime, Some(def)) } else { self.region_var_for_def(self.span, def) @@ -310,7 +310,10 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { if i < parent_substs.len() { parent_substs.type_at(i) } else if let Some(ast_ty) - = provided.types.get(i - parent_substs.len() - method_generics.regions.len()) { + = provided.as_ref().and_then(|p| { + p.types.get(i - parent_substs.len() - method_generics.regions.len()) + }) + { self.to_ty(ast_ty) } else { self.type_var_for_def(self.span, def, cur_substs) diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 0afc482cb79..4ee0b4cb46f 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -70,6 +70,7 @@ pub struct NoMatchData<'tcx> { pub static_candidates: Vec<CandidateSource>, pub unsatisfied_predicates: Vec<TraitRef<'tcx>>, pub out_of_scope_traits: Vec<DefId>, + pub lev_candidate: Option<ty::AssociatedItem>, pub mode: probe::Mode, } @@ -77,12 +78,14 @@ impl<'tcx> NoMatchData<'tcx> { pub fn new(static_candidates: Vec<CandidateSource>, unsatisfied_predicates: Vec<TraitRef<'tcx>>, out_of_scope_traits: Vec<DefId>, + lev_candidate: Option<ty::AssociatedItem>, mode: probe::Mode) -> Self { NoMatchData { static_candidates, unsatisfied_predicates, out_of_scope_traits, + lev_candidate, mode, } } diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 7b947818325..a3b196f99d6 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -23,11 +23,13 @@ use rustc::infer::type_variable::TypeVariableOrigin; use rustc::util::nodemap::FxHashSet; use rustc::infer::{self, InferOk}; use syntax::ast; +use syntax::util::lev_distance::{lev_distance, find_best_match_for_name}; use syntax_pos::Span; use rustc::hir; use std::mem; use std::ops::Deref; use std::rc::Rc; +use std::cmp::max; use self::CandidateKind::*; pub use self::PickKind::*; @@ -51,6 +53,10 @@ struct ProbeContext<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { /// used for error reporting static_candidates: Vec<CandidateSource>, + /// When probing for names, include names that are close to the + /// requested name (by Levensthein distance) + allow_similar_names: bool, + /// Some(candidate) if there is a private candidate private_candidate: Option<Def>, @@ -242,6 +248,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { return Err(MethodError::NoMatch(NoMatchData::new(Vec::new(), Vec::new(), Vec::new(), + None, mode))) } } @@ -261,7 +268,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // 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, steps); + ProbeContext::new(self, span, mode, method_name, return_type, Rc::new(steps)); probe_cx.assemble_inherent_candidates(); match scope { @@ -333,7 +340,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { mode: Mode, method_name: Option<ast::Name>, return_type: Option<Ty<'tcx>>, - steps: Vec<CandidateStep<'tcx>>) + steps: Rc<Vec<CandidateStep<'tcx>>>) -> ProbeContext<'a, 'gcx, 'tcx> { ProbeContext { fcx, @@ -344,8 +351,9 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { inherent_candidates: Vec::new(), extension_candidates: Vec::new(), impl_dups: FxHashSet(), - steps: Rc::new(steps), + steps: steps, static_candidates: Vec::new(), + allow_similar_names: false, private_candidate: None, unsatisfied_predicates: Vec::new(), } @@ -798,10 +806,12 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { if let Some(def) = private_candidate { return Err(MethodError::PrivateMatch(def, out_of_scope_traits)); } + let lev_candidate = self.probe_for_lev_candidate()?; Err(MethodError::NoMatch(NoMatchData::new(static_candidates, unsatisfied_predicates, out_of_scope_traits, + lev_candidate, self.mode))) } @@ -913,11 +923,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { debug!("applicable_candidates: {:?}", applicable_candidates); if applicable_candidates.len() > 1 { - match self.collapse_candidates_to_trait_pick(&applicable_candidates[..]) { - Some(pick) => { - return Some(Ok(pick)); - } - None => {} + if let Some(pick) = self.collapse_candidates_to_trait_pick(&applicable_candidates[..]) { + return Some(Ok(pick)); } } @@ -1126,6 +1133,54 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { }) } + /// Similarly to `probe_for_return_type`, this method attempts to find the best matching + /// candidate method where the method name may have been misspelt. Similarly to other + /// Levenshtein based suggestions, we provide at most one such suggestion. + fn probe_for_lev_candidate(&mut self) -> Result<Option<ty::AssociatedItem>, MethodError<'tcx>> { + debug!("Probing for method names similar to {:?}", + self.method_name); + + 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); + pcx.allow_similar_names = true; + pcx.assemble_inherent_candidates(); + pcx.assemble_extension_candidates_for_traits_in_scope(ast::DUMMY_NODE_ID)?; + + let method_names = pcx.candidate_method_names(); + pcx.allow_similar_names = false; + let applicable_close_candidates: Vec<ty::AssociatedItem> = method_names + .iter() + .filter_map(|&method_name| { + pcx.reset(); + pcx.method_name = Some(method_name); + pcx.assemble_inherent_candidates(); + pcx.assemble_extension_candidates_for_traits_in_scope(ast::DUMMY_NODE_ID) + .ok().map_or(None, |_| { + pcx.pick_core() + .and_then(|pick| pick.ok()) + .and_then(|pick| Some(pick.item)) + }) + }) + .collect(); + + if applicable_close_candidates.is_empty() { + Ok(None) + } else { + let best_name = { + let names = applicable_close_candidates.iter().map(|cand| &cand.name); + find_best_match_for_name(names, + &self.method_name.unwrap().as_str(), + None) + }.unwrap(); + Ok(applicable_close_candidates + .into_iter() + .find(|method| method.name == best_name)) + } + }) + } + /////////////////////////////////////////////////////////////////////////// // MISCELLANY fn has_applicable_self(&self, item: &ty::AssociatedItem) -> bool { @@ -1253,10 +1308,21 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { self.tcx.erase_late_bound_regions(value) } - /// Find the method with the appropriate name (or return type, as the case may be). + /// Find the method with the appropriate name (or return type, as the case may be). If + /// `allow_similar_names` is set, find methods with close-matching names. fn impl_or_trait_item(&self, def_id: DefId) -> Vec<ty::AssociatedItem> { if let Some(name) = self.method_name { - self.fcx.associated_item(def_id, name).map_or(Vec::new(), |x| vec![x]) + if self.allow_similar_names { + let max_dist = max(name.as_str().len(), 3) / 3; + self.tcx.associated_items(def_id) + .filter(|x| { + let dist = lev_distance(&*name.as_str(), &x.name.as_str()); + dist > 0 && dist <= max_dist + }) + .collect() + } else { + self.fcx.associated_item(def_id, name).map_or(Vec::new(), |x| vec![x]) + } } else { self.tcx.associated_items(def_id).collect() } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 7fa3dd7472d..90c5297b399 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -164,6 +164,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { MethodError::NoMatch(NoMatchData { static_candidates: static_sources, unsatisfied_predicates, out_of_scope_traits, + lev_candidate, mode, .. }) => { let tcx = self.tcx; @@ -282,6 +283,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { item_name, rcvr_expr, out_of_scope_traits); + + if let Some(lev_candidate) = lev_candidate { + err.help(&format!("did you mean `{}`?", lev_candidate.name)); + } err.emit(); } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index ae2430990ba..a0099a48c89 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1665,6 +1665,10 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { fn set_tainted_by_errors(&self) { self.infcx.set_tainted_by_errors() } + + fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, _span: Span) { + self.write_ty(hir_id, ty) + } } /// Controls whether the arguments are tupled. This is used for the call @@ -2232,7 +2236,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { adjusted_ty, index_ty); - // First, try built-in indexing. match (adjusted_ty.builtin_index(), &index_ty.sty) { (Some(ty), &ty::TyUint(ast::UintTy::Us)) | (Some(ty), &ty::TyInfer(ty::IntVar(_))) => { @@ -4644,6 +4647,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // a problem. self.check_path_parameter_count(span, &mut type_segment, false); self.check_path_parameter_count(span, &mut fn_segment, false); + self.check_impl_trait(span, &mut fn_segment); let (fn_start, has_self) = match (type_segment, fn_segment) { (_, Some((_, generics))) => { @@ -4664,7 +4668,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { i -= fn_start; fn_segment }; - let lifetimes = segment.map_or(&[][..], |(s, _)| &s.parameters.lifetimes[..]); + let lifetimes = segment.map_or(&[][..], |(s, _)| { + s.parameters.as_ref().map_or(&[][..], |p| &p.lifetimes[..]) + }); if let Some(lifetime) = lifetimes.get(i) { AstConv::ast_region_to_region(self, lifetime, Some(def)) @@ -4688,7 +4694,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn_segment }; let (types, infer_types) = segment.map_or((&[][..], true), |(s, _)| { - (&s.parameters.types[..], s.parameters.infer_types) + (s.parameters.as_ref().map_or(&[][..], |p| &p.types[..]), s.infer_types) }); // Skip over the lifetimes in the same segment. @@ -4765,8 +4771,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { is_method_call: bool) { let (lifetimes, types, infer_types, bindings) = segment.map_or( (&[][..], &[][..], true, &[][..]), - |(s, _)| (&s.parameters.lifetimes[..], &s.parameters.types[..], - s.parameters.infer_types, &s.parameters.bindings[..])); + |(s, _)| s.parameters.as_ref().map_or( + (&[][..], &[][..], s.infer_types, &[][..]), + |p| (&p.lifetimes[..], &p.types[..], + s.infer_types, &p.bindings[..]))); let infer_lifetimes = lifetimes.len() == 0; let count_lifetime_params = |n| { @@ -4864,6 +4872,36 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } + /// Report error if there is an explicit type parameter when using `impl Trait`. + fn check_impl_trait(&self, + span: Span, + segment: &mut Option<(&hir::PathSegment, &ty::Generics)>) { + use hir::SyntheticTyParamKind::*; + + segment.map(|(path_segment, generics)| { + let explicit = !path_segment.infer_types; + let impl_trait = generics.types.iter() + .any(|ty_param| { + match ty_param.synthetic { + Some(ImplTrait) => true, + _ => false, + } + }); + + if explicit && impl_trait { + let mut err = struct_span_err! { + self.tcx.sess, + span, + E0632, + "cannot provide explicit type parameters when `impl Trait` is \ + used in argument position." + }; + + err.emit(); + } + }); + } + fn structurally_resolve_type_or_else<F>(&self, sp: Span, ty: Ty<'tcx>, f: F) -> Ty<'tcx> where F: Fn() -> Ty<'tcx> diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index f17df8b22f3..ddbdd204305 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -523,7 +523,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { let (span, name) = if index < ast_generics.lifetimes.len() { (ast_generics.lifetimes[index].lifetime.span, - ast_generics.lifetimes[index].lifetime.name) + ast_generics.lifetimes[index].lifetime.name.name()) } else { let index = index - ast_generics.lifetimes.len(); (ast_generics.ty_params[index].span, diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 7810d9049e1..3c650718a4b 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -207,6 +207,13 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> { let var_ty = self.resolve(&var_ty, &l.span); self.write_ty_to_tables(l.hir_id, var_ty); } + + fn visit_ty(&mut self, hir_ty: &'gcx hir::Ty) { + intravisit::walk_ty(self, hir_ty); + let ty = self.fcx.node_ty(hir_ty.hir_id); + let ty = self.resolve(&ty, &hir_ty.span); + self.write_ty_to_tables(hir_ty.hir_id, ty); + } } impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 79cb9147c18..25a37a2c48c 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -221,6 +221,10 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { fn set_tainted_by_errors(&self) { // no obvious place to track this, just let it go } + + fn record_ty(&self, _hir_id: hir::HirId, _ty: Ty<'tcx>, _span: Span) { + // no place to record types from signatures? + } } fn type_param_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -918,6 +922,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, has_default: false, object_lifetime_default: rl::Set1::Empty, pure_wrt_drop: false, + synthetic: None, }); allow_defaults = true; @@ -953,7 +958,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let early_lifetimes = early_bound_lifetimes_from_generics(tcx, ast_generics); let regions = early_lifetimes.enumerate().map(|(i, l)| { ty::RegionParameterDef { - name: l.lifetime.name, + name: l.lifetime.name.name(), index: own_start + i as u32, def_id: tcx.hir.local_def_id(l.lifetime.id), pure_wrt_drop: l.pure_wrt_drop, @@ -989,6 +994,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, object_lifetime_default: object_lifetime_defaults.as_ref().map_or(rl::Set1::Empty, |o| o[i]), pure_wrt_drop: p.pure_wrt_drop, + synthetic: p.synthetic, } }); let mut types: Vec<_> = opt_self.into_iter().chain(types).collect(); @@ -1005,6 +1011,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, has_default: false, object_lifetime_default: rl::Set1::Empty, pure_wrt_drop: false, + synthetic: None, })); }); } @@ -1325,6 +1332,12 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx>( fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::GenericPredicates<'tcx> { + explicit_predicates_of(tcx, def_id) +} + +fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId) + -> ty::GenericPredicates<'tcx> { use rustc::hir::map::*; use rustc::hir::*; @@ -1423,7 +1436,7 @@ fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let region = tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion { def_id: tcx.hir.local_def_id(param.lifetime.id), index, - name: param.lifetime.name + name: param.lifetime.name.name(), })); index += 1; diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 6bbe2233ff1..8df97355574 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4677,4 +4677,6 @@ register_diagnostics! { E0592, // duplicate definitions with name `{}` // E0613, // Removed (merged with E0609) E0627, // yield statement outside of generator literal + E0632, // cannot provide explicit type parameters when `impl Trait` is used in + // argument position. } diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs index 14e48b93029..15708ab766a 100644 --- a/src/librustc_typeck/impl_wf_check.rs +++ b/src/librustc_typeck/impl_wf_check.rs @@ -132,7 +132,7 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, !input_parameters.contains(¶m) { report_unused_parameter(tcx, lifetime.lifetime.span, - "lifetime", &lifetime.lifetime.name.to_string()); + "lifetime", &lifetime.lifetime.name.name().to_string()); } } diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index 61ac541e2c1..b295b414a03 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -18,4 +18,4 @@ html-diff = "0.0.4" [build-dependencies] build_helper = { path = "../build_helper" } -gcc = "0.3.50" +cc = "1.0" diff --git a/src/librustdoc/build.rs b/src/librustdoc/build.rs index 830492dec94..97c9ca1e2d2 100644 --- a/src/librustdoc/build.rs +++ b/src/librustdoc/build.rs @@ -9,12 +9,12 @@ // except according to those terms. extern crate build_helper; -extern crate gcc; +extern crate cc; fn main() { let src_dir = std::path::Path::new("../rt/hoedown/src"); build_helper::rerun_if_changed_anything_in_dir(src_dir); - let mut cfg = gcc::Build::new(); + let mut cfg = cc::Build::new(); cfg.file("../rt/hoedown/src/autolink.c") .file("../rt/hoedown/src/buffer.c") .file("../rt/hoedown/src/document.c") diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 095eb7797d4..c9afa3646b2 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -876,7 +876,7 @@ impl Clean<Lifetime> for hir::Lifetime { } _ => {} } - Lifetime(self.name.to_string()) + Lifetime(self.name.name().to_string()) } } @@ -884,14 +884,14 @@ impl Clean<Lifetime> for hir::LifetimeDef { fn clean(&self, _: &DocContext) -> Lifetime { if self.bounds.len() > 0 { let mut s = format!("{}: {}", - self.lifetime.name.to_string(), - self.bounds[0].name.to_string()); + self.lifetime.name.name(), + self.bounds[0].name.name()); for bound in self.bounds.iter().skip(1) { - s.push_str(&format!(" + {}", bound.name.to_string())); + s.push_str(&format!(" + {}", bound.name.name())); } Lifetime(s) } else { - Lifetime(self.lifetime.name.to_string()) + Lifetime(self.lifetime.name.name().to_string()) } } } @@ -1852,25 +1852,27 @@ impl Clean<Type> for hir::Ty { }; if let Some(&hir::ItemTy(ref ty, ref generics)) = alias { - let provided_params = &path.segments.last().unwrap().parameters; + let provided_params = &path.segments.last().unwrap(); let mut ty_substs = FxHashMap(); let mut lt_substs = FxHashMap(); - for (i, ty_param) in generics.ty_params.iter().enumerate() { - let ty_param_def = Def::TyParam(cx.tcx.hir.local_def_id(ty_param.id)); - if let Some(ty) = provided_params.types.get(i).cloned() { - ty_substs.insert(ty_param_def, ty.unwrap().clean(cx)); - } else if let Some(default) = ty_param.default.clone() { - ty_substs.insert(ty_param_def, default.unwrap().clean(cx)); + provided_params.with_parameters(|provided_params| { + for (i, ty_param) in generics.ty_params.iter().enumerate() { + let ty_param_def = Def::TyParam(cx.tcx.hir.local_def_id(ty_param.id)); + if let Some(ty) = provided_params.types.get(i).cloned() { + ty_substs.insert(ty_param_def, ty.unwrap().clean(cx)); + } else if let Some(default) = ty_param.default.clone() { + ty_substs.insert(ty_param_def, default.unwrap().clean(cx)); + } } - } - for (i, lt_param) in generics.lifetimes.iter().enumerate() { - if let Some(lt) = provided_params.lifetimes.get(i).cloned() { - if !lt.is_elided() { - let lt_def_id = cx.tcx.hir.local_def_id(lt_param.lifetime.id); - lt_substs.insert(lt_def_id, lt.clean(cx)); + for (i, lt_param) in generics.lifetimes.iter().enumerate() { + if let Some(lt) = provided_params.lifetimes.get(i).cloned() { + if !lt.is_elided() { + let lt_def_id = cx.tcx.hir.local_def_id(lt_param.lifetime.id); + lt_substs.insert(lt_def_id, lt.clean(cx)); + } } } - } + }); return cx.enter_alias(ty_substs, lt_substs, || ty.clean(cx)); } resolve_type(cx, path.clean(cx), self.id) @@ -2419,7 +2421,7 @@ impl Clean<PathSegment> for hir::PathSegment { fn clean(&self, cx: &DocContext) -> PathSegment { PathSegment { name: self.name.clean(cx), - params: self.parameters.clean(cx) + params: self.with_parameters(|parameters| parameters.clean(cx)) } } } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 1663e5ad142..2ecb7b546fc 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -175,7 +175,7 @@ pub fn run_core(search_paths: SearchPaths, let arena = DroplessArena::new(); let arenas = GlobalArenas::new(); - let hir_map = hir_map::map_crate(&mut hir_forest, &defs); + let hir_map = hir_map::map_crate(&sess, &*cstore, &mut hir_forest, &defs); let output_filenames = driver::build_output_filenames(&input, &None, &None, @@ -191,7 +191,7 @@ pub fn run_core(search_paths: SearchPaths, &arenas, &name, &output_filenames, - |tcx, analysis, _, _, result| { + |tcx, analysis, _, result| { if let Err(_) = result { sess.fatal("Compilation failed, aborting rustdoc"); } diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 081f950e40d..98863b229b5 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -249,8 +249,8 @@ impl<'a> Classifier<'a> { token::BinOpEq(..) | token::FatArrow => Class::Op, // Miscellaneous, no highlighting. - token::Dot | token::DotDot | token::DotDotDot | token::Comma | token::Semi | - token::Colon | token::ModSep | token::LArrow | token::OpenDelim(_) | + token::Dot | token::DotDot | token::DotDotDot | token::DotDotEq | token::Comma | + token::Semi | token::Colon | token::ModSep | token::LArrow | token::OpenDelim(_) | token::CloseDelim(token::Brace) | token::CloseDelim(token::Paren) | token::CloseDelim(token::NoDelim) => Class::None, @@ -353,7 +353,7 @@ impl<'a> Classifier<'a> { token::Lifetime(..) => Class::Lifetime, token::Underscore | token::Eof | token::Interpolated(..) | - token::Tilde | token::At => Class::None, + token::Tilde | token::At | token::DotEq => Class::None, }; // Anything that didn't return above is the simple case where we the diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index e1e52b9428a..485e75443fe 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2621,7 +2621,8 @@ fn render_assoc_item(w: &mut fmt::Formatter, href(did).map(|p| format!("{}#{}.{}", p.0, ty, name)).unwrap_or(anchor) } }; - let mut head_len = format!("{}{}{:#}fn {}{:#}", + let mut head_len = format!("{}{}{}{:#}fn {}{:#}", + VisSpace(&meth.visibility), ConstnessSpace(constness), UnsafetySpace(unsafety), AbiSpace(abi), @@ -2633,8 +2634,9 @@ fn render_assoc_item(w: &mut fmt::Formatter, } else { (0, true) }; - write!(w, "{}{}{}fn <a href='{href}' class='fnname'>{name}</a>\ + write!(w, "{}{}{}{}fn <a href='{href}' class='fnname'>{name}</a>\ {generics}{decl}{where_clause}", + VisSpace(&meth.visibility), ConstnessSpace(constness), UnsafetySpace(unsafety), AbiSpace(abi), diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 5727d3c5f70..1b7232bf1bc 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -823,7 +823,7 @@ span.since { .information { position: absolute; - left: -1px; + left: -20px; margin-top: 7px; z-index: 1; } diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 36efc37a809..7fa1b38bdad 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -124,7 +124,7 @@ pub fn run(input: &str, render_type); { - let map = hir::map::map_crate(&mut hir_forest, &defs); + let map = hir::map::map_crate(&sess, &*cstore, &mut hir_forest, &defs); let krate = map.krate(); let mut hir_collector = HirCollector { sess: &sess, @@ -348,7 +348,21 @@ pub fn make_test(s: &str, } } } - if dont_insert_main || s.contains("fn main") { + + // FIXME (#21299): prefer libsyntax or some other actual parser over this + // best-effort ad hoc approach + let already_has_main = s.lines() + .map(|line| { + let comment = line.find("//"); + if let Some(comment_begins) = comment { + &line[0..comment_begins] + } else { + line + } + }) + .any(|code| code.contains("fn main")); + + if dont_insert_main || already_has_main { prog.push_str(&everything_else); } else { prog.push_str("fn main() {\n"); diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 09c16816934..fb276448ffa 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -36,7 +36,7 @@ rustc_tsan = { path = "../librustc_tsan" } [build-dependencies] build_helper = { path = "../build_helper" } -gcc = "0.3.50" +cc = "1.0" [features] backtrace = [] diff --git a/src/libstd/build.rs b/src/libstd/build.rs index 19ea25fc7df..7ca762c801a 100644 --- a/src/libstd/build.rs +++ b/src/libstd/build.rs @@ -11,7 +11,7 @@ #![deny(warnings)] extern crate build_helper; -extern crate gcc; +extern crate cc; use std::env; use std::process::Command; @@ -68,8 +68,8 @@ fn main() { if cfg!(feature = "backtrace") { println!("cargo:rustc-link-lib=backtrace"); } - println!("cargo:rustc-link-lib=magenta"); - println!("cargo:rustc-link-lib=mxio"); + println!("cargo:rustc-link-lib=zircon"); + println!("cargo:rustc-link-lib=fdio"); println!("cargo:rustc-link-lib=launchpad"); // for std::process } } @@ -77,7 +77,7 @@ fn main() { fn build_libbacktrace(host: &str, target: &str) -> Result<(), ()> { let native = native_lib_boilerplate("libbacktrace", "libbacktrace", "backtrace", ".libs")?; - let compiler = gcc::Build::new().get_compiler(); + let compiler = cc::Build::new().get_compiler(); // only msvc returns None for ar so unwrap is okay let ar = build_helper::cc2ar(compiler.path(), target).unwrap(); let mut cflags = compiler.args().iter().map(|s| s.to_str().unwrap()) diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 96af2272578..7d000d7c859 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -691,6 +691,17 @@ impl<K, V, S> HashMap<K, V, S> /// Returns a reference to the map's [`BuildHasher`]. /// /// [`BuildHasher`]: ../../std/hash/trait.BuildHasher.html + /// + /// # Examples + /// + /// ``` + /// use std::collections::HashMap; + /// use std::collections::hash_map::RandomState; + /// + /// let hasher = RandomState::new(); + /// let map: HashMap<isize, isize> = HashMap::with_hasher(hasher); + /// let hasher: &RandomState = map.hasher(); + /// ``` #[stable(feature = "hashmap_public_hasher", since = "1.9.0")] pub fn hasher(&self) -> &S { &self.hash_builder @@ -2191,6 +2202,36 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> { fn take_key(&mut self) -> Option<K> { self.key.take() } + + /// Replaces the entry, returning the old key and value. + /// + /// # Examples + /// + /// ``` + /// #![feature(map_entry_replace)] + /// use std::collections::HashMap; + /// use std::collections::hash_map::Entry; + /// + /// let mut map: HashMap<String, u32> = HashMap::new(); + /// map.insert("poneyland".to_string(), 15); + /// + /// if let Entry::Occupied(entry) = map.entry("poneyland".to_string()) { + /// let (old_key, old_value): (String, u32) = entry.replace(16); + /// assert_eq!(old_key, "poneyland"); + /// assert_eq!(old_value, 15); + /// } + /// + /// assert_eq!(map.get("poneyland"), Some(&16)); + /// ``` + #[unstable(feature = "map_entry_replace", issue = "44286")] + pub fn replace(mut self, value: V) -> (K, V) { + let (old_key, old_value) = self.elem.read_mut(); + + let old_key = mem::replace(old_key, self.key.unwrap()); + let old_value = mem::replace(old_value, value); + + (old_key, old_value) + } } impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> { diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 72d1946a286..231b0be9276 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -56,6 +56,7 @@ use any::TypeId; use borrow::Cow; use cell; use char; +use convert; use core::array; use fmt::{self, Debug, Display}; use mem::transmute; @@ -370,6 +371,13 @@ impl Error for char::ParseCharError { } } +#[unstable(feature = "try_from", issue = "33417")] +impl Error for convert::Infallible { + fn description(&self) -> &str { + match *self { + } + } +} // copied from any.rs impl Error + 'static { diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 2a916b819cc..91600b01298 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -1595,9 +1595,9 @@ pub fn create_dir<P: AsRef<Path>>(path: P) -> io::Result<()> { /// /// Notable exception is made for situations where any of the directories /// specified in the `path` could not be created as it was being created concurrently. -/// Such cases are considered success. In other words: calling `create_dir_all` -/// concurrently from multiple threads or processes is guaranteed to not fail -/// due to race itself. +/// Such cases are considered to be successful. That is, calling `create_dir_all` +/// concurrently from multiple threads or processes is guaranteed not to fail +/// due to a race condition with itself. /// /// # Examples /// @@ -2161,6 +2161,27 @@ mod tests { } #[test] + #[cfg(unix)] + fn set_get_unix_permissions() { + use os::unix::fs::PermissionsExt; + + let tmpdir = tmpdir(); + let filename = &tmpdir.join("set_get_unix_permissions"); + check!(fs::create_dir(filename)); + let mask = 0o7777; + + check!(fs::set_permissions(filename, + fs::Permissions::from_mode(0))); + let metadata0 = check!(fs::metadata(filename)); + assert_eq!(mask & metadata0.permissions().mode(), 0); + + check!(fs::set_permissions(filename, + fs::Permissions::from_mode(0o1777))); + let metadata1 = check!(fs::metadata(filename)); + assert_eq!(mask & metadata1.permissions().mode(), 0o1777); + } + + #[test] #[cfg(windows)] fn file_test_io_seek_read_write() { use os::windows::fs::FileExt; diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index e20f249d3ea..45d281ee34a 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -40,9 +40,10 @@ use mem; /// /// io::copy(&mut reader, &mut writer)?; /// -/// assert_eq!(reader, &writer[..]); +/// assert_eq!(&b"hello"[..], &writer[..]); /// # Ok(()) /// # } +/// # foo().unwrap(); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> io::Result<u64> diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index aff9af66444..8d1e7882e5d 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -167,7 +167,7 @@ impl TcpStream { /// connection request. /// /// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html - #[stable(feature = "tcpstream_connect_timeout", since = "1.22.0")] + #[stable(feature = "tcpstream_connect_timeout", since = "1.21.0")] pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> { net_imp::TcpStream::connect_timeout(addr, timeout).map(TcpStream) } diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index 76ef36cc9a7..1edb35d8fe7 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -710,6 +710,10 @@ mod prim_u128 { } // /// The pointer-sized signed integer type. /// +/// The size of this primitive is how many bytes it takes to reference any +/// location in memory. For example, on a 32 bit target, this is 4 bytes +/// and on a 64 bit target, this is 8 bytes. +/// /// *[See also the `std::isize` module](isize/index.html).* /// /// However, please note that examples are shared between primitive integer @@ -722,6 +726,10 @@ mod prim_isize { } // /// The pointer-sized unsigned integer type. /// +/// The size of this primitive is how many bytes it takes to reference any +/// location in memory. For example, on a 32 bit target, this is 4 bytes +/// and on a 64 bit target, this is 8 bytes. +/// /// *[See also the `std::usize` module](usize/index.html).* /// /// However, please note that examples are shared between primitive integer diff --git a/src/libstd/process.rs b/src/libstd/process.rs index a3a7e91dd80..1869ad3ed70 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -106,15 +106,18 @@ use sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; pub struct Child { handle: imp::Process, - /// The handle for writing to the child's stdin, if it has been captured + /// The handle for writing to the child's standard input (stdin), if it has + /// been captured. #[stable(feature = "process", since = "1.0.0")] pub stdin: Option<ChildStdin>, - /// The handle for reading from the child's stdout, if it has been captured + /// The handle for reading from the child's standard output (stdout), if it + /// has been captured. #[stable(feature = "process", since = "1.0.0")] pub stdout: Option<ChildStdout>, - /// The handle for reading from the child's stderr, if it has been captured + /// The handle for reading from the child's standard error (stderr), if it + /// has been captured. #[stable(feature = "process", since = "1.0.0")] pub stderr: Option<ChildStderr>, } @@ -149,12 +152,17 @@ impl fmt::Debug for Child { } } -/// A handle to a child process's stdin. +/// A handle to a child process's standard input (stdin). /// /// This struct is used in the [`stdin`] field on [`Child`]. /// +/// When an instance of `ChildStdin` is [dropped], the `ChildStdin`'s underlying +/// file handle will be closed. If the child process was blocked on input prior +/// to being dropped, it will become unblocked after dropping. +/// /// [`Child`]: struct.Child.html /// [`stdin`]: struct.Child.html#structfield.stdin +/// [dropped]: ../ops/trait.Drop.html #[stable(feature = "process", since = "1.0.0")] pub struct ChildStdin { inner: AnonPipe @@ -192,12 +200,16 @@ impl fmt::Debug for ChildStdin { } } -/// A handle to a child process's stdout. +/// A handle to a child process's standard output (stdout). /// /// This struct is used in the [`stdout`] field on [`Child`]. /// +/// When an instance of `ChildStdout` is [dropped], the `ChildStdout`'s +/// underlying file handle will be closed. +/// /// [`Child`]: struct.Child.html /// [`stdout`]: struct.Child.html#structfield.stdout +/// [dropped]: ../ops/trait.Drop.html #[stable(feature = "process", since = "1.0.0")] pub struct ChildStdout { inner: AnonPipe @@ -239,8 +251,12 @@ impl fmt::Debug for ChildStdout { /// /// This struct is used in the [`stderr`] field on [`Child`]. /// +/// When an instance of `ChildStderr` is [dropped], the `ChildStderr`'s +/// underlying file handle will be closed. +/// /// [`Child`]: struct.Child.html /// [`stderr`]: struct.Child.html#structfield.stderr +/// [dropped]: ../ops/trait.Drop.html #[stable(feature = "process", since = "1.0.0")] pub struct ChildStderr { inner: AnonPipe @@ -534,7 +550,7 @@ impl Command { self } - /// Configuration for the child process's stdin handle (file descriptor 0). + /// Configuration for the child process's standard input (stdin) handle. /// /// # Examples /// @@ -554,7 +570,7 @@ impl Command { self } - /// Configuration for the child process's stdout handle (file descriptor 1). + /// Configuration for the child process's standard output (stdout) handle. /// /// # Examples /// @@ -574,7 +590,7 @@ impl Command { self } - /// Configuration for the child process's stderr handle (file descriptor 2). + /// Configuration for the child process's standard error (stderr) handle. /// /// # Examples /// diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index 5c5231f4e84..4757faabfb8 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -24,19 +24,24 @@ use sys_common::rwlock as sys; /// of the underlying data (exclusive access) and the read portion of this lock /// typically allows for read-only access (shared access). /// +/// In comparison, a [`Mutex`] does not distinguish between readers or writers +/// that aquire the lock, therefore blocking any threads waiting for the lock to +/// become available. An `RwLock` will allow any number of readers to aquire the +/// lock as long as a writer is not holding the lock. +/// /// The priority policy of the lock is dependent on the underlying operating /// system's implementation, and this type does not guarantee that any /// particular policy will be used. /// /// The type parameter `T` represents the data that this lock protects. It is -/// required that `T` satisfies `Send` to be shared across threads and `Sync` to -/// allow concurrent access through readers. The RAII guards returned from the -/// locking methods implement `Deref` (and `DerefMut` for the `write` methods) -/// to allow access to the contained of the lock. +/// required that `T` satisfies [`Send`] to be shared across threads and +/// [`Sync`] to allow concurrent access through readers. The RAII guards +/// returned from the locking methods implement [`Deref`][] (and [`DerefMut`] +/// for the `write` methods) to allow access to the contained of the lock. /// /// # Poisoning /// -/// An `RwLock`, like `Mutex`, will become poisoned on a panic. Note, however, +/// An `RwLock`, like [`Mutex`], will become poisoned on a panic. Note, however, /// that an `RwLock` may only be poisoned if a panic occurs while it is locked /// exclusively (write mode). If a panic occurs in any reader, then the lock /// will not be poisoned. @@ -63,6 +68,12 @@ use sys_common::rwlock as sys; /// assert_eq!(*w, 6); /// } // write lock is dropped here /// ``` +/// +/// [`Deref`]: ../../std/ops/trait.Deref.html +/// [`DerefMut`]: ../../std/ops/trait.DerefMut.html +/// [`Send`]: ../../std/marker/trait.Send.html +/// [`Sync`]: ../../std/marker/trait.Sync.html +/// [`Mutex`]: struct.Mutex.html #[stable(feature = "rust1", since = "1.0.0")] pub struct RwLock<T: ?Sized> { inner: Box<sys::RWLock>, @@ -154,6 +165,24 @@ impl<T: ?Sized> RwLock<T> { /// # Panics /// /// This function might panic when called if the lock is already held by the current thread. + /// + /// # Examples + /// + /// ``` + /// use std::sync::{Arc, RwLock}; + /// use std::thread; + /// + /// let lock = Arc::new(RwLock::new(1)); + /// let c_lock = lock.clone(); + /// + /// let n = lock.read().unwrap(); + /// assert_eq!(*n, 1); + /// + /// thread::spawn(move || { + /// let r = c_lock.read(); + /// assert!(r.is_ok()); + /// }).join().unwrap(); + /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn read(&self) -> LockResult<RwLockReadGuard<T>> { @@ -180,6 +209,19 @@ impl<T: ?Sized> RwLock<T> { /// is poisoned whenever a writer panics while holding an exclusive lock. An /// error will only be returned if the lock would have otherwise been /// acquired. + /// + /// # Examples + /// + /// ``` + /// use std::sync::RwLock; + /// + /// let lock = RwLock::new(1); + /// + /// match lock.try_read() { + /// Ok(n) => assert_eq!(*n, 1), + /// Err(_) => unreachable!(), + /// }; + /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn try_read(&self) -> TryLockResult<RwLockReadGuard<T>> { @@ -210,6 +252,19 @@ impl<T: ?Sized> RwLock<T> { /// # Panics /// /// This function might panic when called if the lock is already held by the current thread. + /// + /// # Examples + /// + /// ``` + /// use std::sync::RwLock; + /// + /// let lock = RwLock::new(1); + /// + /// let mut n = lock.write().unwrap(); + /// *n = 2; + /// + /// assert!(lock.try_read().is_err()); + /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn write(&self) -> LockResult<RwLockWriteGuard<T>> { @@ -236,6 +291,19 @@ impl<T: ?Sized> RwLock<T> { /// is poisoned whenever a writer panics while holding an exclusive lock. An /// error will only be returned if the lock would have otherwise been /// acquired. + /// + /// # Examples + /// + /// ``` + /// use std::sync::RwLock; + /// + /// let lock = RwLock::new(1); + /// + /// let n = lock.read().unwrap(); + /// assert_eq!(*n, 1); + /// + /// assert!(lock.try_write().is_err()); + /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<T>> { @@ -253,6 +321,22 @@ impl<T: ?Sized> RwLock<T> { /// If another thread is active, the lock can still become poisoned at any /// time. You should not trust a `false` value for program correctness /// without additional synchronization. + /// + /// # Examples + /// + /// ``` + /// use std::sync::{Arc, RwLock}; + /// use std::thread; + /// + /// let lock = Arc::new(RwLock::new(0)); + /// let c_lock = lock.clone(); + /// + /// let _ = thread::spawn(move || { + /// let _lock = c_lock.write().unwrap(); + /// panic!(); // the lock gets poisoned + /// }).join(); + /// assert_eq!(lock.is_poisoned(), true); + /// ``` #[inline] #[stable(feature = "sync_poison", since = "1.2.0")] pub fn is_poisoned(&self) -> bool { @@ -267,6 +351,19 @@ impl<T: ?Sized> RwLock<T> { /// is poisoned whenever a writer panics while holding an exclusive lock. An /// error will only be returned if the lock would have otherwise been /// acquired. + /// + /// # Examples + /// + /// ``` + /// use std::sync::RwLock; + /// + /// let lock = RwLock::new(String::new()); + /// { + /// let mut s = lock.write().unwrap(); + /// *s = "modified".to_owned(); + /// } + /// assert_eq!(lock.into_inner().unwrap(), "modified"); + /// ``` #[stable(feature = "rwlock_into_inner", since = "1.6.0")] pub fn into_inner(self) -> LockResult<T> where T: Sized { // We know statically that there are no outstanding references to @@ -282,7 +379,7 @@ impl<T: ?Sized> RwLock<T> { (ptr::read(inner), ptr::read(poison), ptr::read(data)) }; mem::forget(self); - inner.destroy(); // Keep in sync with the `Drop` impl. + inner.destroy(); // Keep in sync with the `Drop` impl. drop(inner); poison::map_result(poison.borrow(), |_| data.into_inner()) @@ -300,6 +397,16 @@ impl<T: ?Sized> RwLock<T> { /// is poisoned whenever a writer panics while holding an exclusive lock. An /// error will only be returned if the lock would have otherwise been /// acquired. + /// + /// # Examples + /// + /// ``` + /// use std::sync::RwLock; + /// + /// let mut lock = RwLock::new(0); + /// *lock.get_mut().unwrap() = 10; + /// assert_eq!(*lock.read().unwrap(), 10); + /// ``` #[stable(feature = "rwlock_get_mut", since = "1.6.0")] pub fn get_mut(&mut self) -> LockResult<&mut T> { // We know statically that there are no other references to `self`, so @@ -486,7 +593,7 @@ mod tests { fn test_rw_arc_poison_wr() { let arc = Arc::new(RwLock::new(1)); let arc2 = arc.clone(); - let _: Result<(), _> = thread::spawn(move|| { + let _: Result<(), _> = thread::spawn(move || { let _lock = arc2.write().unwrap(); panic!(); }).join(); @@ -498,7 +605,7 @@ mod tests { let arc = Arc::new(RwLock::new(1)); assert!(!arc.is_poisoned()); let arc2 = arc.clone(); - let _: Result<(), _> = thread::spawn(move|| { + let _: Result<(), _> = thread::spawn(move || { let _lock = arc2.write().unwrap(); panic!(); }).join(); @@ -510,7 +617,7 @@ mod tests { fn test_rw_arc_no_poison_rr() { let arc = Arc::new(RwLock::new(1)); let arc2 = arc.clone(); - let _: Result<(), _> = thread::spawn(move|| { + let _: Result<(), _> = thread::spawn(move || { let _lock = arc2.read().unwrap(); panic!(); }).join(); @@ -521,7 +628,7 @@ mod tests { fn test_rw_arc_no_poison_rw() { let arc = Arc::new(RwLock::new(1)); let arc2 = arc.clone(); - let _: Result<(), _> = thread::spawn(move|| { + let _: Result<(), _> = thread::spawn(move || { let _lock = arc2.read().unwrap(); panic!() }).join(); @@ -535,7 +642,7 @@ mod tests { let arc2 = arc.clone(); let (tx, rx) = channel(); - thread::spawn(move|| { + thread::spawn(move || { let mut lock = arc2.write().unwrap(); for _ in 0..10 { let tmp = *lock; @@ -550,7 +657,7 @@ mod tests { let mut children = Vec::new(); for _ in 0..5 { let arc3 = arc.clone(); - children.push(thread::spawn(move|| { + children.push(thread::spawn(move || { let lock = arc3.read().unwrap(); assert!(*lock >= 0); })); @@ -571,7 +678,7 @@ mod tests { fn test_rw_arc_access_in_unwind() { let arc = Arc::new(RwLock::new(1)); let arc2 = arc.clone(); - let _ = thread::spawn(move|| -> () { + let _ = thread::spawn(move || -> () { struct Unwinder { i: Arc<RwLock<isize>>, } diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs index f44b9aa9615..3e631ad40ac 100644 --- a/src/libstd/sys/unix/ext/fs.rs +++ b/src/libstd/sys/unix/ext/fs.rs @@ -68,8 +68,8 @@ impl FileExt for fs::File { /// Unix-specific extensions to `Permissions` #[stable(feature = "fs_ext", since = "1.1.0")] pub trait PermissionsExt { - /// Returns the underlying raw `mode_t` bits that are the standard Unix - /// permissions for this file. + /// Returns the underlying raw `st_mode` bits that contain the standard + /// Unix permissions for this file. /// /// # Examples /// diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 13112fc1fa5..c4616c3b395 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -95,7 +95,7 @@ pub struct DirBuilder { mode: mode_t } impl FileAttr { pub fn size(&self) -> u64 { self.stat.st_size as u64 } pub fn perm(&self) -> FilePermissions { - FilePermissions { mode: (self.stat.st_mode as mode_t) & 0o777 } + FilePermissions { mode: (self.stat.st_mode as mode_t) } } pub fn file_type(&self) -> FileType { diff --git a/src/libstd/sys/unix/process/mod.rs b/src/libstd/sys/unix/process/mod.rs index b50384d8eee..2a331069bc2 100644 --- a/src/libstd/sys/unix/process/mod.rs +++ b/src/libstd/sys/unix/process/mod.rs @@ -19,4 +19,4 @@ mod process_inner; #[path = "process_fuchsia.rs"] mod process_inner; #[cfg(target_os = "fuchsia")] -mod magenta; +mod zircon; diff --git a/src/libstd/sys/unix/process/process_fuchsia.rs b/src/libstd/sys/unix/process/process_fuchsia.rs index 7d583cb3dfc..5d34da04446 100644 --- a/src/libstd/sys/unix/process/process_fuchsia.rs +++ b/src/libstd/sys/unix/process/process_fuchsia.rs @@ -13,7 +13,7 @@ use libc; use mem; use ptr; -use sys::process::magenta::{Handle, mx_handle_t}; +use sys::process::zircon::{Handle, zx_handle_t}; use sys::process::process_common::*; //////////////////////////////////////////////////////////////////////////////// @@ -51,10 +51,10 @@ impl Command { } unsafe fn do_exec(&mut self, stdio: ChildPipes) - -> io::Result<mx_handle_t> { - use sys::process::magenta::*; + -> io::Result<zx_handle_t> { + use sys::process::zircon::*; - let job_handle = mx_job_default(); + let job_handle = zx_job_default(); let envp = match *self.get_envp() { Some(ref envp) => envp.as_ptr(), None => ptr::null(), @@ -67,39 +67,39 @@ impl Command { } // Duplicate the job handle - let mut job_copy: mx_handle_t = MX_HANDLE_INVALID; - mx_cvt(mx_handle_duplicate(job_handle, MX_RIGHT_SAME_RIGHTS, &mut job_copy))?; + let mut job_copy: zx_handle_t = ZX_HANDLE_INVALID; + zx_cvt(zx_handle_duplicate(job_handle, ZX_RIGHT_SAME_RIGHTS, &mut job_copy))?; // Create a launchpad let mut launchpad: *mut launchpad_t = ptr::null_mut(); - mx_cvt(launchpad_create(job_copy, self.get_argv()[0], &mut launchpad))?; + zx_cvt(launchpad_create(job_copy, self.get_argv()[0], &mut launchpad))?; let launchpad_destructor = LaunchpadDestructor(launchpad); // Set the process argv - mx_cvt(launchpad_set_args(launchpad, self.get_argv().len() as i32 - 1, + zx_cvt(launchpad_set_args(launchpad, self.get_argv().len() as i32 - 1, self.get_argv().as_ptr()))?; // Setup the environment vars - mx_cvt(launchpad_set_environ(launchpad, envp))?; - mx_cvt(launchpad_add_vdso_vmo(launchpad))?; + zx_cvt(launchpad_set_environ(launchpad, envp))?; + zx_cvt(launchpad_add_vdso_vmo(launchpad))?; // Load the executable - mx_cvt(launchpad_elf_load(launchpad, launchpad_vmo_from_file(self.get_argv()[0])))?; - mx_cvt(launchpad_load_vdso(launchpad, MX_HANDLE_INVALID))?; - mx_cvt(launchpad_clone(launchpad, LP_CLONE_MXIO_ROOT | LP_CLONE_MXIO_CWD))?; + zx_cvt(launchpad_elf_load(launchpad, launchpad_vmo_from_file(self.get_argv()[0])))?; + zx_cvt(launchpad_load_vdso(launchpad, ZX_HANDLE_INVALID))?; + zx_cvt(launchpad_clone(launchpad, LP_CLONE_FDIO_NAMESPACE | LP_CLONE_FDIO_CWD))?; // Clone stdin, stdout, and stderr if let Some(fd) = stdio.stdin.fd() { - mx_cvt(launchpad_transfer_fd(launchpad, fd, 0))?; + zx_cvt(launchpad_transfer_fd(launchpad, fd, 0))?; } else { - mx_cvt(launchpad_clone_fd(launchpad, 0, 0))?; + zx_cvt(launchpad_clone_fd(launchpad, 0, 0))?; } if let Some(fd) = stdio.stdout.fd() { - mx_cvt(launchpad_transfer_fd(launchpad, fd, 1))?; + zx_cvt(launchpad_transfer_fd(launchpad, fd, 1))?; } else { - mx_cvt(launchpad_clone_fd(launchpad, 1, 1))?; + zx_cvt(launchpad_clone_fd(launchpad, 1, 1))?; } if let Some(fd) = stdio.stderr.fd() { - mx_cvt(launchpad_transfer_fd(launchpad, fd, 2))?; + zx_cvt(launchpad_transfer_fd(launchpad, fd, 2))?; } else { - mx_cvt(launchpad_clone_fd(launchpad, 2, 2))?; + zx_cvt(launchpad_clone_fd(launchpad, 2, 2))?; } // We don't want FileDesc::drop to be called on any stdio. It would close their fds. The @@ -113,9 +113,9 @@ impl Command { // `launchpad_go` destroys the launchpad, so we must not mem::forget(launchpad_destructor); - let mut process_handle: mx_handle_t = 0; + let mut process_handle: zx_handle_t = 0; let mut err_msg: *const libc::c_char = ptr::null(); - mx_cvt(launchpad_go(launchpad, &mut process_handle, &mut err_msg))?; + zx_cvt(launchpad_go(launchpad, &mut process_handle, &mut err_msg))?; // FIXME: See if we want to do something with that err_msg Ok(process_handle) @@ -136,27 +136,27 @@ impl Process { } pub fn kill(&mut self) -> io::Result<()> { - use sys::process::magenta::*; + use sys::process::zircon::*; - unsafe { mx_cvt(mx_task_kill(self.handle.raw()))?; } + unsafe { zx_cvt(zx_task_kill(self.handle.raw()))?; } Ok(()) } pub fn wait(&mut self) -> io::Result<ExitStatus> { use default::Default; - use sys::process::magenta::*; + use sys::process::zircon::*; - let mut proc_info: mx_info_process_t = Default::default(); - let mut actual: mx_size_t = 0; - let mut avail: mx_size_t = 0; + let mut proc_info: zx_info_process_t = Default::default(); + let mut actual: zx_size_t = 0; + let mut avail: zx_size_t = 0; unsafe { - mx_cvt(mx_object_wait_one(self.handle.raw(), MX_TASK_TERMINATED, - MX_TIME_INFINITE, ptr::null_mut()))?; - mx_cvt(mx_object_get_info(self.handle.raw(), MX_INFO_PROCESS, + zx_cvt(zx_object_wait_one(self.handle.raw(), ZX_TASK_TERMINATED, + ZX_TIME_INFINITE, ptr::null_mut()))?; + zx_cvt(zx_object_get_info(self.handle.raw(), ZX_INFO_PROCESS, &mut proc_info as *mut _ as *mut libc::c_void, - mem::size_of::<mx_info_process_t>(), &mut actual, + mem::size_of::<zx_info_process_t>(), &mut actual, &mut avail))?; } if actual != 1 { @@ -168,14 +168,14 @@ impl Process { pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> { use default::Default; - use sys::process::magenta::*; + use sys::process::zircon::*; - let mut proc_info: mx_info_process_t = Default::default(); - let mut actual: mx_size_t = 0; - let mut avail: mx_size_t = 0; + let mut proc_info: zx_info_process_t = Default::default(); + let mut actual: zx_size_t = 0; + let mut avail: zx_size_t = 0; unsafe { - let status = mx_object_wait_one(self.handle.raw(), MX_TASK_TERMINATED, + let status = zx_object_wait_one(self.handle.raw(), ZX_TASK_TERMINATED, 0, ptr::null_mut()); match status { 0 => { }, // Success @@ -184,9 +184,9 @@ impl Process { }, _ => { panic!("Failed to wait on process handle: {}", status); }, } - mx_cvt(mx_object_get_info(self.handle.raw(), MX_INFO_PROCESS, + zx_cvt(zx_object_get_info(self.handle.raw(), ZX_INFO_PROCESS, &mut proc_info as *mut _ as *mut libc::c_void, - mem::size_of::<mx_info_process_t>(), &mut actual, + mem::size_of::<zx_info_process_t>(), &mut actual, &mut avail))?; } if actual != 1 { diff --git a/src/libstd/sys/unix/process/magenta.rs b/src/libstd/sys/unix/process/zircon.rs index bc20a74f114..b5ec11b40fd 100644 --- a/src/libstd/sys/unix/process/magenta.rs +++ b/src/libstd/sys/unix/process/zircon.rs @@ -17,31 +17,31 @@ use u64; use libc::{c_int, c_void}; -pub type mx_handle_t = i32; -pub type mx_vaddr_t = usize; -pub type mx_rights_t = u32; -pub type mx_status_t = i32; +pub type zx_handle_t = i32; +pub type zx_vaddr_t = usize; +pub type zx_rights_t = u32; +pub type zx_status_t = i32; -pub type mx_size_t = usize; +pub type zx_size_t = usize; -pub const MX_HANDLE_INVALID: mx_handle_t = 0; +pub const ZX_HANDLE_INVALID: zx_handle_t = 0; -pub type mx_time_t = u64; -pub const MX_TIME_INFINITE : mx_time_t = u64::MAX; +pub type zx_time_t = u64; +pub const ZX_TIME_INFINITE : zx_time_t = u64::MAX; -pub type mx_signals_t = u32; +pub type zx_signals_t = u32; -pub const MX_OBJECT_SIGNAL_3 : mx_signals_t = 1 << 3; +pub const ZX_OBJECT_SIGNAL_3 : zx_signals_t = 1 << 3; -pub const MX_TASK_TERMINATED : mx_signals_t = MX_OBJECT_SIGNAL_3; +pub const ZX_TASK_TERMINATED : zx_signals_t = ZX_OBJECT_SIGNAL_3; -pub const MX_RIGHT_SAME_RIGHTS : mx_rights_t = 1 << 31; +pub const ZX_RIGHT_SAME_RIGHTS : zx_rights_t = 1 << 31; -pub type mx_object_info_topic_t = u32; +pub type zx_object_info_topic_t = u32; -pub const MX_INFO_PROCESS : mx_object_info_topic_t = 3; +pub const ZX_INFO_PROCESS : zx_object_info_topic_t = 3; -pub fn mx_cvt<T>(t: T) -> io::Result<T> where T: TryInto<mx_status_t>+Copy { +pub fn zx_cvt<T>(t: T) -> io::Result<T> where T: TryInto<zx_status_t>+Copy { if let Ok(status) = TryInto::try_into(t) { if status < 0 { Err(io::Error::from_raw_os_error(status)) @@ -53,33 +53,33 @@ pub fn mx_cvt<T>(t: T) -> io::Result<T> where T: TryInto<mx_status_t>+Copy { } } -// Safe wrapper around mx_handle_t +// Safe wrapper around zx_handle_t pub struct Handle { - raw: mx_handle_t, + raw: zx_handle_t, } impl Handle { - pub fn new(raw: mx_handle_t) -> Handle { + pub fn new(raw: zx_handle_t) -> Handle { Handle { raw, } } - pub fn raw(&self) -> mx_handle_t { + pub fn raw(&self) -> zx_handle_t { self.raw } } impl Drop for Handle { fn drop(&mut self) { - unsafe { mx_cvt(mx_handle_close(self.raw)).expect("Failed to close mx_handle_t"); } + unsafe { zx_cvt(zx_handle_close(self.raw)).expect("Failed to close zx_handle_t"); } } } -// Common MX_INFO header +// Common ZX_INFO header #[derive(Default)] #[repr(C)] -pub struct mx_info_header_t { +pub struct zx_info_header_t { pub topic: u32, // identifies the info struct pub avail_topic_size: u16, // “native” size of the struct pub topic_size: u16, // size of the returned struct (<=topic_size) @@ -89,34 +89,34 @@ pub struct mx_info_header_t { #[derive(Default)] #[repr(C)] -pub struct mx_record_process_t { +pub struct zx_record_process_t { pub return_code: c_int, } -// Returned for topic MX_INFO_PROCESS +// Returned for topic ZX_INFO_PROCESS #[derive(Default)] #[repr(C)] -pub struct mx_info_process_t { - pub hdr: mx_info_header_t, - pub rec: mx_record_process_t, +pub struct zx_info_process_t { + pub hdr: zx_info_header_t, + pub rec: zx_record_process_t, } extern { - pub fn mx_job_default() -> mx_handle_t; + pub fn zx_job_default() -> zx_handle_t; - pub fn mx_task_kill(handle: mx_handle_t) -> mx_status_t; + pub fn zx_task_kill(handle: zx_handle_t) -> zx_status_t; - pub fn mx_handle_close(handle: mx_handle_t) -> mx_status_t; + pub fn zx_handle_close(handle: zx_handle_t) -> zx_status_t; - pub fn mx_handle_duplicate(handle: mx_handle_t, rights: mx_rights_t, - out: *const mx_handle_t) -> mx_handle_t; + pub fn zx_handle_duplicate(handle: zx_handle_t, rights: zx_rights_t, + out: *const zx_handle_t) -> zx_handle_t; - pub fn mx_object_wait_one(handle: mx_handle_t, signals: mx_signals_t, timeout: mx_time_t, - pending: *mut mx_signals_t) -> mx_status_t; + pub fn zx_object_wait_one(handle: zx_handle_t, signals: zx_signals_t, timeout: zx_time_t, + pending: *mut zx_signals_t) -> zx_status_t; - pub fn mx_object_get_info(handle: mx_handle_t, topic: u32, buffer: *mut c_void, - buffer_size: mx_size_t, actual_size: *mut mx_size_t, - avail: *mut mx_size_t) -> mx_status_t; + pub fn zx_object_get_info(handle: zx_handle_t, topic: u32, buffer: *mut c_void, + buffer_size: zx_size_t, actual_size: *mut zx_size_t, + avail: *mut zx_size_t) -> zx_status_t; } // From `enum special_handles` in system/ulib/launchpad/launchpad.c @@ -133,117 +133,117 @@ pub struct launchpad_t { env: *const c_char, env_len: usize, - handles: *mut mx_handle_t, + handles: *mut zx_handle_t, handles_info: *mut u32, handle_count: usize, handle_alloc: usize, - entry: mx_vaddr_t, - base: mx_vaddr_t, - vdso_base: mx_vaddr_t, + entry: zx_vaddr_t, + base: zx_vaddr_t, + vdso_base: zx_vaddr_t, stack_size: usize, - special_handles: [mx_handle_t; HND_SPECIAL_COUNT], + special_handles: [zx_handle_t; HND_SPECIAL_COUNT], loader_message: bool, } extern { - pub fn launchpad_create(job: mx_handle_t, name: *const c_char, - lp: *mut *mut launchpad_t) -> mx_status_t; + pub fn launchpad_create(job: zx_handle_t, name: *const c_char, + lp: *mut *mut launchpad_t) -> zx_status_t; pub fn launchpad_go(lp: *mut launchpad_t, - proc_handle: *mut mx_handle_t, - err_msg: *mut *const c_char) -> mx_status_t; + proc_handle: *mut zx_handle_t, + err_msg: *mut *const c_char) -> zx_status_t; pub fn launchpad_destroy(lp: *mut launchpad_t); pub fn launchpad_set_args(lp: *mut launchpad_t, argc: c_int, - argv: *const *const c_char) -> mx_status_t; + argv: *const *const c_char) -> zx_status_t; - pub fn launchpad_set_environ(lp: *mut launchpad_t, envp: *const *const c_char) -> mx_status_t; + pub fn launchpad_set_environ(lp: *mut launchpad_t, envp: *const *const c_char) -> zx_status_t; - pub fn launchpad_clone(lp: *mut launchpad_t, what: u32) -> mx_status_t; + pub fn launchpad_clone(lp: *mut launchpad_t, what: u32) -> zx_status_t; - pub fn launchpad_clone_fd(lp: *mut launchpad_t, fd: c_int, target_fd: c_int) -> mx_status_t; + pub fn launchpad_clone_fd(lp: *mut launchpad_t, fd: c_int, target_fd: c_int) -> zx_status_t; - pub fn launchpad_transfer_fd(lp: *mut launchpad_t, fd: c_int, target_fd: c_int) -> mx_status_t; + pub fn launchpad_transfer_fd(lp: *mut launchpad_t, fd: c_int, target_fd: c_int) -> zx_status_t; - pub fn launchpad_elf_load(lp: *mut launchpad_t, vmo: mx_handle_t) -> mx_status_t; + pub fn launchpad_elf_load(lp: *mut launchpad_t, vmo: zx_handle_t) -> zx_status_t; - pub fn launchpad_add_vdso_vmo(lp: *mut launchpad_t) -> mx_status_t; + pub fn launchpad_add_vdso_vmo(lp: *mut launchpad_t) -> zx_status_t; - pub fn launchpad_load_vdso(lp: *mut launchpad_t, vmo: mx_handle_t) -> mx_status_t; + pub fn launchpad_load_vdso(lp: *mut launchpad_t, vmo: zx_handle_t) -> zx_status_t; - pub fn launchpad_vmo_from_file(filename: *const c_char) -> mx_handle_t; + pub fn launchpad_vmo_from_file(filename: *const c_char) -> zx_handle_t; } // Launchpad clone constants -pub const LP_CLONE_MXIO_ROOT: u32 = 0x0001; -pub const LP_CLONE_MXIO_CWD: u32 = 0x0002; -// LP_CLONE_MXIO_STDIO = 0x0004 -// LP_CLONE_MXIO_ALL = 0x00FF +pub const LP_CLONE_FDIO_NAMESPACE: u32 = 0x0001; +pub const LP_CLONE_FDIO_CWD: u32 = 0x0002; +// LP_CLONE_FDIO_STDIO = 0x0004 +// LP_CLONE_FDIO_ALL = 0x00FF // LP_CLONE_ENVIRON = 0x0100 // LP_CLONE_DEFAULT_JOB = 0x0200 // LP_CLONE_ALL = 0xFFFF // Errors -#[allow(unused)] pub const ERR_INTERNAL: mx_status_t = -1; +#[allow(unused)] pub const ERR_INTERNAL: zx_status_t = -1; // ERR_NOT_SUPPORTED: The operation is not implemented, supported, // or enabled. -#[allow(unused)] pub const ERR_NOT_SUPPORTED: mx_status_t = -2; +#[allow(unused)] pub const ERR_NOT_SUPPORTED: zx_status_t = -2; // ERR_NO_RESOURCES: The system was not able to allocate some resource // needed for the operation. -#[allow(unused)] pub const ERR_NO_RESOURCES: mx_status_t = -3; +#[allow(unused)] pub const ERR_NO_RESOURCES: zx_status_t = -3; // ERR_NO_MEMORY: The system was not able to allocate memory needed // for the operation. -#[allow(unused)] pub const ERR_NO_MEMORY: mx_status_t = -4; +#[allow(unused)] pub const ERR_NO_MEMORY: zx_status_t = -4; -// ERR_CALL_FAILED: The second phase of mx_channel_call(; did not complete +// ERR_CALL_FAILED: The second phase of zx_channel_call(; did not complete // successfully. -#[allow(unused)] pub const ERR_CALL_FAILED: mx_status_t = -5; +#[allow(unused)] pub const ERR_CALL_FAILED: zx_status_t = -5; // ERR_INTERRUPTED_RETRY: The system call was interrupted, but should be // retried. This should not be seen outside of the VDSO. -#[allow(unused)] pub const ERR_INTERRUPTED_RETRY: mx_status_t = -6; +#[allow(unused)] pub const ERR_INTERRUPTED_RETRY: zx_status_t = -6; // ======= Parameter errors ======= // ERR_INVALID_ARGS: an argument is invalid, ex. null pointer -#[allow(unused)] pub const ERR_INVALID_ARGS: mx_status_t = -10; +#[allow(unused)] pub const ERR_INVALID_ARGS: zx_status_t = -10; // ERR_BAD_HANDLE: A specified handle value does not refer to a handle. -#[allow(unused)] pub const ERR_BAD_HANDLE: mx_status_t = -11; +#[allow(unused)] pub const ERR_BAD_HANDLE: zx_status_t = -11; // ERR_WRONG_TYPE: The subject of the operation is the wrong type to // perform the operation. // Example: Attempting a message_read on a thread handle. -#[allow(unused)] pub const ERR_WRONG_TYPE: mx_status_t = -12; +#[allow(unused)] pub const ERR_WRONG_TYPE: zx_status_t = -12; // ERR_BAD_SYSCALL: The specified syscall number is invalid. -#[allow(unused)] pub const ERR_BAD_SYSCALL: mx_status_t = -13; +#[allow(unused)] pub const ERR_BAD_SYSCALL: zx_status_t = -13; // ERR_OUT_OF_RANGE: An argument is outside the valid range for this // operation. -#[allow(unused)] pub const ERR_OUT_OF_RANGE: mx_status_t = -14; +#[allow(unused)] pub const ERR_OUT_OF_RANGE: zx_status_t = -14; // ERR_BUFFER_TOO_SMALL: A caller provided buffer is too small for // this operation. -#[allow(unused)] pub const ERR_BUFFER_TOO_SMALL: mx_status_t = -15; +#[allow(unused)] pub const ERR_BUFFER_TOO_SMALL: zx_status_t = -15; // ======= Precondition or state errors ======= // ERR_BAD_STATE: operation failed because the current state of the // object does not allow it, or a precondition of the operation is // not satisfied -#[allow(unused)] pub const ERR_BAD_STATE: mx_status_t = -20; +#[allow(unused)] pub const ERR_BAD_STATE: zx_status_t = -20; // ERR_TIMED_OUT: The time limit for the operation elapsed before // the operation completed. -#[allow(unused)] pub const ERR_TIMED_OUT: mx_status_t = -21; +#[allow(unused)] pub const ERR_TIMED_OUT: zx_status_t = -21; // ERR_SHOULD_WAIT: The operation cannot be performed currently but // potentially could succeed if the caller waits for a prerequisite @@ -253,67 +253,67 @@ pub const LP_CLONE_MXIO_CWD: u32 = 0x0002; // messages waiting but has an open remote will return ERR_SHOULD_WAIT. // Attempting to read from a message pipe that has no messages waiting // and has a closed remote end will return ERR_REMOTE_CLOSED. -#[allow(unused)] pub const ERR_SHOULD_WAIT: mx_status_t = -22; +#[allow(unused)] pub const ERR_SHOULD_WAIT: zx_status_t = -22; // ERR_CANCELED: The in-progress operation (e.g. a wait) has been // // canceled. -#[allow(unused)] pub const ERR_CANCELED: mx_status_t = -23; +#[allow(unused)] pub const ERR_CANCELED: zx_status_t = -23; // ERR_PEER_CLOSED: The operation failed because the remote end // of the subject of the operation was closed. -#[allow(unused)] pub const ERR_PEER_CLOSED: mx_status_t = -24; +#[allow(unused)] pub const ERR_PEER_CLOSED: zx_status_t = -24; // ERR_NOT_FOUND: The requested entity is not found. -#[allow(unused)] pub const ERR_NOT_FOUND: mx_status_t = -25; +#[allow(unused)] pub const ERR_NOT_FOUND: zx_status_t = -25; // ERR_ALREADY_EXISTS: An object with the specified identifier // already exists. // Example: Attempting to create a file when a file already exists // with that name. -#[allow(unused)] pub const ERR_ALREADY_EXISTS: mx_status_t = -26; +#[allow(unused)] pub const ERR_ALREADY_EXISTS: zx_status_t = -26; // ERR_ALREADY_BOUND: The operation failed because the named entity // is already owned or controlled by another entity. The operation // could succeed later if the current owner releases the entity. -#[allow(unused)] pub const ERR_ALREADY_BOUND: mx_status_t = -27; +#[allow(unused)] pub const ERR_ALREADY_BOUND: zx_status_t = -27; // ERR_UNAVAILABLE: The subject of the operation is currently unable // to perform the operation. // Note: This is used when there's no direct way for the caller to // observe when the subject will be able to perform the operation // and should thus retry. -#[allow(unused)] pub const ERR_UNAVAILABLE: mx_status_t = -28; +#[allow(unused)] pub const ERR_UNAVAILABLE: zx_status_t = -28; // ======= Permission check errors ======= // ERR_ACCESS_DENIED: The caller did not have permission to perform // the specified operation. -#[allow(unused)] pub const ERR_ACCESS_DENIED: mx_status_t = -30; +#[allow(unused)] pub const ERR_ACCESS_DENIED: zx_status_t = -30; // ======= Input-output errors ======= // ERR_IO: Otherwise unspecified error occurred during I/O. -#[allow(unused)] pub const ERR_IO: mx_status_t = -40; +#[allow(unused)] pub const ERR_IO: zx_status_t = -40; // ERR_REFUSED: The entity the I/O operation is being performed on // rejected the operation. // Example: an I2C device NAK'ing a transaction or a disk controller // rejecting an invalid command. -#[allow(unused)] pub const ERR_IO_REFUSED: mx_status_t = -41; +#[allow(unused)] pub const ERR_IO_REFUSED: zx_status_t = -41; // ERR_IO_DATA_INTEGRITY: The data in the operation failed an integrity // check and is possibly corrupted. // Example: CRC or Parity error. -#[allow(unused)] pub const ERR_IO_DATA_INTEGRITY: mx_status_t = -42; +#[allow(unused)] pub const ERR_IO_DATA_INTEGRITY: zx_status_t = -42; // ERR_IO_DATA_LOSS: The data in the operation is currently unavailable // and may be permanently lost. // Example: A disk block is irrecoverably damaged. -#[allow(unused)] pub const ERR_IO_DATA_LOSS: mx_status_t = -43; +#[allow(unused)] pub const ERR_IO_DATA_LOSS: zx_status_t = -43; // Filesystem specific errors -#[allow(unused)] pub const ERR_BAD_PATH: mx_status_t = -50; -#[allow(unused)] pub const ERR_NOT_DIR: mx_status_t = -51; -#[allow(unused)] pub const ERR_NOT_FILE: mx_status_t = -52; +#[allow(unused)] pub const ERR_BAD_PATH: zx_status_t = -50; +#[allow(unused)] pub const ERR_NOT_DIR: zx_status_t = -51; +#[allow(unused)] pub const ERR_NOT_FILE: zx_status_t = -52; // ERR_FILE_BIG: A file exceeds a filesystem-specific size limit. -#[allow(unused)] pub const ERR_FILE_BIG: mx_status_t = -53; +#[allow(unused)] pub const ERR_FILE_BIG: zx_status_t = -53; // ERR_NO_SPACE: Filesystem or device space is exhausted. -#[allow(unused)] pub const ERR_NO_SPACE: mx_status_t = -54; +#[allow(unused)] pub const ERR_NO_SPACE: zx_status_t = -54; diff --git a/src/libstd/sys/unix/rand.rs b/src/libstd/sys/unix/rand.rs index 1f56a299407..fd066c9cdbe 100644 --- a/src/libstd/sys/unix/rand.rs +++ b/src/libstd/sys/unix/rand.rs @@ -344,15 +344,15 @@ mod imp { use io; use rand::Rng; - #[link(name = "magenta")] + #[link(name = "zircon")] extern { - fn mx_cprng_draw(buffer: *mut u8, len: usize, actual: *mut usize) -> i32; + fn zx_cprng_draw(buffer: *mut u8, len: usize, actual: *mut usize) -> i32; } fn getrandom(buf: &mut [u8]) -> Result<usize, i32> { unsafe { let mut actual = 0; - let status = mx_cprng_draw(buf.as_mut_ptr(), buf.len(), &mut actual); + let status = zx_cprng_draw(buf.as_mut_ptr(), buf.len(), &mut actual); if status == 0 { Ok(actual) } else { @@ -387,7 +387,7 @@ mod imp { let ret = getrandom(buf); match ret { Err(err) => { - panic!("kernel mx_cprng_draw call failed! (returned {}, buf.len() {})", + panic!("kernel zx_cprng_draw call failed! (returned {}, buf.len() {})", err, buf.len()) } Ok(actual) => { diff --git a/src/libstd/sys_common/poison.rs b/src/libstd/sys_common/poison.rs index 3c61593acc5..934ac3edbf1 100644 --- a/src/libstd/sys_common/poison.rs +++ b/src/libstd/sys_common/poison.rs @@ -65,6 +65,31 @@ pub struct Guard { /// each lock, but once a lock is poisoned then all future acquisitions will /// return this error. /// +/// # Examples +/// +/// ``` +/// use std::sync::{Arc, Mutex}; +/// use std::thread; +/// +/// let mutex = Arc::new(Mutex::new(1)); +/// +/// // poison the mutex +/// let c_mutex = mutex.clone(); +/// let _ = thread::spawn(move || { +/// let mut data = c_mutex.lock().unwrap(); +/// *data = 2; +/// panic!(); +/// }).join(); +/// +/// match mutex.lock() { +/// Ok(_) => unreachable!(), +/// Err(p_err) => { +/// let data = p_err.get_ref(); +/// println!("recovered: {}", data); +/// } +/// }; +/// ``` +/// /// [`Mutex`]: ../../std/sync/struct.Mutex.html /// [`RwLock`]: ../../std/sync/struct.RwLock.html #[stable(feature = "rust1", since = "1.0.0")] @@ -72,10 +97,16 @@ pub struct PoisonError<T> { guard: T, } -/// An enumeration of possible errors which can occur while calling the -/// [`try_lock`] method. +/// An enumeration of possible errors associated with a [`TryLockResult`] which +/// can occur while trying to aquire a lock, from the [`try_lock`] method on a +/// [`Mutex`] or the [`try_read`] and [`try_write`] methods on an [`RwLock`]. /// +/// [`Mutex`]: struct.Mutex.html +/// [`RwLock`]: struct.RwLock.html +/// [`TryLockResult`]: type.TryLockResult.html /// [`try_lock`]: struct.Mutex.html#method.try_lock +/// [`try_read`]: struct.RwLock.html#method.try_read +/// [`try_write`]: struct.RwLock.html#method.try_write #[stable(feature = "rust1", since = "1.0.0")] pub enum TryLockError<T> { /// The lock could not be acquired because another thread failed while holding @@ -148,6 +179,28 @@ impl<T> PoisonError<T> { /// Consumes this error indicating that a lock is poisoned, returning the /// underlying guard to allow access regardless. + /// + /// # Examples + /// + /// ``` + /// use std::collections::HashSet; + /// use std::sync::{Arc, Mutex}; + /// use std::thread; + /// + /// let mutex = Arc::new(Mutex::new(HashSet::new())); + /// + /// // poison the mutex + /// let c_mutex = mutex.clone(); + /// let _ = thread::spawn(move || { + /// let mut data = c_mutex.lock().unwrap(); + /// data.insert(10); + /// panic!(); + /// }).join(); + /// + /// let p_err = mutex.lock().unwrap_err(); + /// let data = p_err.into_inner(); + /// println!("recovered {} items", data.len()); + /// ``` #[stable(feature = "sync_poison", since = "1.2.0")] pub fn into_inner(self) -> T { self.guard } diff --git a/src/libstd/time/duration.rs b/src/libstd/time/duration.rs index d715a0d740b..86927ce322e 100644 --- a/src/libstd/time/duration.rs +++ b/src/libstd/time/duration.rs @@ -13,7 +13,9 @@ use ops::{Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign, DivAssign}; const NANOS_PER_SEC: u32 = 1_000_000_000; const NANOS_PER_MILLI: u32 = 1_000_000; +const NANOS_PER_MICRO: u32 = 1_000; const MILLIS_PER_SEC: u64 = 1_000; +const MICROS_PER_SEC: u64 = 1_000_000; /// A `Duration` type to represent a span of time, typically used for system /// timeouts. @@ -116,6 +118,27 @@ impl Duration { Duration { secs: secs, nanos: nanos } } + /// Creates a new `Duration` from the specified number of microseconds. + /// + /// # Examples + /// + /// ``` + /// #![feature(duration_from_micros)] + /// use std::time::Duration; + /// + /// let duration = Duration::from_micros(1_000_002); + /// + /// assert_eq!(1, duration.as_secs()); + /// assert_eq!(2000, duration.subsec_nanos()); + /// ``` + #[unstable(feature = "duration_from_micros", issue = "44400")] + #[inline] + pub fn from_micros(micros: u64) -> Duration { + let secs = micros / MICROS_PER_SEC; + let nanos = ((micros % MICROS_PER_SEC) as u32) * NANOS_PER_MICRO; + Duration { secs: secs, nanos: nanos } + } + /// Returns the number of _whole_ seconds contained by this `Duration`. /// /// The returned value does not include the fractional (nanosecond) part of the diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 496be8b3eb2..0504e889ea1 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -538,11 +538,17 @@ pub enum BindingMode { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum RangeEnd { - Included, + Included(RangeSyntax), Excluded, } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub enum RangeSyntax { + DotDotDot, + DotDotEq, +} + +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum PatKind { /// Represents a wildcard pattern (`_`) Wild, @@ -578,7 +584,7 @@ pub enum PatKind { Ref(P<Pat>, Mutability), /// A literal Lit(P<Expr>), - /// A range pattern, e.g. `1...2` or `1..2` + /// A range pattern, e.g. `1...2`, `1..=2` or `1..2` Range(P<Expr>, P<Expr>, RangeEnd), /// `[a, b, ..i, y, z]` is represented as: /// `PatKind::Slice(box [a, b], Some(i), box [y, z])` diff --git a/src/libsyntax/diagnostic_list.rs b/src/libsyntax/diagnostic_list.rs index b29883670bd..c3cf4747835 100644 --- a/src/libsyntax/diagnostic_list.rs +++ b/src/libsyntax/diagnostic_list.rs @@ -291,7 +291,7 @@ Erroneous code example: fn main() { let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1]; - let x = &tmp[1...]; // error: inclusive range was used with no end + let x = &tmp[1..=]; // error: inclusive range was used with no end } ``` @@ -312,7 +312,7 @@ Or put an end to your inclusive range: fn main() { let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1]; - let x = &tmp[1...3]; // ok! + let x = &tmp[1..=3]; // ok! } ``` "##, diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index c139cfeaebf..0e05cce35e2 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -783,6 +783,10 @@ impl<'a> ExtCtxt<'a> { pub fn span_err(&self, sp: Span, msg: &str) { self.parse_sess.span_diagnostic.span_err(sp, msg); } + pub fn mut_span_err(&self, sp: Span, msg: &str) + -> DiagnosticBuilder<'a> { + self.parse_sess.span_diagnostic.mut_span_err(sp, msg) + } pub fn span_warn(&self, sp: Span, msg: &str) { self.parse_sess.span_diagnostic.span_warn(sp, msg); } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index de9c085cc78..6e7a8203b61 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -282,7 +282,33 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let expansion = self.expand_invoc(invoc, ext); self.collect_invocations(expansion, &[]) } else if let InvocationKind::Attr { attr: None, traits, item } = invoc.kind { - let item = item + let derive_allowed = match item { + Annotatable::Item(ref item) => match item.node { + ast::ItemKind::Struct(..) | + ast::ItemKind::Enum(..) | + ast::ItemKind::Union(..) => true, + _ => false, + }, + _ => false, + }; + if !derive_allowed { + let attr = item.attrs().iter() + .find(|attr| attr.check_name("derive")) + .expect("`derive` attribute should exist"); + let span = attr.span; + let mut err = self.cx.mut_span_err(span, + "`derive` may only be applied to \ + structs, enums and unions"); + if let ast::AttrStyle::Inner = attr.style { + let trait_list = traits.iter() + .map(|t| format!("{}", t)).collect::<Vec<_>>(); + let suggestion = format!("#[derive({})]", trait_list.join(", ")); + err.span_suggestion(span, "try an outer attribute", suggestion); + } + err.emit(); + } + + let item = self.fully_configure(item) .map_attrs(|mut attrs| { attrs.retain(|a| a.path != "derive"); attrs }); let item_with_markers = add_derived_markers(&mut self.cx, item.span(), &traits, item.clone()); @@ -374,6 +400,27 @@ impl<'a, 'b> MacroExpander<'a, 'b> { result } + fn fully_configure(&mut self, item: Annotatable) -> Annotatable { + let mut cfg = StripUnconfigured { + should_test: self.cx.ecfg.should_test, + sess: self.cx.parse_sess, + features: self.cx.ecfg.features, + }; + // Since the item itself has already been configured by the InvocationCollector, + // we know that fold result vector will contain exactly one element + match item { + Annotatable::Item(item) => { + Annotatable::Item(cfg.fold_item(item).pop().unwrap()) + } + Annotatable::TraitItem(item) => { + Annotatable::TraitItem(item.map(|item| cfg.fold_trait_item(item).pop().unwrap())) + } + Annotatable::ImplItem(item) => { + Annotatable::ImplItem(item.map(|item| cfg.fold_impl_item(item).pop().unwrap())) + } + } + } + fn expand_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) -> Expansion { let result = match invoc.kind { InvocationKind::Bang { .. } => self.expand_bang_invoc(invoc, ext), @@ -714,15 +761,6 @@ struct InvocationCollector<'a, 'b: 'a> { monotonic: bool, } -macro_rules! fully_configure { - ($this:ident, $node:ident, $noop_fold:ident) => { - match $noop_fold($node, &mut $this.cfg).pop() { - Some(node) => node, - None => return SmallVector::new(), - } - } -} - impl<'a, 'b> InvocationCollector<'a, 'b> { fn collect(&mut self, expansion_kind: ExpansionKind, kind: InvocationKind) -> Expansion { let mark = Mark::fresh(self.cx.current_expansion.mark); @@ -748,13 +786,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { item: Annotatable, kind: ExpansionKind) -> Expansion { - if !traits.is_empty() && - (kind == ExpansionKind::TraitItems || kind == ExpansionKind::ImplItems) { - self.cx.span_err(traits[0].span, "`derive` can be only be applied to items"); - self.cx.trace_macros_diag(); - return kind.expect_from_annotatables(::std::iter::once(item)); - } - self.collect(kind, InvocationKind::Attr { attr: attr, traits: traits, item: item }) + self.collect(kind, InvocationKind::Attr { attr, traits, item }) } // If `item` is an attr invocation, remove and return the macro attribute. @@ -880,7 +912,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { let (attr, traits, mut item) = self.classify_item(item); if attr.is_some() || !traits.is_empty() { - let item = Annotatable::Item(fully_configure!(self, item, noop_fold_item)); + let item = Annotatable::Item(item); return self.collect_attr(attr, traits, item, ExpansionKind::Items).make_items(); } @@ -954,8 +986,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { let (attr, traits, item) = self.classify_item(item); if attr.is_some() || !traits.is_empty() { - let item = - Annotatable::TraitItem(P(fully_configure!(self, item, noop_fold_trait_item))); + let item = Annotatable::TraitItem(P(item)); return self.collect_attr(attr, traits, item, ExpansionKind::TraitItems) .make_trait_items() } @@ -975,7 +1006,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { let (attr, traits, item) = self.classify_item(item); if attr.is_some() || !traits.is_empty() { - let item = Annotatable::ImplItem(P(fully_configure!(self, item, noop_fold_impl_item))); + let item = Annotatable::ImplItem(P(item)); return self.collect_attr(attr, traits, item, ExpansionKind::ImplItems) .make_impl_items(); } diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index c3f3a59c302..bd8c9a0ed40 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -686,7 +686,9 @@ fn expr_mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> P<ast::Expr> { token::At => "At", token::Dot => "Dot", token::DotDot => "DotDot", + token::DotEq => "DotEq", token::DotDotDot => "DotDotDot", + token::DotDotEq => "DotDotEq", token::Comma => "Comma", token::Semi => "Semi", token::Colon => "Colon", diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 6560943a932..e92a7484f33 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -26,7 +26,7 @@ use self::AttributeType::*; use self::AttributeGate::*; use abi::Abi; -use ast::{self, NodeId, PatKind, RangeEnd}; +use ast::{self, NodeId, PatKind, RangeEnd, RangeSyntax}; use attr; use codemap::Spanned; use syntax_pos::Span; @@ -261,7 +261,7 @@ declare_features! ( // rustc internal (active, abi_vectorcall, "1.7.0", None), - // a...b and ...b + // a..=b and ..=b (active, inclusive_range_syntax, "1.7.0", Some(28237)), // X..Y patterns @@ -380,7 +380,7 @@ declare_features! ( // #[doc(masked)] (active, doc_masked, "1.21.0", None), - // allow `#[must_use]` on functions (RFC 1940) + // allow `#[must_use]` on functions and comparison operators (RFC 1940) (active, fn_must_use, "1.21.0", Some(43302)), // allow '|' at beginning of match arms (RFC 1925) @@ -389,6 +389,12 @@ declare_features! ( // Copy/Clone closures (RFC 2132) (active, clone_closures, "1.22.0", Some(44490)), (active, copy_closures, "1.22.0", Some(44490)), + + // allow `'_` placeholder lifetimes + (active, underscore_lifetimes, "1.22.0", Some(44524)), + + // allow `..=` in patterns (RFC 1192) + (active, dotdoteq_in_patterns, "1.22.0", Some(28237)), ); declare_features! ( @@ -721,6 +727,12 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG is just used for rustc unit tests \ and will never be stable", cfg_fn!(rustc_attrs))), + ("rustc_synthetic", Whitelisted, Gated(Stability::Unstable, + "rustc_attrs", + "this attribute \ + is just used for rustc unit tests \ + and will never be stable", + cfg_fn!(rustc_attrs))), ("rustc_symbol_name", Whitelisted, Gated(Stability::Unstable, "rustc_attrs", "internal rustc attributes will never be stable", @@ -1488,6 +1500,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, exclusive_range_pattern, pattern.span, "exclusive range pattern syntax is experimental"); } + PatKind::Range(_, _, RangeEnd::Included(RangeSyntax::DotDotEq)) => { + gate_feature_post!(&self, dotdoteq_in_patterns, pattern.span, + "`..=` syntax in patterns is experimental"); + } _ => {} } visit::walk_pat(self, pattern) @@ -1572,6 +1588,14 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } visit::walk_lifetime_def(self, lifetime_def) } + + fn visit_lifetime(&mut self, lt: &'a ast::Lifetime) { + if lt.ident.name == "'_" { + gate_feature_post!(&self, underscore_lifetimes, lt.span, + "underscore lifetimes are unstable"); + } + visit::walk_lifetime(self, lt) + } } pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> Features { diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index ce3f16d2ba1..1cb7b0eca58 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -1131,6 +1131,9 @@ impl<'a> StringReader<'a> { if self.ch_is('.') { self.bump(); Ok(token::DotDotDot) + } else if self.ch_is('=') { + self.bump(); + Ok(token::DotDotEq) } else { Ok(token::DotDot) } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a2514a04254..d5ba4b54d90 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -38,7 +38,7 @@ use ast::{Ty, TyKind, TypeBinding, TyParam, TyParamBounds}; use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple}; use ast::{Visibility, WhereClause}; use ast::{BinOpKind, UnOp}; -use ast::RangeEnd; +use ast::{RangeEnd, RangeSyntax}; use {ast, attr}; use codemap::{self, CodeMap, Spanned, respan}; use syntax_pos::{self, Span, BytePos}; @@ -432,7 +432,7 @@ impl Error { Error::InclusiveRangeWithNoEnd => { let mut err = struct_span_err!(handler, sp, E0586, "inclusive range with no end"); - err.help("inclusive ranges must be bounded at the end (`...b` or `a...b`)"); + err.help("inclusive ranges must be bounded at the end (`..=b` or `a..=b`)"); err } } @@ -2632,7 +2632,7 @@ impl<'a> Parser<'a> { self.bump(); let e = self.parse_prefix_expr(None); let (span, e) = self.interpolated_or_expr_span(e)?; - (span, self.mk_unary(UnOp::Not, e)) + (lo.to(span), self.mk_unary(UnOp::Not, e)) } // Suggest `!` for bitwise negation when encountering a `~` token::Tilde => { @@ -2645,26 +2645,26 @@ impl<'a> Parser<'a> { err.span_label(span_of_tilde, "did you mean `!`?"); err.help("use `!` instead of `~` if you meant to perform bitwise negation"); err.emit(); - (span, self.mk_unary(UnOp::Not, e)) + (lo.to(span), self.mk_unary(UnOp::Not, e)) } token::BinOp(token::Minus) => { self.bump(); let e = self.parse_prefix_expr(None); let (span, e) = self.interpolated_or_expr_span(e)?; - (span, self.mk_unary(UnOp::Neg, e)) + (lo.to(span), self.mk_unary(UnOp::Neg, e)) } token::BinOp(token::Star) => { self.bump(); let e = self.parse_prefix_expr(None); let (span, e) = self.interpolated_or_expr_span(e)?; - (span, self.mk_unary(UnOp::Deref, e)) + (lo.to(span), self.mk_unary(UnOp::Deref, e)) } token::BinOp(token::And) | token::AndAnd => { self.expect_and()?; let m = self.parse_mutability(); let e = self.parse_prefix_expr(None); let (span, e) = self.interpolated_or_expr_span(e)?; - (span, ExprKind::AddrOf(m, e)) + (lo.to(span), ExprKind::AddrOf(m, e)) } token::Ident(..) if self.token.is_keyword(keywords::In) => { self.bump(); @@ -2675,13 +2675,13 @@ impl<'a> Parser<'a> { let blk = self.parse_block()?; let span = blk.span; let blk_expr = self.mk_expr(span, ExprKind::Block(blk), ThinVec::new()); - (span, ExprKind::InPlace(place, blk_expr)) + (lo.to(span), ExprKind::InPlace(place, blk_expr)) } token::Ident(..) if self.token.is_keyword(keywords::Box) => { self.bump(); let e = self.parse_prefix_expr(None); let (span, e) = self.interpolated_or_expr_span(e)?; - (span, ExprKind::Box(e)) + (lo.to(span), ExprKind::Box(e)) } _ => return self.parse_dot_or_call_expr(Some(attrs)) }; @@ -2710,7 +2710,7 @@ impl<'a> Parser<'a> { LhsExpr::AttributesParsed(attrs) => Some(attrs), _ => None, }; - if self.token == token::DotDot || self.token == token::DotDotDot { + if [token::DotDot, token::DotDotDot, token::DotDotEq].contains(&self.token) { return self.parse_prefix_range_expr(attrs); } else { self.parse_prefix_expr(attrs)? @@ -2744,6 +2744,10 @@ impl<'a> Parser<'a> { if op.precedence() < min_prec { break; } + // Warn about deprecated ... syntax (until SNAP) + if self.token == token::DotDotDot { + self.warn_dotdoteq(self.span); + } self.bump(); if op.is_comparison() { self.check_no_chained_comparison(&lhs, &op); @@ -2770,12 +2774,13 @@ impl<'a> Parser<'a> { } }; continue - } else if op == AssocOp::DotDot || op == AssocOp::DotDotDot { - // If we didn’t have to handle `x..`/`x...`, it would be pretty easy to + } else if op == AssocOp::DotDot || op == AssocOp::DotDotEq { + // If we didn’t have to handle `x..`/`x..=`, it would be pretty easy to // generalise it to the Fixity::None code. // - // We have 2 alternatives here: `x..y`/`x...y` and `x..`/`x...` The other + // We have 2 alternatives here: `x..y`/`x..=y` and `x..`/`x..=` The other // two variants are handled with `parse_prefix_range_expr` call above. + // (and `x...y`/`x...` until SNAP) let rhs = if self.is_at_start_of_range_notation_rhs() { Some(self.parse_assoc_expr_with(op.precedence() + 1, LhsExpr::NotYetParsed)?) @@ -2852,8 +2857,8 @@ impl<'a> Parser<'a> { let aopexpr = self.mk_assign_op(codemap::respan(cur_op_span, aop), lhs, rhs); self.mk_expr(span, aopexpr, ThinVec::new()) } - AssocOp::As | AssocOp::Colon | AssocOp::DotDot | AssocOp::DotDotDot => { - self.bug("As, Colon, DotDot or DotDotDot branch reached") + AssocOp::As | AssocOp::Colon | AssocOp::DotDot | AssocOp::DotDotEq => { + self.bug("AssocOp should have been handled by special case") } }; @@ -2949,17 +2954,22 @@ impl<'a> Parser<'a> { } } - /// Parse prefix-forms of range notation: `..expr`, `..`, `...expr` + /// Parse prefix-forms of range notation: `..expr`, `..`, `..=expr` (and `...expr` until SNAP) fn parse_prefix_range_expr(&mut self, already_parsed_attrs: Option<ThinVec<Attribute>>) -> PResult<'a, P<Expr>> { - debug_assert!(self.token == token::DotDot || self.token == token::DotDotDot, - "parse_prefix_range_expr: token {:?} is not DotDot or DotDotDot", + // SNAP remove DotDotDot + debug_assert!([token::DotDot, token::DotDotDot, token::DotDotEq].contains(&self.token), + "parse_prefix_range_expr: token {:?} is not DotDot/DotDotDot/DotDotEq", self.token); let tok = self.token.clone(); let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?; let lo = self.span; let mut hi = self.span; + // Warn about deprecated ... syntax (until SNAP) + if tok == token::DotDotDot { + self.warn_dotdoteq(self.span); + } self.bump(); let opt_end = if self.is_at_start_of_range_notation_rhs() { // RHS must be parsed with more associativity than the dots. @@ -3450,7 +3460,7 @@ impl<'a> Parser<'a> { fn parse_as_ident(&mut self) -> bool { self.look_ahead(1, |t| match *t { token::OpenDelim(token::Paren) | token::OpenDelim(token::Brace) | - token::DotDotDot | token::ModSep | token::Not => Some(false), + token::DotDotDot | token::DotDotEq | token::ModSep | token::Not => Some(false), // ensure slice patterns [a, b.., c] and [a, b, c..] don't go into the // range pattern branch token::DotDot => None, @@ -3544,11 +3554,13 @@ impl<'a> Parser<'a> { let mac = respan(lo.to(self.prev_span), Mac_ { path: path, tts: tts }); pat = PatKind::Mac(mac); } - token::DotDotDot | token::DotDot => { + token::DotDotDot | token::DotDotEq | token::DotDot => { let end_kind = match self.token { token::DotDot => RangeEnd::Excluded, - token::DotDotDot => RangeEnd::Included, - _ => panic!("can only parse `..` or `...` for ranges (checked above)"), + token::DotDotDot => RangeEnd::Included(RangeSyntax::DotDotDot), + token::DotDotEq => RangeEnd::Included(RangeSyntax::DotDotEq), + _ => panic!("can only parse `..`/`...`/`..=` for ranges \ + (checked above)"), }; // Parse range let span = lo.to(self.prev_span); @@ -3589,7 +3601,12 @@ impl<'a> Parser<'a> { Ok(begin) => { if self.eat(&token::DotDotDot) { let end = self.parse_pat_range_end()?; - pat = PatKind::Range(begin, end, RangeEnd::Included); + pat = PatKind::Range(begin, end, + RangeEnd::Included(RangeSyntax::DotDotDot)); + } else if self.eat(&token::DotDotEq) { + let end = self.parse_pat_range_end()?; + pat = PatKind::Range(begin, end, + RangeEnd::Included(RangeSyntax::DotDotEq)); } else if self.eat(&token::DotDot) { let end = self.parse_pat_range_end()?; pat = PatKind::Range(begin, end, RangeEnd::Excluded); @@ -3973,7 +3990,7 @@ impl<'a> Parser<'a> { token::BinOp(token::Minus) | token::BinOp(token::Star) | token::BinOp(token::And) | token::BinOp(token::Or) | token::AndAnd | token::OrOr | - token::DotDot | token::DotDotDot => false, + token::DotDot | token::DotDotDot | token::DotDotEq => false, _ => true, } { self.warn_missing_semicolon(); @@ -4195,6 +4212,12 @@ impl<'a> Parser<'a> { }).emit(); } + fn warn_dotdoteq(&self, span: Span) { + self.diagnostic().struct_span_warn(span, { + "`...` is being replaced by `..=`" + }).emit(); + } + // Parse bounds of a type parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`. // BOUND = TY_BOUND | LT_BOUND // LT_BOUND = LIFETIME (e.g. `'a`) diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index a316733bdb5..4888654fac9 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -152,6 +152,8 @@ pub enum Token { Dot, DotDot, DotDotDot, + DotDotEq, + DotEq, // HACK(durka42) never produced by the parser, only used for libproc_macro Comma, Semi, Colon, @@ -212,18 +214,19 @@ impl Token { pub fn can_begin_expr(&self) -> bool { match *self { Ident(ident) => ident_can_begin_expr(ident), // value name or keyword - OpenDelim(..) | // tuple, array or block - Literal(..) | // literal - Not | // operator not - BinOp(Minus) | // unary minus - BinOp(Star) | // dereference - BinOp(Or) | OrOr | // closure - BinOp(And) | // reference - AndAnd | // double reference - DotDot | DotDotDot | // range notation - Lt | BinOp(Shl) | // associated path - ModSep | // global path - Pound => true, // expression attributes + OpenDelim(..) | // tuple, array or block + Literal(..) | // literal + Not | // operator not + BinOp(Minus) | // unary minus + BinOp(Star) | // dereference + BinOp(Or) | OrOr | // closure + BinOp(And) | // reference + AndAnd | // double reference + DotDot | DotDotDot | DotDotEq | // range notation + // SNAP remove DotDotDot + Lt | BinOp(Shl) | // associated path + ModSep | // global path + Pound => true, // expression attributes Interpolated(ref nt) => match nt.0 { NtIdent(..) | NtExpr(..) | NtBlock(..) | NtPath(..) => true, _ => false, @@ -402,10 +405,12 @@ impl Token { Dot => match joint { Dot => DotDot, DotDot => DotDotDot, + DotEq => DotDotEq, _ => return None, }, DotDot => match joint { Dot => DotDotDot, + Eq => DotDotEq, _ => return None, }, Colon => match joint { @@ -413,9 +418,9 @@ impl Token { _ => return None, }, - Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot | Comma | - Semi | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar | Question | - OpenDelim(..) | CloseDelim(..) | Underscore => return None, + Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot | DotEq | + DotDotEq | Comma | Semi | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar | + Question | OpenDelim(..) | CloseDelim(..) | Underscore => return None, Literal(..) | Ident(..) | Lifetime(..) | Interpolated(..) | DocComment(..) | Whitespace | Comment | Shebang(..) | Eof => return None, diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 9903dc50f36..959dd4ef30f 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -11,7 +11,7 @@ pub use self::AnnNode::*; use abi::{self, Abi}; -use ast::{self, BlockCheckMode, PatKind, RangeEnd}; +use ast::{self, BlockCheckMode, PatKind, RangeEnd, RangeSyntax}; use ast::{SelfKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}; use ast::Attribute; use util::parser::{self, AssocOp, Fixity}; @@ -203,6 +203,8 @@ pub fn token_to_string(tok: &Token) -> String { token::Dot => ".".to_string(), token::DotDot => "..".to_string(), token::DotDotDot => "...".to_string(), + token::DotDotEq => "..=".to_string(), + token::DotEq => ".=".to_string(), token::Comma => ",".to_string(), token::Semi => ";".to_string(), token::Colon => ":".to_string(), @@ -2588,7 +2590,8 @@ impl<'a> State<'a> { self.print_expr(begin)?; self.s.space()?; match *end_kind { - RangeEnd::Included => self.s.word("...")?, + RangeEnd::Included(RangeSyntax::DotDotDot) => self.s.word("...")?, + RangeEnd::Included(RangeSyntax::DotDotEq) => self.s.word("..=")?, RangeEnd::Excluded => self.s.word("..")?, } self.print_expr(end)?; diff --git a/src/libsyntax/util/parser.rs b/src/libsyntax/util/parser.rs index a4f06cb1b45..590874806d7 100644 --- a/src/libsyntax/util/parser.rs +++ b/src/libsyntax/util/parser.rs @@ -62,8 +62,8 @@ pub enum AssocOp { As, /// `..` range DotDot, - /// `...` range - DotDotDot, + /// `..=` range + DotDotEq, /// `:` Colon, } @@ -105,7 +105,8 @@ impl AssocOp { Token::AndAnd => Some(LAnd), Token::OrOr => Some(LOr), Token::DotDot => Some(DotDot), - Token::DotDotDot => Some(DotDotDot), + Token::DotDotEq => Some(DotDotEq), + Token::DotDotDot => Some(DotDotEq), // remove this after SNAP Token::Colon => Some(Colon), _ if t.is_keyword(keywords::As) => Some(As), _ => None @@ -151,7 +152,7 @@ impl AssocOp { Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => 7, LAnd => 6, LOr => 5, - DotDot | DotDotDot => 4, + DotDot | DotDotEq => 4, Inplace => 3, Assign | AssignOp(_) => 2, } @@ -166,7 +167,7 @@ impl AssocOp { As | Multiply | Divide | Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual | LAnd | LOr | Colon => Fixity::Left, - DotDot | DotDotDot => Fixity::None + DotDot | DotDotEq => Fixity::None } } @@ -176,7 +177,7 @@ impl AssocOp { Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => true, Inplace | Assign | AssignOp(_) | As | Multiply | Divide | Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | LAnd | LOr | - DotDot | DotDotDot | Colon => false + DotDot | DotDotEq | Colon => false } } @@ -186,7 +187,7 @@ impl AssocOp { Assign | AssignOp(_) | Inplace => true, Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual | As | Multiply | Divide | Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | LAnd | - LOr | DotDot | DotDotDot | Colon => false + LOr | DotDot | DotDotEq | Colon => false } } @@ -211,7 +212,7 @@ impl AssocOp { BitOr => Some(BinOpKind::BitOr), LAnd => Some(BinOpKind::And), LOr => Some(BinOpKind::Or), - Inplace | Assign | AssignOp(_) | As | DotDot | DotDotDot | Colon => None + Inplace | Assign | AssignOp(_) | As | DotDot | DotDotEq | Colon => None } } } diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index d701810e2e9..5c1ca19d635 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -428,8 +428,9 @@ impl<'a> TraitDef<'a> { } } _ => { - cx.span_err(mitem.span, - "`derive` may only be applied to structs, enums and unions"); + // Non-ADT derive is an error, but it should have been + // set earlier; see + // libsyntax/ext/expand.rs:MacroExpander::expand() return; } }; @@ -448,8 +449,10 @@ impl<'a> TraitDef<'a> { push(Annotatable::Item(P(ast::Item { attrs: attrs, ..(*newitem).clone() }))) } _ => { - cx.span_err(mitem.span, - "`derive` may only be applied to structs and enums"); + // Non-Item derive is an error, but it should have been + // set earlier; see + // libsyntax/ext/expand.rs:MacroExpander::expand() + return; } } } diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index 919804d7efd..4790fa0a7ed 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -25,7 +25,7 @@ use std::fmt; /// A SyntaxContext represents a chain of macro expansions (represented by marks). #[derive(Clone, Copy, PartialEq, Eq, Default, PartialOrd, Ord, Hash)] -pub struct SyntaxContext(u32); +pub struct SyntaxContext(pub(super) u32); #[derive(Copy, Clone, Default)] pub struct SyntaxContextData { diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 27fbca19dcc..582f2798181 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -25,11 +25,10 @@ #![feature(optin_builtin_traits)] #![allow(unused_attributes)] #![feature(specialization)] -#![feature(staged_api)] use std::borrow::Cow; use std::cell::{Cell, RefCell}; -use std::cmp; +use std::cmp::{self, Ordering}; use std::fmt; use std::hash::Hasher; use std::ops::{Add, Sub}; @@ -47,6 +46,9 @@ extern crate serialize as rustc_serialize; // used by deriving pub mod hygiene; pub use hygiene::{SyntaxContext, ExpnInfo, ExpnFormat, NameAndSpan, CompilerDesugaringKind}; +mod span_encoding; +pub use span_encoding::{Span, DUMMY_SP}; + pub mod symbol; pub type FileName = String; @@ -59,23 +61,33 @@ pub type FileName = String; /// able to use many of the functions on spans in codemap and you cannot assume /// 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 +/// sent to other threads, but some pieces of performance infra run in a separate thread. +/// Using `Span` is generally preferred. #[derive(Clone, Copy, Hash, PartialEq, Eq, Ord, PartialOrd)] -pub struct Span { - #[unstable(feature = "rustc_private", issue = "27812")] - #[rustc_deprecated(since = "1.21", reason = "use getters/setters instead")] +pub struct SpanData { pub lo: BytePos, - #[unstable(feature = "rustc_private", issue = "27812")] - #[rustc_deprecated(since = "1.21", reason = "use getters/setters instead")] pub hi: BytePos, /// Information about where the macro came from, if this piece of /// code was created by a macro expansion. - #[unstable(feature = "rustc_private", issue = "27812")] - #[rustc_deprecated(since = "1.21", reason = "use getters/setters instead")] pub ctxt: SyntaxContext, } -#[allow(deprecated)] -pub const DUMMY_SP: Span = Span { lo: BytePos(0), hi: BytePos(0), ctxt: NO_EXPANSION }; +// The interner in thread-local, so `Span` shouldn't move between threads. +impl !Send for Span {} +impl !Sync for Span {} + +impl PartialOrd for Span { + fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> { + PartialOrd::partial_cmp(&self.data(), &rhs.data()) + } +} +impl Ord for Span { + fn cmp(&self, rhs: &Self) -> Ordering { + Ord::cmp(&self.data(), &rhs.data()) + } +} /// A collection of spans. Spans have two orthogonal attributes: /// @@ -90,38 +102,32 @@ pub struct MultiSpan { } impl Span { - #[allow(deprecated)] - #[inline] - pub fn new(lo: BytePos, hi: BytePos, ctxt: SyntaxContext) -> Self { - if lo <= hi { Span { lo, hi, ctxt } } else { Span { lo: hi, hi: lo, ctxt } } - } - - #[allow(deprecated)] #[inline] pub fn lo(self) -> BytePos { - self.lo + self.data().lo } #[inline] pub fn with_lo(self, lo: BytePos) -> Span { - Span::new(lo, self.hi(), self.ctxt()) + let base = self.data(); + Span::new(lo, base.hi, base.ctxt) } - #[allow(deprecated)] #[inline] pub fn hi(self) -> BytePos { - self.hi + self.data().hi } #[inline] pub fn with_hi(self, hi: BytePos) -> Span { - Span::new(self.lo(), hi, self.ctxt()) + let base = self.data(); + Span::new(base.lo, hi, base.ctxt) } - #[allow(deprecated)] #[inline] pub fn ctxt(self) -> SyntaxContext { - self.ctxt + self.data().ctxt } #[inline] pub fn with_ctxt(self, ctxt: SyntaxContext) -> Span { - Span::new(self.lo(), self.hi(), ctxt) + let base = self.data(); + Span::new(base.lo, base.hi, ctxt) } /// Returns a new span representing just the end-point of this span @@ -342,6 +348,12 @@ impl fmt::Debug for Span { } } +impl fmt::Debug for SpanData { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + SPAN_DEBUG.with(|span_debug| span_debug.get()(Span::new(self.lo, self.hi, self.ctxt), f)) + } +} + impl MultiSpan { pub fn new() -> MultiSpan { MultiSpan { diff --git a/src/libsyntax_pos/span_encoding.rs b/src/libsyntax_pos/span_encoding.rs new file mode 100644 index 00000000000..c2b32171a9a --- /dev/null +++ b/src/libsyntax_pos/span_encoding.rs @@ -0,0 +1,143 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Spans are encoded using 1-bit tag and 2 different encoding formats (one for each tag value). +// One format is used for keeping span data inline, +// another contains index into an out-of-line span interner. +// The encoding format for inline spans were obtained by optimizing over crates in rustc/libstd. +// See https://internals.rust-lang.org/t/rfc-compiler-refactoring-spans/1357/28 + +use {BytePos, SpanData}; +use hygiene::SyntaxContext; + +use rustc_data_structures::fx::FxHashMap; +use std::cell::RefCell; + +/// A compressed span. +/// Contains either fields of `SpanData` inline if they are small, or index into span interner. +/// The primary goal of `Span` is to be as small as possible and fit into other structures +/// (that's why it uses `packed` as well). Decoding speed is the second priority. +/// See `SpanData` for the info on span fields in decoded representation. +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +#[repr(packed)] +pub struct Span(u32); + +/// Dummy span, both position and length are zero, syntax context is zero as well. +/// This span is kept inline and encoded with format 0. +pub const DUMMY_SP: Span = Span(0); + +impl Span { + #[inline] + pub fn new(lo: BytePos, hi: BytePos, ctxt: SyntaxContext) -> Self { + encode(&match lo <= hi { + true => SpanData { lo, hi, ctxt }, + false => SpanData { lo: hi, hi: lo, ctxt }, + }) + } + + #[inline] + pub fn data(self) -> SpanData { + decode(self) + } +} + +// Tags +const TAG_INLINE: u32 = 0; +const TAG_INTERNED: u32 = 1; +const TAG_MASK: u32 = 1; + +// Fields indexes +const BASE_INDEX: usize = 0; +const LEN_INDEX: usize = 1; +const CTXT_INDEX: usize = 2; + +// Tag = 0, inline format. +// ----------------------------------- +// | base 31:8 | len 7:1 | tag 0:0 | +// ----------------------------------- +const INLINE_SIZES: [u32; 3] = [24, 7, 0]; +const INLINE_OFFSETS: [u32; 3] = [8, 1, 1]; + +// Tag = 1, interned format. +// ------------------------ +// | index 31:1 | tag 0:0 | +// ------------------------ +const INTERNED_INDEX_SIZE: u32 = 31; +const INTERNED_INDEX_OFFSET: u32 = 1; + +#[inline] +fn encode(sd: &SpanData) -> Span { + let (base, len, ctxt) = (sd.lo.0, sd.hi.0 - sd.lo.0, sd.ctxt.0); + + let val = if (base >> INLINE_SIZES[BASE_INDEX]) == 0 && + (len >> INLINE_SIZES[LEN_INDEX]) == 0 && + (ctxt >> INLINE_SIZES[CTXT_INDEX]) == 0 { + (base << INLINE_OFFSETS[BASE_INDEX]) | (len << INLINE_OFFSETS[LEN_INDEX]) | + (ctxt << INLINE_OFFSETS[CTXT_INDEX]) | TAG_INLINE + } else { + let index = with_span_interner(|interner| interner.intern(sd)); + (index << INTERNED_INDEX_OFFSET) | TAG_INTERNED + }; + Span(val) +} + +#[inline] +fn decode(span: Span) -> SpanData { + let val = span.0; + + // Extract a field at position `pos` having size `size`. + let extract = |pos: u32, size: u32| { + let mask = ((!0u32) as u64 >> (32 - size)) as u32; // Can't shift u32 by 32 + (val >> pos) & mask + }; + + let (base, len, ctxt) = if val & TAG_MASK == TAG_INLINE {( + extract(INLINE_OFFSETS[BASE_INDEX], INLINE_SIZES[BASE_INDEX]), + extract(INLINE_OFFSETS[LEN_INDEX], INLINE_SIZES[LEN_INDEX]), + extract(INLINE_OFFSETS[CTXT_INDEX], INLINE_SIZES[CTXT_INDEX]), + )} else { + let index = extract(INTERNED_INDEX_OFFSET, INTERNED_INDEX_SIZE); + return with_span_interner(|interner| *interner.get(index)); + }; + SpanData { lo: BytePos(base), hi: BytePos(base + len), ctxt: SyntaxContext(ctxt) } +} + +#[derive(Default)] +struct SpanInterner { + spans: FxHashMap<SpanData, u32>, + span_data: Vec<SpanData>, +} + +impl SpanInterner { + fn intern(&mut self, span_data: &SpanData) -> u32 { + if let Some(index) = self.spans.get(span_data) { + return *index; + } + + let index = self.spans.len() as u32; + self.span_data.push(*span_data); + self.spans.insert(*span_data, index); + index + } + + #[inline] + fn get(&self, index: u32) -> &SpanData { + &self.span_data[index as usize] + } +} + +// If an interner exists in TLS, return it. Otherwise, prepare a fresh one. +#[inline] +fn with_span_interner<T, F: FnOnce(&mut SpanInterner) -> T>(f: F) -> T { + thread_local!(static INTERNER: RefCell<SpanInterner> = { + RefCell::new(SpanInterner::default()) + }); + INTERNER.with(|interner| f(&mut *interner.borrow_mut())) +} diff --git a/src/rtstartup/rsbegin.rs b/src/rtstartup/rsbegin.rs index 335817fddbb..8733c7436d5 100644 --- a/src/rtstartup/rsbegin.rs +++ b/src/rtstartup/rsbegin.rs @@ -38,7 +38,7 @@ trait Copy {} trait Freeze {} impl Freeze for .. {} -#[lang="drop_in_place"] +#[lang = "drop_in_place"] #[inline] #[allow(unconditional_recursion)] pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) { diff --git a/src/rtstartup/rsend.rs b/src/rtstartup/rsend.rs index 9229b4e3128..a6aed3540dd 100644 --- a/src/rtstartup/rsend.rs +++ b/src/rtstartup/rsend.rs @@ -25,7 +25,7 @@ trait Copy {} trait Freeze {} impl Freeze for .. {} -#[lang="drop_in_place"] +#[lang = "drop_in_place"] #[inline] #[allow(unconditional_recursion)] pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) { diff --git a/src/rustc/libc_shim/Cargo.toml b/src/rustc/libc_shim/Cargo.toml index 39df3528be3..0c04402124a 100644 --- a/src/rustc/libc_shim/Cargo.toml +++ b/src/rustc/libc_shim/Cargo.toml @@ -1,16 +1,7 @@ -# This is a shim Cargo.toml over the "real Cargo.toml" found in the libc -# repository itself. The purpose for this is to add a build script which prints -# out `--cfg stdbuild` to mirror the makefiles' build system. -# -# Note that other than that this isn't actually needed, and we should probably -# remove this shim in favor of just working with cargo features directly with -# libc. That should make everything nicer! - [package] name = "libc" version = "0.0.0" authors = ["The Rust Project Developers"] -build = "build.rs" [lib] name = "libc" @@ -20,4 +11,27 @@ 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" } + +[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"] diff --git a/src/test/compile-fail/E0506.rs b/src/test/compile-fail/E0506.rs index ddaffd4a273..b2cf66849c7 100644 --- a/src/test/compile-fail/E0506.rs +++ b/src/test/compile-fail/E0506.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// revisions: ast mir +//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir + struct FancyNum { num: u8, } @@ -15,7 +18,9 @@ struct FancyNum { fn main() { let mut fancy_num = FancyNum { num: 5 }; let fancy_ref = &fancy_num; - fancy_num = FancyNum { num: 6 }; //~ ERROR E0506 + fancy_num = FancyNum { num: 6 }; //[ast]~ ERROR E0506 + //[mir]~^ ERROR (Mir) [E0506] + //[mir]~| ERROR (Ast) [E0506] println!("Num: {}, Ref: {}", fancy_num.num, fancy_ref.num); } diff --git a/src/test/compile-fail/E0586.rs b/src/test/compile-fail/E0586.rs index 0b063569abc..c1bfc5c73a1 100644 --- a/src/test/compile-fail/E0586.rs +++ b/src/test/compile-fail/E0586.rs @@ -10,5 +10,5 @@ fn main() { let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1]; - let x = &tmp[1...]; //~ ERROR E0586 + let x = &tmp[1..=]; //~ ERROR E0586 } diff --git a/src/test/compile-fail/E0637.rs b/src/test/compile-fail/E0637.rs new file mode 100644 index 00000000000..455529b088a --- /dev/null +++ b/src/test/compile-fail/E0637.rs @@ -0,0 +1,20 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +#![feature(underscore_lifetimes)] + +struct Foo<'a: '_>(&'a u8); //~ ERROR invalid lifetime bound name: `'_` +fn foo<'a: '_>(_: &'a u8) {} //~ ERROR invalid lifetime bound name: `'_` + +struct Bar<'a>(&'a u8); +impl<'a: '_> Bar<'a> { //~ ERROR invalid lifetime bound name: `'_` + fn bar() {} +} + +fn main() {} diff --git a/src/test/compile-fail/borrowck/borrowck-assign-comp.rs b/src/test/compile-fail/borrowck/borrowck-assign-comp.rs index 802b83119b7..e63de3a3bed 100644 --- a/src/test/compile-fail/borrowck/borrowck-assign-comp.rs +++ b/src/test/compile-fail/borrowck/borrowck-assign-comp.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// revisions: ast mir +//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir + struct point { x: isize, y: isize } fn a() { @@ -17,7 +20,9 @@ fn a() { // This assignment is illegal because the field x is not // inherently mutable; since `p` was made immutable, `p.x` is now // immutable. Otherwise the type of &_q.x (&isize) would be wrong. - p.x = 5; //~ ERROR cannot assign to `p.x` + p.x = 5; //[ast]~ ERROR cannot assign to `p.x` + //[mir]~^ ERROR cannot assign to `p.x` because it is borrowed (Ast) + //[mir]~| ERROR cannot assign to `p.0` because it is borrowed (Mir) q.x; } @@ -27,7 +32,9 @@ fn c() { let mut p = point {x: 3, y: 4}; let q = &p.y; - p = point {x: 5, y: 7};//~ ERROR cannot assign to `p` + p = point {x: 5, y: 7};//[ast]~ ERROR cannot assign to `p` + //[mir]~^ ERROR cannot assign to `p` because it is borrowed (Ast) + //[mir]~| ERROR cannot assign to `p` because it is borrowed (Mir) p.x; // silence warning *q; // stretch loan } @@ -38,7 +45,9 @@ fn d() { let mut p = point {x: 3, y: 4}; let q = &p.y; - p.y = 5; //~ ERROR cannot assign to `p.y` + p.y = 5; //[ast]~ ERROR cannot assign to `p.y` + //[mir]~^ ERROR cannot assign to `p.y` because it is borrowed (Ast) + //[mir]~| ERROR cannot assign to `p.1` because it is borrowed (Mir) *q; } diff --git a/src/test/compile-fail/borrowck/borrowck-closures-mut-and-imm.rs b/src/test/compile-fail/borrowck/borrowck-closures-mut-and-imm.rs index aaa07661215..6c003ec2d48 100644 --- a/src/test/compile-fail/borrowck/borrowck-closures-mut-and-imm.rs +++ b/src/test/compile-fail/borrowck/borrowck-closures-mut-and-imm.rs @@ -11,6 +11,10 @@ // Tests that two closures cannot simultaneously have mutable // and immutable access to the variable. Issue #6801. +// ignore-tidy-linelength +// revisions: ast mir +//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir + #![feature(box_syntax)] fn get(x: &isize) -> isize { @@ -24,37 +28,49 @@ fn set(x: &mut isize) { fn a() { let mut x = 3; let c1 = || x = 4; - let c2 = || x * 5; //~ ERROR cannot borrow `x` + let c2 = || x * 5; //[ast]~ ERROR cannot borrow `x` + //[mir]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable (Ast) + //[mir]~| ERROR cannot borrow `x` as immutable because it is also borrowed as mutable (Mir) } fn b() { let mut x = 3; let c1 = || set(&mut x); - let c2 = || get(&x); //~ ERROR cannot borrow `x` + let c2 = || get(&x); //[ast]~ ERROR cannot borrow `x` + //[mir]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable (Ast) + //[mir]~| ERROR cannot borrow `x` as immutable because it is also borrowed as mutable (Mir) } fn c() { let mut x = 3; let c1 = || set(&mut x); - let c2 = || x * 5; //~ ERROR cannot borrow `x` + let c2 = || x * 5; //[ast]~ ERROR cannot borrow `x` + //[mir]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable (Ast) + //[mir]~| ERROR cannot borrow `x` as immutable because it is also borrowed as mutable (Mir) } fn d() { let mut x = 3; let c2 = || x * 5; - x = 5; //~ ERROR cannot assign + x = 5; //[ast]~ ERROR cannot assign + //[mir]~^ ERROR cannot assign to `x` because it is borrowed (Ast) + //[mir]~| ERROR cannot assign to `x` because it is borrowed (Mir) } fn e() { let mut x = 3; let c1 = || get(&x); - x = 5; //~ ERROR cannot assign + x = 5; //[ast]~ ERROR cannot assign + //[mir]~^ ERROR cannot assign to `x` because it is borrowed (Ast) + //[mir]~| ERROR cannot assign to `x` because it is borrowed (Mir) } fn f() { let mut x: Box<_> = box 3; let c1 = || get(&*x); - *x = 5; //~ ERROR cannot assign + *x = 5; //[ast]~ ERROR cannot assign + //[mir]~^ ERROR cannot assign to `*x` because it is borrowed (Ast) + //[mir]~| ERROR cannot assign to `(*x)` because it is borrowed (Mir) } fn g() { @@ -64,7 +80,9 @@ fn g() { let mut x: Box<_> = box Foo { f: box 3 }; let c1 = || get(&*x.f); - *x.f = 5; //~ ERROR cannot assign to `*x.f` + *x.f = 5; //[ast]~ ERROR cannot assign to `*x.f` + //[mir]~^ ERROR cannot assign to `*x.f` because it is borrowed (Ast) + //[mir]~| ERROR cannot assign to `(*(*x).0)` because it is borrowed (Mir) } fn h() { @@ -74,7 +92,9 @@ fn h() { let mut x: Box<_> = box Foo { f: box 3 }; let c1 = || get(&*x.f); - let c2 = || *x.f = 5; //~ ERROR cannot borrow `x` as mutable + let c2 = || *x.f = 5; //[ast]~ ERROR cannot borrow `x` as mutable + //[mir]~^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable (Ast) + //[mir]~| ERROR cannot borrow `x` as mutable because it is also borrowed as immutable (Mir) } fn main() { diff --git a/src/test/compile-fail/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs b/src/test/compile-fail/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs index 8af10231921..03b6b1d7324 100644 --- a/src/test/compile-fail/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs +++ b/src/test/compile-fail/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs @@ -8,11 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// revisions: ast mir +//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir + fn main() { let mut _a = 3; let _b = &mut _a; { let _c = &*_b; - _a = 4; //~ ERROR cannot assign to `_a` + _a = 4; //[ast]~ ERROR cannot assign to `_a` + //[mir]~^ ERROR cannot assign to `_a` because it is borrowed (Ast) + //[mir]~| ERROR cannot assign to `_a` because it is borrowed (Mir) } } diff --git a/src/test/compile-fail/borrowck/borrowck-lend-flow-match.rs b/src/test/compile-fail/borrowck/borrowck-lend-flow-match.rs index f24e82d11c5..0e8c003e408 100644 --- a/src/test/compile-fail/borrowck/borrowck-lend-flow-match.rs +++ b/src/test/compile-fail/borrowck/borrowck-lend-flow-match.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// revisions: ast mir +//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir + #![allow(unused_variables)] #![allow(unused_assignments)] @@ -22,7 +25,9 @@ fn separate_arms() { x = Some(0); } Some(ref __isize) => { - x = Some(1); //~ ERROR cannot assign + x = Some(1); //[ast]~ ERROR cannot assign + //[mir]~^ ERROR cannot assign to `x` because it is borrowed (Ast) + //[mir]~| ERROR cannot assign to `x` because it is borrowed (Mir) } } x.clone(); // just to prevent liveness warnings diff --git a/src/test/compile-fail/borrowck/borrowck-match-binding-is-assignment.rs b/src/test/compile-fail/borrowck/borrowck-match-binding-is-assignment.rs index c219b7c5424..3639db5cfc4 100644 --- a/src/test/compile-fail/borrowck/borrowck-match-binding-is-assignment.rs +++ b/src/test/compile-fail/borrowck/borrowck-match-binding-is-assignment.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// revisions: ast mir +//[mir]compile-flags: -Zemit-end-regions -Zborrowck-mir + // Test that immutable pattern bindings cannot be reassigned. #![feature(slice_patterns)] @@ -23,31 +26,41 @@ struct S { pub fn main() { match 1 { x => { - x += 1; //~ ERROR re-assignment of immutable variable `x` + x += 1; //[ast]~ ERROR re-assignment of immutable variable `x` + //[mir]~^ ERROR (Mir) [E0384] + //[mir]~| ERROR (Ast) [E0384] } } match E::Foo(1) { E::Foo(x) => { - x += 1; //~ ERROR re-assignment of immutable variable `x` + x += 1; //[ast]~ ERROR re-assignment of immutable variable `x` + //[mir]~^ ERROR (Mir) [E0384] + //[mir]~| ERROR (Ast) [E0384] } } match (S { bar: 1 }) { S { bar: x } => { - x += 1; //~ ERROR re-assignment of immutable variable `x` + x += 1; //[ast]~ ERROR re-assignment of immutable variable `x` + //[mir]~^ ERROR (Mir) [E0384] + //[mir]~| ERROR (Ast) [E0384] } } match (1,) { (x,) => { - x += 1; //~ ERROR re-assignment of immutable variable `x` + x += 1; //[ast]~ ERROR re-assignment of immutable variable `x` + //[mir]~^ ERROR (Mir) [E0384] + //[mir]~| ERROR (Ast) [E0384] } } match [1,2,3] { [x,_,_] => { - x += 1; //~ ERROR re-assignment of immutable variable `x` + x += 1; //[ast]~ ERROR re-assignment of immutable variable `x` + //[mir]~^ ERROR (Mir) [E0384] + //[mir]~| ERROR (Ast) [E0384] } } } diff --git a/src/test/compile-fail/borrowck/borrowck-move-from-unsafe-ptr.rs b/src/test/compile-fail/borrowck/borrowck-move-from-unsafe-ptr.rs index 7284fa7a850..9a39ff6206b 100644 --- a/src/test/compile-fail/borrowck/borrowck-move-from-unsafe-ptr.rs +++ b/src/test/compile-fail/borrowck/borrowck-move-from-unsafe-ptr.rs @@ -9,8 +9,8 @@ // except according to those terms. -fn foo(x: *const Box<isize>) -> Box<isize> { - let y = *x; //~ ERROR dereference of raw pointer requires unsafe function or block +unsafe fn foo(x: *const Box<isize>) -> Box<isize> { + let y = *x; //~ ERROR cannot move out of dereference of raw pointer return y; } diff --git a/src/test/compile-fail/borrowck/borrowck-overloaded-index-and-overloaded-deref.rs b/src/test/compile-fail/borrowck/borrowck-overloaded-index-and-overloaded-deref.rs index bee56c9bf39..9b20cd470f6 100644 --- a/src/test/compile-fail/borrowck/borrowck-overloaded-index-and-overloaded-deref.rs +++ b/src/test/compile-fail/borrowck/borrowck-overloaded-index-and-overloaded-deref.rs @@ -13,6 +13,9 @@ // operator. The accounting of the all the implicit things going on // here is rather subtle. Issue #20232. +// revisions: ast mir +//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir + use std::ops::{Deref, Index}; struct MyVec<T> { x: T } @@ -39,7 +42,9 @@ fn main() { let mut v = MyVec { x: MyPtr { x: Foo { f: 22 } } }; let i = &v[0].f; v = MyVec { x: MyPtr { x: Foo { f: 23 } } }; - //~^ ERROR cannot assign to `v` + //[ast]~^ ERROR cannot assign to `v` + //[mir]~^^ ERROR cannot assign to `v` because it is borrowed (Ast) + //[mir]~| ERROR cannot assign to `v` because it is borrowed (Mir) read(*i); } diff --git a/src/test/compile-fail/borrowck/borrowck-pat-reassign-binding.rs b/src/test/compile-fail/borrowck/borrowck-pat-reassign-binding.rs index d176245823e..06bb98fa0ec 100644 --- a/src/test/compile-fail/borrowck/borrowck-pat-reassign-binding.rs +++ b/src/test/compile-fail/borrowck/borrowck-pat-reassign-binding.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// revisions: ast mir +//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir + fn main() { let mut x: Option<isize> = None; match x { @@ -17,7 +20,9 @@ fn main() { } Some(ref i) => { // But on this branch, `i` is an outstanding borrow - x = Some(*i+1); //~ ERROR cannot assign to `x` + x = Some(*i+1); //[ast]~ ERROR cannot assign to `x` + //[mir]~^ ERROR cannot assign to `x` because it is borrowed (Ast) + //[mir]~| ERROR cannot assign to `x` because it is borrowed (Mir) } } x.clone(); // just to prevent liveness warnings diff --git a/src/test/compile-fail/borrowck/borrowck-union-borrow.rs b/src/test/compile-fail/borrowck/borrowck-union-borrow.rs index 20b882e1f80..73d323ea82c 100644 --- a/src/test/compile-fail/borrowck/borrowck-union-borrow.rs +++ b/src/test/compile-fail/borrowck/borrowck-union-borrow.rs @@ -9,6 +9,8 @@ // except according to those terms. // ignore-tidy-linelength +// revisions: ast mir +//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir #[derive(Clone, Copy)] union U { @@ -30,11 +32,15 @@ fn main() { } { let ra = &u.a; - let rma = &mut u.a; //~ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable + let rma = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable + //[mir]~^ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable (Ast) + //[mir]~| ERROR cannot borrow `u.0` as mutable because it is also borrowed as immutable (Mir) } { let ra = &u.a; - u.a = 1; //~ ERROR cannot assign to `u.a` because it is borrowed + u.a = 1; //[ast]~ ERROR cannot assign to `u.a` because it is borrowed + //[mir]~^ ERROR cannot assign to `u.a` because it is borrowed (Ast) + //[mir]~| ERROR cannot assign to `u.0` because it is borrowed (Mir) } // Imm borrow, other field { @@ -47,45 +53,65 @@ fn main() { } { let ra = &u.a; - let rmb = &mut u.b; //~ ERROR cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`) + let rmb = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`) + //[mir]~^ ERROR cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`) (Ast) + // FIXME Error for MIR (needs support for union) } { let ra = &u.a; - u.b = 1; //~ ERROR cannot assign to `u.b` because it is borrowed + u.b = 1; //[ast]~ ERROR cannot assign to `u.b` because it is borrowed + //[mir]~^ ERROR cannot assign to `u.b` because it is borrowed (Ast) + // FIXME Error for MIR (needs support for union) } // Mut borrow, same field { let rma = &mut u.a; - let ra = &u.a; //~ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable + let ra = &u.a; //[ast]~ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable + //[mir]~^ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable (Ast) + //[mir]~| ERROR cannot borrow `u.0` as immutable because it is also borrowed as mutable (Mir) } { let ra = &mut u.a; - let a = u.a; //~ ERROR cannot use `u.a` because it was mutably borrowed + let a = u.a; //[ast]~ ERROR cannot use `u.a` because it was mutably borrowed + //[mir]~^ ERROR cannot use `u.a` because it was mutably borrowed (Ast) + //[mir]~| ERROR cannot use `u.0` because it was mutably borrowed (Mir) } { let rma = &mut u.a; - let rma2 = &mut u.a; //~ ERROR cannot borrow `u.a` as mutable more than once at a time + let rma2 = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as mutable more than once at a time + //[mir]~^ ERROR cannot borrow `u.a` as mutable more than once at a time (Ast) + //[mir]~| ERROR cannot borrow `u.0` as mutable more than once at a time (Mir) } { let rma = &mut u.a; - u.a = 1; //~ ERROR cannot assign to `u.a` because it is borrowed + u.a = 1; //[ast]~ ERROR cannot assign to `u.a` because it is borrowed + //[mir]~^ ERROR cannot assign to `u.a` because it is borrowed (Ast) + //[mir]~| ERROR cannot assign to `u.0` because it is borrowed (Mir) } // Mut borrow, other field { let rma = &mut u.a; - let rb = &u.b; //~ ERROR cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`) + let rb = &u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`) + //[mir]~^ ERROR cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`) (Ast) + // FIXME Error for MIR (needs support for union) } { let ra = &mut u.a; - let b = u.b; //~ ERROR cannot use `u.b` because it was mutably borrowed + let b = u.b; //[ast]~ ERROR cannot use `u.b` because it was mutably borrowed + //[mir]~^ ERROR cannot use `u.b` because it was mutably borrowed (Ast) + // FIXME Error for MIR (needs support for union) } { let rma = &mut u.a; - let rmb2 = &mut u.b; //~ ERROR cannot borrow `u` (via `u.b`) as mutable more than once at a time + let rmb2 = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as mutable more than once at a time + //[mir]~^ ERROR cannot borrow `u` (via `u.b`) as mutable more than once at a time (Ast) + // FIXME Error for MIR (needs support for union) } { let rma = &mut u.a; - u.b = 1; //~ ERROR cannot assign to `u.b` because it is borrowed + u.b = 1; //[ast]~ ERROR cannot assign to `u.b` because it is borrowed + //[mir]~^ ERROR cannot assign to `u.b` because it is borrowed (Ast) + // FIXME Error for MIR (needs support for union) } } } diff --git a/src/test/compile-fail/borrowck/borrowck-vec-pattern-move-tail.rs b/src/test/compile-fail/borrowck/borrowck-vec-pattern-move-tail.rs index fddb9838c44..b5916584930 100644 --- a/src/test/compile-fail/borrowck/borrowck-vec-pattern-move-tail.rs +++ b/src/test/compile-fail/borrowck/borrowck-vec-pattern-move-tail.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// revisions: ast mir +//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir + #![feature(slice_patterns)] fn main() { @@ -17,7 +20,9 @@ fn main() { _ => unreachable!() }; println!("t[0]: {}", t[0]); - a[2] = 0; //~ ERROR cannot assign to `a[..]` because it is borrowed + a[2] = 0; //[ast]~ ERROR cannot assign to `a[..]` because it is borrowed + //[mir]~^ ERROR cannot assign to `a[..]` because it is borrowed (Ast) + // FIXME Error for MIR (error missed) println!("t[0]: {}", t[0]); t[0]; } diff --git a/src/test/compile-fail/cdylib-deps-must-be-static.rs b/src/test/compile-fail/cdylib-deps-must-be-static.rs index 853507cbc6d..bf7189c21fb 100644 --- a/src/test/compile-fail/cdylib-deps-must-be-static.rs +++ b/src/test/compile-fail/cdylib-deps-must-be-static.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern: dependency `cdylib_dep` not found in rlib format +// error-pattern: crate `cdylib_dep` required to be available in rlib format, but was not found // aux-build:cdylib-dep.rs // ignore-musl // ignore-emscripten diff --git a/src/test/compile-fail/coerce-overloaded-autoderef.rs b/src/test/compile-fail/coerce-overloaded-autoderef.rs index 14fbc34c43b..43b771ce5db 100644 --- a/src/test/compile-fail/coerce-overloaded-autoderef.rs +++ b/src/test/compile-fail/coerce-overloaded-autoderef.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// revisions: ast mir +//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir + fn borrow_mut<T>(x: &mut T) -> &mut T { x } fn borrow<T>(x: &T) -> &T { x } @@ -17,24 +20,32 @@ fn borrow2<T>(_: &mut T, _: &T) {} fn double_mut_borrow<T>(x: &mut Box<T>) { let y = borrow_mut(x); let z = borrow_mut(x); - //~^ ERROR cannot borrow `*x` as mutable more than once at a time + //[ast]~^ ERROR cannot borrow `*x` as mutable more than once at a time + //[mir]~^^ ERROR cannot borrow `*x` as mutable more than once at a time (Ast) + //[mir]~| ERROR cannot borrow `(*x)` as mutable more than once at a time (Mir) } fn double_imm_borrow(x: &mut Box<i32>) { let y = borrow(x); let z = borrow(x); **x += 1; - //~^ ERROR cannot assign to `**x` because it is borrowed + //[ast]~^ ERROR cannot assign to `**x` because it is borrowed + //[mir]~^^ ERROR cannot assign to `**x` because it is borrowed (Ast) + //[mir]~| ERROR cannot assign to `(*(*x))` because it is borrowed (Mir) } fn double_mut_borrow2<T>(x: &mut Box<T>) { borrow_mut2(x, x); - //~^ ERROR cannot borrow `*x` as mutable more than once at a time + //[ast]~^ ERROR cannot borrow `*x` as mutable more than once at a time + //[mir]~^^ ERROR cannot borrow `*x` as mutable more than once at a time (Ast) + //[mir]~| ERROR cannot borrow `(*x)` as mutable more than once at a time (Mir) } fn double_borrow2<T>(x: &mut Box<T>) { borrow2(x, x); - //~^ ERROR cannot borrow `*x` as immutable because it is also borrowed as mutable + //[ast]~^ ERROR cannot borrow `*x` as immutable because it is also borrowed as mutable + //[mir]~^^ ERROR cannot borrow `*x` as immutable because it is also borrowed as mutable (Ast) + //[mir]~| ERROR cannot borrow `(*x)` as immutable because it is also borrowed as mutable (Mir) } pub fn main() {} diff --git a/src/test/compile-fail/feature-gate-dotdoteq_in_patterns.rs b/src/test/compile-fail/feature-gate-dotdoteq_in_patterns.rs new file mode 100644 index 00000000000..1fb139bf07f --- /dev/null +++ b/src/test/compile-fail/feature-gate-dotdoteq_in_patterns.rs @@ -0,0 +1,16 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub fn main() { + match 22 { + 0 ..= 3 => {} //~ ERROR `..=` syntax in patterns is experimental + _ => {} + } +} diff --git a/src/rustc/libc_shim/build.rs b/src/test/compile-fail/feature-gate-underscore-lifetimes.rs index 546f60482e7..9da50c5c877 100644 --- a/src/rustc/libc_shim/build.rs +++ b/src/test/compile-fail/feature-gate-underscore-lifetimes.rs @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![deny(warnings)] +struct Foo<'a>(&'a u8); -// See comments in Cargo.toml for why this exists +fn foo(x: &u8) -> Foo<'_> { //~ ERROR underscore lifetimes are unstable + Foo(x) +} fn main() { - println!("cargo:rustc-cfg=stdbuild"); - println!("cargo:rerun-if-changed=build.rs"); + let x = 5; + let _ = foo(&x); } diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-derive-2.rs b/src/test/compile-fail/feature-gate/issue-43106-gating-of-derive-2.rs index be82d0a5f6d..2dbc6cb140d 100644 --- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-derive-2.rs +++ b/src/test/compile-fail/feature-gate/issue-43106-gating-of-derive-2.rs @@ -8,23 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// `#![derive]` is interpreted (and raises errors) when it occurs at -// contexts other than ADT definitions. This test checks cases where -// the derive-macro does not exist. +// This test checks cases where the derive-macro does not exist. -#![derive(x3300)] -//~^ ERROR cannot find derive macro `x3300` in this scope - -#[derive(x3300)] -//~^ ERROR cannot find derive macro `x3300` in this scope mod derive { - mod inner { #![derive(x3300)] } - //~^ ERROR cannot find derive macro `x3300` in this scope - - #[derive(x3300)] - //~^ ERROR cannot find derive macro `x3300` in this scope - fn derive() { } - #[derive(x3300)] //~^ ERROR cannot find derive macro `x3300` in this scope union U { f: i32 } @@ -36,12 +22,4 @@ mod derive { #[derive(x3300)] //~^ ERROR cannot find derive macro `x3300` in this scope struct S; - - #[derive(x3300)] - //~^ ERROR cannot find derive macro `x3300` in this scope - type T = S; - - #[derive(x3300)] - //~^ ERROR cannot find derive macro `x3300` in this scope - impl S { } } diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-derive.rs b/src/test/compile-fail/feature-gate/issue-43106-gating-of-derive.rs index 41c3d0ef561..e5293ebb94d 100644 --- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-derive.rs +++ b/src/test/compile-fail/feature-gate/issue-43106-gating-of-derive.rs @@ -8,9 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// `#![derive]` is interpreted (and raises errors) when it occurs at -// contexts other than ADT definitions. This test checks cases where -// the derive-macro exists. +// `#![derive]` raises errors when it occurs at contexts other than ADT +// definitions. #![derive(Debug)] //~^ ERROR `derive` may only be applied to structs, enums and unions diff --git a/src/test/compile-fail/hrtb-identity-fn-borrows.rs b/src/test/compile-fail/hrtb-identity-fn-borrows.rs index 17939cf9fe0..b6216ce0589 100644 --- a/src/test/compile-fail/hrtb-identity-fn-borrows.rs +++ b/src/test/compile-fail/hrtb-identity-fn-borrows.rs @@ -11,6 +11,9 @@ // Test that the `'a` in the where clause correctly links the region // of the output to the region of the input. +// revisions: ast mir +//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir + trait FnLike<A,R> { fn call(&self, arg: A) -> R; } @@ -21,7 +24,9 @@ fn call_repeatedly<F>(f: F) // Result is stored: cannot re-assign `x` let mut x = 3; let y = f.call(&x); - x = 5; //~ ERROR cannot assign + x = 5; //[ast]~ ERROR cannot assign + //[mir]~^ ERROR cannot assign to `x` because it is borrowed (Ast) + //[mir]~| ERROR cannot assign to `x` because it is borrowed (Mir) // Result is not stored: can re-assign `x` let mut x = 3; diff --git a/src/test/compile-fail/impossible_range.rs b/src/test/compile-fail/impossible_range.rs index 94e048fed65..e4465e9f6b6 100644 --- a/src/test/compile-fail/impossible_range.rs +++ b/src/test/compile-fail/impossible_range.rs @@ -18,12 +18,12 @@ pub fn main() { ..1; 0..1; - ...; //~ERROR inclusive range with no end + ..=; //~ERROR inclusive range with no end //~^HELP bounded at the end - 0...; //~ERROR inclusive range with no end + 0..=; //~ERROR inclusive range with no end //~^HELP bounded at the end - ...1; - 0...1; + ..=1; + 0..=1; } diff --git a/src/test/compile-fail/issue-43023.rs b/src/test/compile-fail/issue-43023.rs new file mode 100644 index 00000000000..6a5f7a1136a --- /dev/null +++ b/src/test/compile-fail/issue-43023.rs @@ -0,0 +1,28 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct S; + +impl S { + #[derive(Debug)] //~ ERROR `derive` may only be applied to structs, enums and unions + fn f() { + file!(); + } +} + +trait Tr1 { + #[derive(Debug)] //~ ERROR `derive` may only be applied to structs, enums and unions + fn f(); +} + +trait Tr2 { + #[derive(Debug)] //~ ERROR `derive` may only be applied to structs, enums and unions + type F; +} diff --git a/src/test/compile-fail/issue-43733.rs b/src/test/compile-fail/issue-43733.rs index f10531e407d..90ccc589b4e 100644 --- a/src/test/compile-fail/issue-43733.rs +++ b/src/test/compile-fail/issue-43733.rs @@ -9,11 +9,13 @@ // except according to those terms. #![feature(const_fn)] +#![feature(thread_local)] #![feature(cfg_target_thread_local, thread_local_internals)] type Foo = std::cell::RefCell<String>; #[cfg(target_thread_local)] +#[thread_local] static __KEY: std::thread::__FastLocalKeyInner<Foo> = std::thread::__FastLocalKeyInner::new(); @@ -25,7 +27,7 @@ fn __getit() -> std::option::Option< &'static std::cell::UnsafeCell< std::option::Option<Foo>>> { - __KEY.get() //~ ERROR invocation of unsafe method requires unsafe + __KEY.get() //~ ERROR call to unsafe function requires unsafe } static FOO: std::thread::LocalKey<Foo> = diff --git a/src/test/compile-fail/lifetime-underscore.rs b/src/test/compile-fail/label-underscore.rs index 5b518a4931d..30411bf8789 100644 --- a/src/test/compile-fail/lifetime-underscore.rs +++ b/src/test/compile-fail/label-underscore.rs @@ -8,12 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn _f<'_>() //~ ERROR invalid lifetime name `'_` - -> &'_ u8 //~ ERROR invalid lifetime name `'_` -{ - panic!(); -} - fn main() { '_: loop { //~ ERROR invalid label name `'_` break '_ //~ ERROR invalid label name `'_` diff --git a/src/test/compile-fail/lint-stability-deprecated.rs b/src/test/compile-fail/lint-stability-deprecated.rs index 9bc2c021904..de455afbd66 100644 --- a/src/test/compile-fail/lint-stability-deprecated.rs +++ b/src/test/compile-fail/lint-stability-deprecated.rs @@ -107,6 +107,7 @@ mod cross_crate { struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable); struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated); //~^ WARN use of deprecated item + //~| WARN use of deprecated item let _ = DeprecatedStruct { //~ WARN use of deprecated item i: 0 //~ WARN use of deprecated item diff --git a/src/test/compile-fail/mut-pattern-internal-mutability.rs b/src/test/compile-fail/mut-pattern-internal-mutability.rs index b0d618328dc..3a84bd6565e 100644 --- a/src/test/compile-fail/mut-pattern-internal-mutability.rs +++ b/src/test/compile-fail/mut-pattern-internal-mutability.rs @@ -8,11 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// revisions: ast mir +//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir + fn main() { let foo = &mut 1; let &mut x = foo; - x += 1; //~ ERROR re-assignment of immutable variable + x += 1; //[ast]~ ERROR re-assignment of immutable variable + //[mir]~^ ERROR re-assignment of immutable variable `x` (Ast) + //[mir]~| ERROR re-assignment of immutable variable `x` (Mir) // explicitly mut-ify internals let &mut mut x = foo; @@ -20,5 +25,7 @@ fn main() { // check borrowing is detected successfully let &mut ref x = foo; - *foo += 1; //~ ERROR cannot assign to `*foo` because it is borrowed + *foo += 1; //[ast]~ ERROR cannot assign to `*foo` because it is borrowed + //[mir]~^ ERROR cannot assign to `*foo` because it is borrowed (Ast) + //[mir]~| ERROR cannot assign to `(*foo)` because it is borrowed (Mir) } diff --git a/src/test/compile-fail/object-lifetime-default-mybox.rs b/src/test/compile-fail/object-lifetime-default-mybox.rs index 014b0c1e80e..54657e76e97 100644 --- a/src/test/compile-fail/object-lifetime-default-mybox.rs +++ b/src/test/compile-fail/object-lifetime-default-mybox.rs @@ -34,7 +34,7 @@ fn load1<'a,'b>(a: &'a MyBox<SomeTrait>, b: &'b MyBox<SomeTrait>) -> &'b MyBox<SomeTrait> { - a //~ ERROR E0312 + a //~ ERROR lifetime mismatch } fn load2<'a>(ss: &MyBox<SomeTrait+'a>) -> MyBox<SomeTrait+'a> { diff --git a/src/test/compile-fail/private-inferred-type.rs b/src/test/compile-fail/private-inferred-type.rs index 4d41f8ba47d..973d467b112 100644 --- a/src/test/compile-fail/private-inferred-type.rs +++ b/src/test/compile-fail/private-inferred-type.rs @@ -103,10 +103,11 @@ mod adjust { fn main() { let _: m::Alias; //~ ERROR type `m::Priv` is private - let _: <m::Alias as m::TraitWithAssocTy>::AssocTy; // FIXME + //~^ ERROR type `m::Priv` is private + let _: <m::Alias as m::TraitWithAssocTy>::AssocTy; //~ ERROR type `m::Priv` is private m::Alias {}; //~ ERROR type `m::Priv` is private m::Pub { 0: m::Alias {} }; //~ ERROR type `m::Priv` is private - m::Pub { 0: loop {} }; // FIXME + m::Pub { 0: loop {} }; // OK, `m::Pub` is in value context, so it means Pub<_>, not Pub<Priv> m::Pub::static_method; //~ ERROR type `m::Priv` is private m::Pub::INHERENT_ASSOC_CONST; //~ ERROR type `m::Priv` is private m::Pub(0u8).method_with_substs::<m::Alias>(); //~ ERROR type `m::Priv` is private diff --git a/src/test/compile-fail/private-type-in-interface.rs b/src/test/compile-fail/private-type-in-interface.rs index a5581664f74..eb8c40a7dd5 100644 --- a/src/test/compile-fail/private-type-in-interface.rs +++ b/src/test/compile-fail/private-type-in-interface.rs @@ -31,7 +31,6 @@ fn f_ext(_: ext::Alias) {} //~ ERROR type `ext::Priv` is private trait Tr1 {} impl m::Alias {} //~ ERROR type `m::Priv` is private impl Tr1 for ext::Alias {} //~ ERROR type `ext::Priv` is private - //~^ ERROR type `ext::Priv` is private type A = <m::Alias as m::Trait>::X; //~ ERROR type `m::Priv` is private trait Tr2<T> {} diff --git a/src/test/compile-fail/range_inclusive_gate.rs b/src/test/compile-fail/range_inclusive_gate.rs index 1d1153e951b..69b9a4c67ad 100644 --- a/src/test/compile-fail/range_inclusive_gate.rs +++ b/src/test/compile-fail/range_inclusive_gate.rs @@ -14,7 +14,7 @@ // #![feature(inclusive_range)] pub fn main() { - let _: std::ops::RangeInclusive<_> = { use std::intrinsics; 1 } ... { use std::intrinsics; 2 }; + let _: std::ops::RangeInclusive<_> = { use std::intrinsics; 1 } ..= { use std::intrinsics; 2 }; //~^ ERROR use of unstable library feature 'inclusive_range' //~| ERROR core_intrinsics //~| ERROR core_intrinsics diff --git a/src/test/compile-fail/regions-pattern-typing-issue-19997.rs b/src/test/compile-fail/regions-pattern-typing-issue-19997.rs index ae9ceb600d4..91f5f048bc1 100644 --- a/src/test/compile-fail/regions-pattern-typing-issue-19997.rs +++ b/src/test/compile-fail/regions-pattern-typing-issue-19997.rs @@ -8,13 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// revisions: ast mir +//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir + fn main() { let a0 = 0; let f = 1; let mut a1 = &a0; match (&a1,) { (&ref b0,) => { - a1 = &f; //~ ERROR cannot assign + a1 = &f; //[ast]~ ERROR cannot assign + //[mir]~^ ERROR cannot assign to `a1` because it is borrowed (Ast) + //[mir]~| ERROR cannot assign to `a1` because it is borrowed (Mir) } } } diff --git a/src/test/compile-fail/rmeta_lib.rs b/src/test/compile-fail/rmeta_lib.rs index 3b7d1f3cc90..a61ff05e8c8 100644 --- a/src/test/compile-fail/rmeta_lib.rs +++ b/src/test/compile-fail/rmeta_lib.rs @@ -10,7 +10,7 @@ // aux-build:rmeta_meta.rs // no-prefer-dynamic -// error-pattern: crate `rmeta_meta` required to be available in rlib, but it was not available +// error-pattern: crate `rmeta_meta` required to be available in rlib format, but was not found // Check that building a non-metadata crate fails if a dependent crate is // metadata-only. diff --git a/src/test/compile-fail/synthetic-param.rs b/src/test/compile-fail/synthetic-param.rs new file mode 100644 index 00000000000..a9762e383fe --- /dev/null +++ b/src/test/compile-fail/synthetic-param.rs @@ -0,0 +1,38 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(generic_param_attrs, rustc_attrs)] + +fn func<#[rustc_synthetic] T>(_: T) {} + +struct Foo; + +impl Foo { + pub fn func<#[rustc_synthetic] T>(_: T) {} +} + +struct Bar<S> { + t: S +} + +impl<S> Bar<S> { + pub fn func<#[rustc_synthetic] T>(_: T) {} +} + +fn main() { + func::<u8>(42); //~ ERROR cannot provide explicit type parameters + func(42); // Ok + + Foo::func::<u8>(42); //~ ERROR cannot provide explicit type parameters + Foo::func(42); // Ok + + Bar::<i8>::func::<u8>(42); //~ ERROR cannot provide explicit type parameters + Bar::<i8>::func(42); // Ok +} diff --git a/src/test/compile-fail/type-path-err-node-types.rs b/src/test/compile-fail/type-path-err-node-types.rs new file mode 100644 index 00000000000..8f26777b441 --- /dev/null +++ b/src/test/compile-fail/type-path-err-node-types.rs @@ -0,0 +1,17 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Type arguments of unresolved types should have their types recorded + +fn main() { + let _: Nonexistent<u8, Assoc = u16>; //~ ERROR cannot find type `Nonexistent` in this scope + + let _ = |a, b: _| -> _ { 0 }; +} diff --git a/src/test/compile-fail/underscore-lifetime-binders.rs b/src/test/compile-fail/underscore-lifetime-binders.rs new file mode 100644 index 00000000000..99b6e036f33 --- /dev/null +++ b/src/test/compile-fail/underscore-lifetime-binders.rs @@ -0,0 +1,39 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(underscore_lifetimes)] + +struct Foo<'a>(&'a u8); +struct Baz<'a>(&'_ &'a u8); //~ ERROR missing lifetime specifier + +impl Foo<'_> { //~ ERROR missing lifetime specifier + fn x() {} +} + +fn foo<'_> //~ ERROR invalid lifetime parameter name: `'_` +(_: Foo<'_>) {} + +trait Meh<'a> {} +impl<'a> Meh<'a> for u8 {} + +fn meh() -> Box<for<'_> Meh<'_>> //~ ERROR invalid lifetime parameter name: `'_` +//~^ ERROR missing lifetime specifier +//~^^ ERROR missing lifetime specifier +{ + Box::new(5u8) +} + +fn foo2(_: &'_ u8, y: &'_ u8) -> &'_ u8 { y } //~ ERROR missing lifetime specifier + +fn main() { + let x = 5; + foo(Foo(&x)); + let _ = meh(); +} diff --git a/src/test/compile-fail/underscore-lifetime-elison-mismatch.rs b/src/test/compile-fail/underscore-lifetime-elison-mismatch.rs new file mode 100644 index 00000000000..a1c4e4a1fd9 --- /dev/null +++ b/src/test/compile-fail/underscore-lifetime-elison-mismatch.rs @@ -0,0 +1,15 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(underscore_lifetimes)] + +fn foo(x: &mut Vec<&'_ u8>, y: &'_ u8) { x.push(y); } //~ ERROR lifetime mismatch + +fn main() {} diff --git a/src/test/compile-fail/union/union-unsafe.rs b/src/test/compile-fail/union/union-unsafe.rs index 2e018e696a4..e57d65dcb89 100644 --- a/src/test/compile-fail/union/union-unsafe.rs +++ b/src/test/compile-fail/union/union-unsafe.rs @@ -42,8 +42,8 @@ fn main() { let mut u1 = U1 { a: 10 }; // OK let a = u1.a; //~ ERROR access to union field requires unsafe u1.a = 11; // OK - let U1 { a } = u1; //~ ERROR matching on union field requires unsafe - if let U1 { a: 12 } = u1 {} //~ ERROR matching on union field requires unsafe + let U1 { a } = u1; //~ ERROR access to union field requires unsafe + if let U1 { a: 12 } = u1 {} //~ ERROR access to union field requires unsafe // let U1 { .. } = u1; // OK let mut u2 = U2 { a: String::from("old") }; // OK diff --git a/src/test/compile-fail/unsafe-fn-assign-deref-ptr.rs b/src/test/compile-fail/unsafe-fn-assign-deref-ptr.rs index cff10329b85..f30da250f6a 100644 --- a/src/test/compile-fail/unsafe-fn-assign-deref-ptr.rs +++ b/src/test/compile-fail/unsafe-fn-assign-deref-ptr.rs @@ -1,3 +1,4 @@ + // Copyright 2012 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. @@ -9,7 +10,7 @@ // except according to those terms. -fn f(p: *const u8) { +fn f(p: *mut u8) { *p = 0; //~ ERROR dereference of raw pointer requires unsafe function or block return; } diff --git a/src/test/compile-fail/unsafe-move-val-init.rs b/src/test/compile-fail/unsafe-move-val-init.rs new file mode 100644 index 00000000000..84a8c84a0db --- /dev/null +++ b/src/test/compile-fail/unsafe-move-val-init.rs @@ -0,0 +1,20 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(core_intrinsics)] + +use std::intrinsics; + +// `move_val_init` has an odd desugaring, check that it is still treated +// as unsafe. +fn main() { + intrinsics::move_val_init(1 as *mut u32, 1); + //~^ ERROR dereference of raw pointer requires unsafe function or block +} diff --git a/src/test/incremental/callee_caller_cross_crate/b.rs b/src/test/incremental/callee_caller_cross_crate/b.rs index 9e56d34636f..355983e9ca1 100644 --- a/src/test/incremental/callee_caller_cross_crate/b.rs +++ b/src/test/incremental/callee_caller_cross_crate/b.rs @@ -12,6 +12,8 @@ // revisions:rpass1 rpass2 // compile-flags:-Z query-dep-graph +// ignore-test -- ignored until red/green restores cross-crate tracking fidelity + #![feature(rustc_attrs)] extern crate a; diff --git a/src/test/incremental/change_private_fn_cc/struct_point.rs b/src/test/incremental/change_private_fn_cc/struct_point.rs index a6d029515d7..d58a9bacdb5 100644 --- a/src/test/incremental/change_private_fn_cc/struct_point.rs +++ b/src/test/incremental/change_private_fn_cc/struct_point.rs @@ -15,6 +15,8 @@ // compile-flags: -Z query-dep-graph // aux-build:point.rs +// ignore-test -- ignored until red/green restores cross-crate tracking fidelity + #![feature(rustc_attrs)] #![feature(stmt_expr_attributes)] #![allow(dead_code)] diff --git a/src/test/incremental/change_private_impl_method_cc/struct_point.rs b/src/test/incremental/change_private_impl_method_cc/struct_point.rs index 05c076b9f4b..3f665f5c820 100644 --- a/src/test/incremental/change_private_impl_method_cc/struct_point.rs +++ b/src/test/incremental/change_private_impl_method_cc/struct_point.rs @@ -15,6 +15,8 @@ // compile-flags: -Z query-dep-graph // aux-build:point.rs +// ignore-test -- ignored until red/green restores cross-crate tracking fidelity + #![feature(rustc_attrs)] #![feature(stmt_expr_attributes)] #![allow(dead_code)] diff --git a/src/test/incremental/dirty_clean.rs b/src/test/incremental/dirty_clean.rs index b828cc9c70a..6d54cf53660 100644 --- a/src/test/incremental/dirty_clean.rs +++ b/src/test/incremental/dirty_clean.rs @@ -37,7 +37,7 @@ mod y { #[rustc_clean(label="TypeckTables", cfg="cfail2")] pub fn y() { - //[cfail2]~^ ERROR `TypeckTables(y::y)` not found in dep graph, but should be clean + //[cfail2]~^ ERROR `TypeckTables(y::y)` should be clean but is not x::x(); } } @@ -45,6 +45,6 @@ mod y { mod z { #[rustc_dirty(label="TypeckTables", cfg="cfail2")] pub fn z() { - //[cfail2]~^ ERROR `TypeckTables(z::z)` found in dep graph, but should be dirty + //[cfail2]~^ ERROR `TypeckTables(z::z)` should be dirty but is not } } diff --git a/src/test/incremental/hashes/enum_defs.rs b/src/test/incremental/hashes/enum_defs.rs index 0f734683b60..8f84266d5a4 100644 --- a/src/test/incremental/hashes/enum_defs.rs +++ b/src/test/incremental/hashes/enum_defs.rs @@ -143,7 +143,7 @@ enum EnumChangeValueCStyleVariant1 { #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="HirBody", cfg="cfail2")] #[rustc_clean(label="HirBody", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] diff --git a/src/test/incremental/hashes/indexing_expressions.rs b/src/test/incremental/hashes/indexing_expressions.rs index bb31982d93f..a12624d0832 100644 --- a/src/test/incremental/hashes/indexing_expressions.rs +++ b/src/test/incremental/hashes/indexing_expressions.rs @@ -153,5 +153,5 @@ fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] { #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] { - &slice[3...7] + &slice[3..=7] } diff --git a/src/test/incremental/rlib_cross_crate/b.rs b/src/test/incremental/rlib_cross_crate/b.rs index 9849e93d3ff..39065d9671a 100644 --- a/src/test/incremental/rlib_cross_crate/b.rs +++ b/src/test/incremental/rlib_cross_crate/b.rs @@ -18,6 +18,8 @@ // no-prefer-dynamic // compile-flags: -Z query-dep-graph +// ignore-test -- ignored until red/green restores cross-crate tracking fidelity + #![feature(rustc_attrs)] extern crate a; diff --git a/src/test/incremental/string_constant.rs b/src/test/incremental/string_constant.rs index 36a26cf1755..760975b292f 100644 --- a/src/test/incremental/string_constant.rs +++ b/src/test/incremental/string_constant.rs @@ -27,7 +27,8 @@ mod x { } #[cfg(rpass2)] - #[rustc_dirty(label="TypeckTables", cfg="rpass2")] + #[rustc_dirty(label="HirBody", cfg="rpass2")] + #[rustc_dirty(label="MirOptimized", cfg="rpass2")] pub fn x() { println!("{}", "2"); } @@ -37,6 +38,7 @@ mod y { use x; #[rustc_clean(label="TypeckTables", cfg="rpass2")] + #[rustc_clean(label="MirOptimized", cfg="rpass2")] pub fn y() { x::x(); } @@ -46,6 +48,7 @@ mod z { use y; #[rustc_clean(label="TypeckTables", cfg="rpass2")] + #[rustc_clean(label="MirOptimized", cfg="rpass2")] pub fn z() { y::y(); } diff --git a/src/test/incremental/struct_change_field_type_cross_crate/b.rs b/src/test/incremental/struct_change_field_type_cross_crate/b.rs index 9660f47da35..e5ec9784847 100644 --- a/src/test/incremental/struct_change_field_type_cross_crate/b.rs +++ b/src/test/incremental/struct_change_field_type_cross_crate/b.rs @@ -12,6 +12,8 @@ // revisions:rpass1 rpass2 // compile-flags: -Z query-dep-graph +// ignore-test -- ignored until red/green restores cross-crate tracking fidelity + #![feature(rustc_attrs)] extern crate a; diff --git a/src/test/incremental/type_alias_cross_crate/b.rs b/src/test/incremental/type_alias_cross_crate/b.rs index ee35a4d9b9c..63e1437f068 100644 --- a/src/test/incremental/type_alias_cross_crate/b.rs +++ b/src/test/incremental/type_alias_cross_crate/b.rs @@ -12,6 +12,8 @@ // revisions:rpass1 rpass2 rpass3 // compile-flags: -Z query-dep-graph +// ignore-test -- ignored until red/green restores cross-crate tracking fidelity + #![feature(rustc_attrs)] extern crate a; diff --git a/src/test/parse-fail/pat-ranges-1.rs b/src/test/parse-fail/pat-ranges-1.rs index e1cbb961b1b..857a3924aec 100644 --- a/src/test/parse-fail/pat-ranges-1.rs +++ b/src/test/parse-fail/pat-ranges-1.rs @@ -11,5 +11,5 @@ // Parsing of range patterns fn main() { - let macropus!() ... 11 = 12; //~ error: expected one of `:`, `;`, or `=`, found `...` + let macropus!() ..= 11 = 12; //~ error: expected one of `:`, `;`, or `=`, found `..=` } diff --git a/src/test/parse-fail/pat-ranges-2.rs b/src/test/parse-fail/pat-ranges-2.rs index 04ad5ff083b..64c749333cf 100644 --- a/src/test/parse-fail/pat-ranges-2.rs +++ b/src/test/parse-fail/pat-ranges-2.rs @@ -11,5 +11,5 @@ // Parsing of range patterns fn main() { - let 10 ... makropulos!() = 12; //~ error: expected one of `::`, `:`, `;`, or `=`, found `!` + let 10 ..= makropulos!() = 12; //~ error: expected one of `::`, `:`, `;`, or `=`, found `!` } diff --git a/src/test/parse-fail/pat-ranges-3.rs b/src/test/parse-fail/pat-ranges-3.rs index 5f7aac71d29..1327a9fab36 100644 --- a/src/test/parse-fail/pat-ranges-3.rs +++ b/src/test/parse-fail/pat-ranges-3.rs @@ -11,5 +11,5 @@ // Parsing of range patterns fn main() { - let 10 ... 10 + 3 = 12; //~ expected one of `:`, `;`, or `=`, found `+` + let 10 ..= 10 + 3 = 12; //~ expected one of `:`, `;`, or `=`, found `+` } diff --git a/src/test/parse-fail/pat-ranges-4.rs b/src/test/parse-fail/pat-ranges-4.rs index 4bbf387d1c0..c159c770250 100644 --- a/src/test/parse-fail/pat-ranges-4.rs +++ b/src/test/parse-fail/pat-ranges-4.rs @@ -11,5 +11,6 @@ // Parsing of range patterns fn main() { - let 10 - 3 ... 10 = 8; //~ error: expected one of `...`, `..`, `:`, `;`, or `=`, found `-` + let 10 - 3 ..= 10 = 8; + //~^ error: expected one of `...`, `..=`, `..`, `:`, `;`, or `=`, found `-` } diff --git a/src/test/parse-fail/range_inclusive.rs b/src/test/parse-fail/range_inclusive.rs index ce97372c668..cc32b9903b5 100644 --- a/src/test/parse-fail/range_inclusive.rs +++ b/src/test/parse-fail/range_inclusive.rs @@ -13,7 +13,7 @@ #![feature(inclusive_range_syntax, inclusive_range)] pub fn main() { - for _ in 1... {} //~ERROR inclusive range with no end + for _ in 1..= {} //~ERROR inclusive range with no end //~^HELP bounded at the end } diff --git a/src/test/parse-fail/range_inclusive_gate.rs b/src/test/parse-fail/range_inclusive_gate.rs index 30dc6fc5b20..de690c3fea3 100644 --- a/src/test/parse-fail/range_inclusive_gate.rs +++ b/src/test/parse-fail/range_inclusive_gate.rs @@ -15,21 +15,21 @@ // #![feature(inclusive_range_syntax, inclusive_range)] macro_rules! m { - () => { for _ in 1...10 {} } //~ ERROR inclusive range syntax is experimental + () => { for _ in 1..=10 {} } //~ ERROR inclusive range syntax is experimental } #[cfg(nope)] fn f() {} #[cfg(not(nope))] fn f() { - for _ in 1...10 {} //~ ERROR inclusive range syntax is experimental + for _ in 1..=10 {} //~ ERROR inclusive range syntax is experimental } #[cfg(nope)] macro_rules! n { () => {} } #[cfg(not(nope))] macro_rules! n { - () => { for _ in 1...10 {} } //~ ERROR inclusive range syntax is experimental + () => { for _ in 1..=10 {} } //~ ERROR inclusive range syntax is experimental } macro_rules! o { @@ -38,7 +38,7 @@ macro_rules! o { fn g() {} #[cfg(not(nope))] fn g() { - for _ in 1...10 {} //~ ERROR inclusive range syntax is experimental + for _ in 1..=10 {} //~ ERROR inclusive range syntax is experimental } g(); @@ -54,7 +54,7 @@ macro_rules! p { fn h() {} #[cfg(not(nope))] fn h() { - for _ in 1...10 {} //~ ERROR inclusive range syntax is experimental + for _ in 1..=10 {} //~ ERROR inclusive range syntax is experimental } h(); @@ -62,8 +62,8 @@ macro_rules! p { } pub fn main() { - for _ in 1...10 {} //~ ERROR inclusive range syntax is experimental - for _ in ...10 {} //~ ERROR inclusive range syntax is experimental + for _ in 1..=10 {} //~ ERROR inclusive range syntax is experimental + for _ in ..=10 {} //~ ERROR inclusive range syntax is experimental f(); // not allowed in cfg'ed functions diff --git a/src/test/run-make/codegen-options-parsing/Makefile b/src/test/run-make/codegen-options-parsing/Makefile index dc46a8a04ef..755e211a349 100644 --- a/src/test/run-make/codegen-options-parsing/Makefile +++ b/src/test/run-make/codegen-options-parsing/Makefile @@ -1,26 +1,28 @@ -include ../tools.mk +LOG = $(TMPDIR)/log.txt + all: #Option taking a number - $(RUSTC) -C codegen-units dummy.rs 2>&1 | \ - grep 'codegen option `codegen-units` requires a number' - $(RUSTC) -C codegen-units= dummy.rs 2>&1 | \ - grep 'incorrect value `` for codegen option `codegen-units` - a number was expected' - $(RUSTC) -C codegen-units=foo dummy.rs 2>&1 | \ - grep 'incorrect value `foo` for codegen option `codegen-units` - a number was expected' + $(RUSTC) -C codegen-units dummy.rs 2>&1 | tee $(LOG) + grep 'codegen option `codegen-units` requires a number' $(LOG) + $(RUSTC) -C codegen-units= dummy.rs 2>&1 | tee $(LOG) + grep 'incorrect value `` for codegen option `codegen-units` - a number was expected' $(LOG) + $(RUSTC) -C codegen-units=foo dummy.rs 2>&1 | tee $(LOG) + grep 'incorrect value `foo` for codegen option `codegen-units` - a number was expected' $(LOG) $(RUSTC) -C codegen-units=1 dummy.rs #Option taking a string - $(RUSTC) -C extra-filename dummy.rs 2>&1 | \ - grep 'codegen option `extra-filename` requires a string' + $(RUSTC) -C extra-filename dummy.rs 2>&1 | tee $(LOG) + grep 'codegen option `extra-filename` requires a string' $(LOG) $(RUSTC) -C extra-filename= dummy.rs 2>&1 $(RUSTC) -C extra-filename=foo dummy.rs 2>&1 #Option taking no argument - $(RUSTC) -C lto= dummy.rs 2>&1 | \ - grep 'codegen option `lto` takes no value' - $(RUSTC) -C lto=1 dummy.rs 2>&1 | \ - grep 'codegen option `lto` takes no value' - $(RUSTC) -C lto=foo dummy.rs 2>&1 | \ - grep 'codegen option `lto` takes no value' + $(RUSTC) -C lto= dummy.rs 2>&1 | tee $(LOG) + grep 'codegen option `lto` takes no value' $(LOG) + $(RUSTC) -C lto=1 dummy.rs 2>&1 | tee $(LOG) + grep 'codegen option `lto` takes no value' $(LOG) + $(RUSTC) -C lto=foo dummy.rs 2>&1 | tee $(LOG) + grep 'codegen option `lto` takes no value' $(LOG) $(RUSTC) -C lto dummy.rs # Should not link dead code... diff --git a/src/test/run-make/llvm-phase/test.rs b/src/test/run-make/llvm-phase/test.rs index 7a63871f19e..2ff4593a801 100644 --- a/src/test/run-make/llvm-phase/test.rs +++ b/src/test/run-make/llvm-phase/test.rs @@ -77,6 +77,7 @@ fn main() { .split(' ').map(|s| s.to_string()).collect(); args.push("--out-dir".to_string()); args.push(env::var("TMPDIR").unwrap()); + args.push("-Ccodegen-units=1".to_string()); let (result, _) = rustc_driver::run_compiler( &args, &mut JitCalls, Some(box JitLoader), None); diff --git a/src/test/ui/mismatched_types/E0281.rs b/src/test/run-pass-fulldeps/proc-macro/attr-cfg.rs index abb66c99fab..5a28d756df5 100644 --- a/src/test/ui/mismatched_types/E0281.rs +++ b/src/test/run-pass-fulldeps/proc-macro/attr-cfg.rs @@ -8,18 +8,32 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn foo<F: Fn(usize)>(x: F) { } +// aux-build:attr-cfg.rs +// ignore-stage1 +// revisions: foo bar +#![feature(proc_macro)] + +extern crate attr_cfg; +use attr_cfg::attr_cfg; + +#[attr_cfg] +fn outer() -> u8 { + #[cfg(foo)] + fn inner() -> u8 { 1 } + + #[cfg(bar)] + fn inner() -> u8 { 2 } + + inner() +} + +#[cfg(foo)] +fn main() { + assert_eq!(outer(), 1); +} + +#[cfg(bar)] fn main() { - foo(|y: String| { }); - //~^ ERROR E0281 - //~| ERROR E0281 - //~| NOTE implements - //~| NOTE implements - //~| NOTE requires - //~| NOTE requires - //~| NOTE expected usize, found struct `std::string::String` - //~| NOTE expected usize, found struct `std::string::String` - //~| NOTE required by `foo` - //~| NOTE required by `foo` + assert_eq!(outer(), 2); } diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-cfg.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-cfg.rs new file mode 100644 index 00000000000..9145c46cfc7 --- /dev/null +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-cfg.rs @@ -0,0 +1,32 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// no-prefer-dynamic +#![feature(proc_macro)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn attr_cfg(args: TokenStream, input: TokenStream) -> TokenStream { + let input_str = input.to_string(); + + assert_eq!(input_str, "fn outer() -> u8 { + #[cfg(foo)] + fn inner() -> u8 { 1 } + #[cfg(bar)] + fn inner() -> u8 { 2 } + inner() +}"); + + input +} diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-attr-cfg.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-attr-cfg.rs new file mode 100644 index 00000000000..787a4a470e2 --- /dev/null +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-attr-cfg.rs @@ -0,0 +1,23 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// no-prefer-dynamic +#![feature(proc_macro)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Foo, attributes(foo))] +pub fn derive(input: TokenStream) -> TokenStream { + assert!(!input.to_string().contains("#[cfg(any())]")); + "".parse().unwrap() +} diff --git a/src/test/run-pass-fulldeps/proc-macro/derive-attr-cfg.rs b/src/test/run-pass-fulldeps/proc-macro/derive-attr-cfg.rs new file mode 100644 index 00000000000..b94c45248da --- /dev/null +++ b/src/test/run-pass-fulldeps/proc-macro/derive-attr-cfg.rs @@ -0,0 +1,27 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:derive-attr-cfg.rs +// ignore-stage1 + +#![feature(proc_macro)] + +extern crate derive_attr_cfg; +use derive_attr_cfg::Foo; + +#[derive(Foo)] +#[foo] +struct S { + #[cfg(any())] + x: i32 +} + +fn main() { +} diff --git a/src/test/run-pass-valgrind/issue-44800.rs b/src/test/run-pass-valgrind/issue-44800.rs new file mode 100644 index 00000000000..cfde6f32f66 --- /dev/null +++ b/src/test/run-pass-valgrind/issue-44800.rs @@ -0,0 +1,25 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(global_allocator, alloc_system, allocator_api)] +extern crate alloc_system; + +use std::collections::VecDeque; +use alloc_system::System; + +#[global_allocator] +static ALLOCATOR: System = System; + +fn main() { + let mut deque = VecDeque::with_capacity(32); + deque.push_front(0); + deque.reserve(31); + deque.push_back(0); +} diff --git a/src/test/run-pass/for-loop-unconstrained-element-type-i32-fallback.rs b/src/test/run-pass/for-loop-unconstrained-element-type-i32-fallback.rs index b36afcf87b3..0bfc4d2264c 100644 --- a/src/test/run-pass/for-loop-unconstrained-element-type-i32-fallback.rs +++ b/src/test/run-pass/for-loop-unconstrained-element-type-i32-fallback.rs @@ -9,12 +9,12 @@ // except according to those terms. // Test that the type of `sum` falls back to `i32` here, -// and that the for loop desugaring doesn't inferfere with +// and that the for loop desugaring doesn't interfere with // that. fn main() { let mut sum = 0; for i in Vec::new() { - sum += i; + sum += &i; } } diff --git a/src/test/run-pass/ifmt.rs b/src/test/run-pass/ifmt.rs index cef2f879f9c..08e9990511f 100644 --- a/src/test/run-pass/ifmt.rs +++ b/src/test/run-pass/ifmt.rs @@ -13,6 +13,7 @@ #![allow(unused_features)] #![feature(box_syntax)] +use std::cell::RefCell; use std::fmt::{self, Write}; use std::usize; @@ -240,6 +241,8 @@ pub fn main() { // test that trailing commas are acceptable format!("{}", "test",); format!("{foo}", foo="test",); + + test_refcell(); } // Basic test to make sure that we can invoke the `write!` macro with an @@ -319,3 +322,12 @@ fn test_once() { assert_eq!(format!("{0} {0} {0} {a} {a} {a}", foo(), a=foo()), "1 1 1 2 2 2".to_string()); } + +fn test_refcell() { + let refcell = RefCell::new(5); + assert_eq!(format!("{:?}", refcell), "RefCell { value: 5 }"); + let borrow = refcell.borrow_mut(); + assert_eq!(format!("{:?}", refcell), "RefCell { value: <borrowed> }"); + drop(borrow); + assert_eq!(format!("{:?}", refcell), "RefCell { value: 5 }"); +} diff --git a/src/test/run-pass/inc-range-pat.rs b/src/test/run-pass/inc-range-pat.rs new file mode 100644 index 00000000000..5faf36eddaf --- /dev/null +++ b/src/test/run-pass/inc-range-pat.rs @@ -0,0 +1,22 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test old and new syntax for inclusive range patterns. +#![feature(dotdoteq_in_patterns)] + + +fn main() { + assert!(match 42 { 0 ... 100 => true, _ => false }); + assert!(match 42 { 0 ..= 100 => true, _ => false }); + + assert!(match 'x' { 'a' ... 'z' => true, _ => false }); + assert!(match 'x' { 'a' ..= 'z' => true, _ => false }); +} + diff --git a/src/test/run-pass/issue-44730.rs b/src/test/run-pass/issue-44730.rs new file mode 100644 index 00000000000..6e8aba01255 --- /dev/null +++ b/src/test/run-pass/issue-44730.rs @@ -0,0 +1,24 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! dox + +#![deny(missing_docs)] + +macro_rules! doc { + ($e:expr) => ( + #[doc = $e] + pub struct Foo; + ) +} + +doc!("a"); + +fn main() {} diff --git a/src/test/run-pass/num-wrapping.rs b/src/test/run-pass/num-wrapping.rs index 143759e2715..20c7f27336e 100644 --- a/src/test/run-pass/num-wrapping.rs +++ b/src/test/run-pass/num-wrapping.rs @@ -173,6 +173,15 @@ fn test_op_assigns() { tmp.$op(Wrapping($rhs)); assert_eq!(black_box(tmp), Wrapping($ans)); } + + // also test that a &Wrapping<T> right-hand side is possible + { + let mut tmp = Wrapping($initial); + tmp = black_box(tmp); + tmp.$op(&Wrapping($rhs)); + assert_eq!(black_box(tmp), Wrapping($ans)); + } + // FIXME(30524): Uncomment this test /* { diff --git a/src/test/run-pass/op-assign-builtins-by-ref.rs b/src/test/run-pass/op-assign-builtins-by-ref.rs new file mode 100644 index 00000000000..230d44ba647 --- /dev/null +++ b/src/test/run-pass/op-assign-builtins-by-ref.rs @@ -0,0 +1,84 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + // test compound assignment operators with ref as right-hand side, + // for each operator, with various types as operands. + + // test AddAssign + { + let mut x = 3i8; + x += &2i8; + assert_eq!(x, 5i8); + } + + // test SubAssign + { + let mut x = 7i16; + x -= &4; + assert_eq!(x, 3i16); + } + + // test MulAssign + { + let mut x = 3f32; + x *= &3f32; + assert_eq!(x, 9f32); + } + + // test DivAssign + { + let mut x = 6f64; + x /= &2f64; + assert_eq!(x, 3f64); + } + + // test RemAssign + { + let mut x = 7i64; + x %= &4i64; + assert_eq!(x, 3i64); + } + + // test BitOrAssign + { + let mut x = 0b1010u8; + x |= &0b1100u8; + assert_eq!(x, 0b1110u8); + } + + // test BitAndAssign + { + let mut x = 0b1010u16; + x &= &0b1100u16; + assert_eq!(x, 0b1000u16); + } + + // test BitXorAssign + { + let mut x = 0b1010u32; + x ^= &0b1100u32; + assert_eq!(x, 0b0110u32); + } + + // test ShlAssign + { + let mut x = 0b1010u64; + x <<= &2u32; + assert_eq!(x, 0b101000u64); + } + + // test ShrAssign + { + let mut x = 0b1010u64; + x >>= &2i16; + assert_eq!(x, 0b10u64); + } +} diff --git a/src/test/run-pass/range_inclusive.rs b/src/test/run-pass/range_inclusive.rs index f6119e70999..71e11804052 100644 --- a/src/test/run-pass/range_inclusive.rs +++ b/src/test/run-pass/range_inclusive.rs @@ -17,18 +17,18 @@ use std::ops::{RangeInclusive, RangeToInclusive}; fn foo() -> isize { 42 } // Test that range syntax works in return statements -fn return_range_to() -> RangeToInclusive<i32> { return ...1; } +fn return_range_to() -> RangeToInclusive<i32> { return ..=1; } pub fn main() { let mut count = 0; - for i in 0_usize...10 { + for i in 0_usize..=10 { assert!(i >= 0 && i <= 10); count += i; } assert_eq!(count, 55); let mut count = 0; - let mut range = 0_usize...10; + let mut range = 0_usize..=10; for i in range { assert!(i >= 0 && i <= 10); count += i; @@ -36,53 +36,53 @@ pub fn main() { assert_eq!(count, 55); let mut count = 0; - for i in (0_usize...10).step_by(2) { + for i in (0_usize..=10).step_by(2) { assert!(i >= 0 && i <= 10 && i % 2 == 0); count += i; } assert_eq!(count, 30); - let _ = 0_usize...4+4-3; - let _ = 0...foo(); + let _ = 0_usize..=4+4-3; + let _ = 0..=foo(); - let _ = { &42...&100 }; // references to literals are OK - let _ = ...42_usize; + let _ = { &42..=&100 }; // references to literals are OK + let _ = ..=42_usize; // Test we can use two different types with a common supertype. let x = &42; { let y = 42; - let _ = x...&y; + let _ = x..=&y; } // test collection indexing - let vec = (0...10).collect::<Vec<_>>(); + let vec = (0..=10).collect::<Vec<_>>(); let slice: &[_] = &*vec; let string = String::from("hello world"); let stir = "hello world"; - assert_eq!(&vec[3...6], &[3, 4, 5, 6]); - assert_eq!(&vec[ ...6], &[0, 1, 2, 3, 4, 5, 6]); + assert_eq!(&vec[3..=6], &[3, 4, 5, 6]); + assert_eq!(&vec[ ..=6], &[0, 1, 2, 3, 4, 5, 6]); - assert_eq!(&slice[3...6], &[3, 4, 5, 6]); - assert_eq!(&slice[ ...6], &[0, 1, 2, 3, 4, 5, 6]); + assert_eq!(&slice[3..=6], &[3, 4, 5, 6]); + assert_eq!(&slice[ ..=6], &[0, 1, 2, 3, 4, 5, 6]); - assert_eq!(&string[3...6], "lo w"); - assert_eq!(&string[ ...6], "hello w"); + assert_eq!(&string[3..=6], "lo w"); + assert_eq!(&string[ ..=6], "hello w"); - assert_eq!(&stir[3...6], "lo w"); - assert_eq!(&stir[ ...6], "hello w"); + assert_eq!(&stir[3..=6], "lo w"); + assert_eq!(&stir[ ..=6], "hello w"); // test the size hints and emptying - let mut long = 0...255u8; - let mut short = 42...42u8; + let mut long = 0..=255u8; + let mut short = 42..=42u8; assert_eq!(long.size_hint(), (256, Some(256))); assert_eq!(short.size_hint(), (1, Some(1))); long.next(); short.next(); assert_eq!(long.size_hint(), (255, Some(255))); assert_eq!(short.size_hint(), (0, Some(0))); - assert_eq!(short, 1...0); + assert_eq!(short, 1..=0); assert_eq!(long.len(), 255); assert_eq!(short.len(), 0); @@ -94,31 +94,31 @@ pub fn main() { assert_eq!(long.next(), Some(1)); assert_eq!(long.next(), Some(2)); assert_eq!(long.next_back(), Some(252)); - for i in 3...251 { + for i in 3..=251 { assert_eq!(long.next(), Some(i)); } - assert_eq!(long, 1...0); + assert_eq!(long, 1..=0); // check underflow - let mut narrow = 1...0; + let mut narrow = 1..=0; assert_eq!(narrow.next_back(), None); - assert_eq!(narrow, 1...0); - let mut zero = 0u8...0; + assert_eq!(narrow, 1..=0); + let mut zero = 0u8..=0; assert_eq!(zero.next_back(), Some(0)); assert_eq!(zero.next_back(), None); - assert_eq!(zero, 1...0); - let mut high = 255u8...255; + assert_eq!(zero, 1..=0); + let mut high = 255u8..=255; assert_eq!(high.next_back(), Some(255)); assert_eq!(high.next_back(), None); - assert_eq!(high, 1...0); + assert_eq!(high, 1..=0); // what happens if you have a nonsense range? - let mut nonsense = 10...5; + let mut nonsense = 10..=5; assert_eq!(nonsense.next(), None); - assert_eq!(nonsense, 10...5); + assert_eq!(nonsense, 10..=5); // output - assert_eq!(format!("{:?}", 0...10), "0...10"); - assert_eq!(format!("{:?}", ...10), "...10"); - assert_eq!(format!("{:?}", long), "1...0"); + assert_eq!(format!("{:?}", 0..=10), "0..=10"); + assert_eq!(format!("{:?}", ..=10), "..=10"); + assert_eq!(format!("{:?}", long), "1..=0"); } diff --git a/src/test/run-pass/range_inclusive_gate.rs b/src/test/run-pass/range_inclusive_gate.rs index 5e0ec19d6b3..570087aedbb 100644 --- a/src/test/run-pass/range_inclusive_gate.rs +++ b/src/test/run-pass/range_inclusive_gate.rs @@ -14,7 +14,7 @@ fn main() { let mut count = 0; - for i in 0_usize...10 { + for i in 0_usize..=10 { assert!(i >= 0 && i <= 10); count += i; } diff --git a/src/test/run-pass/underscore-lifetimes.rs b/src/test/run-pass/underscore-lifetimes.rs new file mode 100644 index 00000000000..ed0369353bc --- /dev/null +++ b/src/test/run-pass/underscore-lifetimes.rs @@ -0,0 +1,47 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(underscore_lifetimes)] + +struct Foo<'a>(&'a u8); + +fn foo(x: &u8) -> Foo<'_> { + Foo(x) +} + +fn foo2(x: &'_ u8) -> Foo<'_> { + Foo(x) +} + +fn foo3(x: &'_ u8) -> Foo { + Foo(x) +} + +fn foo4(_: Foo<'_>) {} + +struct Foo2<'a, 'b> { + a: &'a u8, + b: &'b u8, +} +fn foo5<'b>(foo: Foo2<'_, 'b>) -> &'b u8 { + foo.b +} + +fn main() { + let x = &5; + let _ = foo(x); + let _ = foo2(x); + let _ = foo3(x); + foo4(Foo(x)); + let _ = foo5(Foo2 { + a: x, + b: &6, + }); +} diff --git a/src/test/rustdoc/pub-method.rs b/src/test/rustdoc/pub-method.rs new file mode 100644 index 00000000000..5998734e4a2 --- /dev/null +++ b/src/test/rustdoc/pub-method.rs @@ -0,0 +1,31 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-tidy-linelength +// compile-flags: --no-defaults --passes collapse-docs --passes unindent-comments --passes strip-priv-imports + +#![crate_name = "foo"] + +// @has foo/fn.bar.html +// @has - '//*[@class="rust fn"]' 'pub fn bar() -> ' +/// foo +pub fn bar() -> usize { + 2 +} + +// @has foo/struct.Foo.html +// @has - '//*[@class="method"]' 'pub fn new()' +// @has - '//*[@class="method"]' 'fn not_pub()' +pub struct Foo(usize); + +impl Foo { + pub fn new() -> Foo { Foo(0) } + fn not_pub() {} +} diff --git a/src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr b/src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr index 7c9c4e99039..0cc3a5b6bf3 100644 --- a/src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr +++ b/src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr @@ -2,7 +2,7 @@ warning: function is never used: `lintme` --> $DIR/lint-plugin-cmdline-allow.rs:20:1 | 20 | fn lintme() { } - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ | note: lint level defined here --> $DIR/lint-plugin-cmdline-allow.rs:17:9 diff --git a/src/test/ui/block-result/issue-3563.stderr b/src/test/ui/block-result/issue-3563.stderr index 4b1f8b032b7..e3f0df6fb5f 100644 --- a/src/test/ui/block-result/issue-3563.stderr +++ b/src/test/ui/block-result/issue-3563.stderr @@ -3,6 +3,8 @@ error[E0599]: no method named `b` found for type `&Self` in the current scope | 13 | || self.b() | ^ + | + = help: did you mean `a`? error[E0308]: mismatched types --> $DIR/issue-3563.rs:13:9 diff --git a/src/test/ui/deref-suggestion.rs b/src/test/ui/deref-suggestion.rs new file mode 100644 index 00000000000..16d8226bfec --- /dev/null +++ b/src/test/ui/deref-suggestion.rs @@ -0,0 +1,34 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +macro_rules! borrow { + ($x:expr) => { &$x } +} + +fn foo(_: String) {} + +fn foo2(s: &String) { + foo(s); +} + +fn foo3(_: u32) {} +fn foo4(u: &u32) { + foo3(u); +} + +fn main() { + let s = String::new(); + let r_s = &s; + foo2(r_s); + foo(&"aaa".to_owned()); + foo(&mut "aaa".to_owned()); + foo3(borrow!(0)); + foo4(&0); +} diff --git a/src/test/ui/deref-suggestion.stderr b/src/test/ui/deref-suggestion.stderr new file mode 100644 index 00000000000..5ad9c19fa8c --- /dev/null +++ b/src/test/ui/deref-suggestion.stderr @@ -0,0 +1,59 @@ +error[E0308]: mismatched types + --> $DIR/deref-suggestion.rs:18:9 + | +18 | foo(s); + | ^ expected struct `std::string::String`, found reference + | + = note: expected type `std::string::String` + found type `&std::string::String` + = help: here are some functions which might fulfill your needs: + - .escape_debug() + - .escape_default() + - .escape_unicode() + - .to_lowercase() + - .to_uppercase() + +error[E0308]: mismatched types + --> $DIR/deref-suggestion.rs:23:10 + | +23 | foo3(u); + | ^ expected u32, found &u32 + | + = note: expected type `u32` + found type `&u32` + = help: try with `*u` + +error[E0308]: mismatched types + --> $DIR/deref-suggestion.rs:30:9 + | +30 | foo(&"aaa".to_owned()); + | ^^^^^^^^^^^^^^^^^ expected struct `std::string::String`, found reference + | + = note: expected type `std::string::String` + found type `&std::string::String` + = help: try with `"aaa".to_owned()` + +error[E0308]: mismatched types + --> $DIR/deref-suggestion.rs:31:9 + | +31 | foo(&mut "aaa".to_owned()); + | ^^^^^^^^^^^^^^^^^^^^^ expected struct `std::string::String`, found mutable reference + | + = note: expected type `std::string::String` + found type `&mut std::string::String` + = help: try with `"aaa".to_owned()` + +error[E0308]: mismatched types + --> $DIR/deref-suggestion.rs:12:20 + | +12 | ($x:expr) => { &$x } + | ^^^ expected u32, found &{integer} +... +32 | foo3(borrow!(0)); + | ---------- in this macro invocation + | + = note: expected type `u32` + found type `&{integer}` + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr index 9e4f6c42179..cb9a1edf1dd 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr @@ -1,27 +1,13 @@ -error[E0312]: lifetime of reference outlives lifetime of borrowed content... +error[E0623]: lifetime mismatch --> $DIR/ex1-return-one-existing-name-if-else-using-impl.rs:21:20 | +19 | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { + | ---- ------- + | | + | this parameter and the return type are declared with different lifetimes... +20 | 21 | if x > y { x } else { y } - | ^ - | -note: ...the reference is valid for the lifetime 'a as defined on the method body at 19:5... - --> $DIR/ex1-return-one-existing-name-if-else-using-impl.rs:19:5 - | -19 | / fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { -20 | | -21 | | if x > y { x } else { y } -22 | | -23 | | } - | |_____^ -note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the method body at 19:5 - --> $DIR/ex1-return-one-existing-name-if-else-using-impl.rs:19:5 - | -19 | / fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { -20 | | -21 | | if x > y { x } else { y } -22 | | -23 | | } - | |_____^ + | ^ ...but data from `x` is returned here error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr index e3fd0192053..8af6acc62c4 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr @@ -1,27 +1,13 @@ -error[E0312]: lifetime of reference outlives lifetime of borrowed content... +error[E0623]: lifetime mismatch --> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:18:5 | +16 | fn foo<'a>(&self, x: &'a i32) -> &i32 { + | ------- ---- + | | + | this parameter and the return type are declared with different lifetimes... +17 | 18 | x - | ^ - | -note: ...the reference is valid for the anonymous lifetime #1 defined on the method body at 16:3... - --> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:16:3 - | -16 | / fn foo<'a>(&self, x: &'a i32) -> &i32 { -17 | | -18 | | x -19 | | -20 | | } - | |___^ -note: ...but the borrowed content is only valid for the lifetime 'a as defined on the method body at 16:3 - --> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:16:3 - | -16 | / fn foo<'a>(&self, x: &'a i32) -> &i32 { -17 | | -18 | | x -19 | | -20 | | } - | |___^ + | ^ ...but data from `x` is returned here error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr index 8551f015db5..c09de0c33af 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr @@ -1,27 +1,13 @@ -error[E0312]: lifetime of reference outlives lifetime of borrowed content... +error[E0623]: lifetime mismatch --> $DIR/ex1-return-one-existing-name-self-is-anon.rs:18:30 | +16 | fn foo<'a>(&self, x: &'a Foo) -> &'a Foo { + | ----- ------- + | | + | this parameter and the return type are declared with different lifetimes... +17 | 18 | if true { x } else { self } - | ^^^^ - | -note: ...the reference is valid for the lifetime 'a as defined on the method body at 16:5... - --> $DIR/ex1-return-one-existing-name-self-is-anon.rs:16:5 - | -16 | / fn foo<'a>(&self, x: &'a Foo) -> &'a Foo { -17 | | -18 | | if true { x } else { self } -19 | | -20 | | } - | |_____^ -note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the method body at 16:5 - --> $DIR/ex1-return-one-existing-name-self-is-anon.rs:16:5 - | -16 | / fn foo<'a>(&self, x: &'a Foo) -> &'a Foo { -17 | | -18 | | if true { x } else { self } -19 | | -20 | | } - | |_____^ + | ^^^^ ...but data from `self` is returned here error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr index 1b5ac7c7b57..73460277de4 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr @@ -4,7 +4,7 @@ error[E0623]: lifetime mismatch 15 | fn foo(mut x: Ref) { | --- | | - | this type was declared with multiple lifetimes... + | this type is declared with multiple lifetimes... 16 | x.a = x.b; | ^^^ ...but data with one lifetime flows into the other here diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.stderr index 689a1ac292b..fb524ae62c5 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.stderr @@ -4,7 +4,7 @@ error[E0623]: lifetime mismatch 15 | fn foo(mut x: Ref) { | --- | | - | this type was declared with multiple lifetimes... + | this type is declared with multiple lifetimes... 16 | x.a = x.b; | ^^^ ...but data with one lifetime flows into the other here diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr index 890f9b311e7..1409b216133 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr @@ -1,23 +1,12 @@ -error[E0312]: lifetime of reference outlives lifetime of borrowed content... +error[E0623]: lifetime mismatch --> $DIR/ex3-both-anon-regions-return-type-is-anon.rs:17:5 | +16 | fn foo<'a>(&self, x: &i32) -> &i32 { + | ---- ---- + | | + | this parameter and the return type are declared with different lifetimes... 17 | x - | ^ - | -note: ...the reference is valid for the anonymous lifetime #1 defined on the method body at 16:3... - --> $DIR/ex3-both-anon-regions-return-type-is-anon.rs:16:3 - | -16 | / fn foo<'a>(&self, x: &i32) -> &i32 { -17 | | x -18 | | } - | |___^ -note: ...but the borrowed content is only valid for the anonymous lifetime #2 defined on the method body at 16:3 - --> $DIR/ex3-both-anon-regions-return-type-is-anon.rs:16:3 - | -16 | / fn foo<'a>(&self, x: &i32) -> &i32 { -17 | | x -18 | | } - | |___^ + | ^ ...but data from `x` is returned here error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr index 43f00c32c62..cae45023e26 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr @@ -1,23 +1,12 @@ -error[E0312]: lifetime of reference outlives lifetime of borrowed content... +error[E0623]: lifetime mismatch --> $DIR/ex3-both-anon-regions-self-is-anon.rs:17:19 | +16 | fn foo<'a>(&self, x: &Foo) -> &Foo { + | ---- ---- + | | + | this parameter and the return type are declared with different lifetimes... 17 | if true { x } else { self } - | ^ - | -note: ...the reference is valid for the anonymous lifetime #1 defined on the method body at 16:5... - --> $DIR/ex3-both-anon-regions-self-is-anon.rs:16:5 - | -16 | / fn foo<'a>(&self, x: &Foo) -> &Foo { -17 | | if true { x } else { self } -18 | | } - | |_____^ -note: ...but the borrowed content is only valid for the anonymous lifetime #2 defined on the method body at 16:5 - --> $DIR/ex3-both-anon-regions-self-is-anon.rs:16:5 - | -16 | / fn foo<'a>(&self, x: &Foo) -> &Foo { -17 | | if true { x } else { self } -18 | | } - | |_____^ + | ^ ...but data from `x` is returned here error: aborting due to previous error diff --git a/src/test/compile-fail/issue-16747.rs b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.rs index dd7e8a869ec..465b4271035 100644 --- a/src/test/compile-fail/issue-16747.rs +++ b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.rs @@ -16,14 +16,16 @@ trait Collection { fn len(&self) -> usize; } struct List<'a, T: ListItem<'a>> { slice: &'a [T] -//~^ ERROR the parameter type `T` may not live long enough -//~| HELP consider adding an explicit lifetime bound -//~| NOTE ...so that the reference type `&'a [T]` does not outlive the data it points at } + impl<'a, T: ListItem<'a>> Collection for List<'a, T> { fn len(&self) -> usize { 0 } } +struct Foo<T> { + foo: &'static T +} + fn main() {} diff --git a/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr new file mode 100644 index 00000000000..e17a660c591 --- /dev/null +++ b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr @@ -0,0 +1,30 @@ +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/lifetime-doesnt-live-long-enough.rs:18:5 + | +17 | struct List<'a, T: ListItem<'a>> { + | -- help: consider adding an explicit lifetime bound `T: 'a`... +18 | slice: &'a [T] + | ^^^^^^^^^^^^^^ + | +note: ...so that the reference type `&'a [T]` does not outlive the data it points at + --> $DIR/lifetime-doesnt-live-long-enough.rs:18:5 + | +18 | slice: &'a [T] + | ^^^^^^^^^^^^^^ + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/lifetime-doesnt-live-long-enough.rs:28:5 + | +27 | struct Foo<T> { + | - help: consider adding an explicit lifetime bound `T: 'static`... +28 | foo: &'static T + | ^^^^^^^^^^^^^^^ + | +note: ...so that the reference type `&'static T` does not outlive the data it points at + --> $DIR/lifetime-doesnt-live-long-enough.rs:28:5 + | +28 | foo: &'static T + | ^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/mismatched_types/E0281.stderr b/src/test/ui/mismatched_types/E0281.stderr deleted file mode 100644 index 744e8c30939..00000000000 --- a/src/test/ui/mismatched_types/E0281.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0281]: type mismatch: `[closure@$DIR/E0281.rs:14:9: 14:24]` implements the trait `std::ops::Fn<(std::string::String,)>`, but the trait `std::ops::Fn<(usize,)>` is required - --> $DIR/E0281.rs:14:5 - | -14 | foo(|y: String| { }); - | ^^^ --------------- implements `std::ops::Fn<(std::string::String,)>` - | | - | expected usize, found struct `std::string::String` - | requires `std::ops::Fn<(usize,)>` - | - = note: required by `foo` - -error: aborting due to previous error - diff --git a/src/test/ui/mismatched_types/E0631.rs b/src/test/ui/mismatched_types/E0631.rs new file mode 100644 index 00000000000..e28f15ab0b6 --- /dev/null +++ b/src/test/ui/mismatched_types/E0631.rs @@ -0,0 +1,21 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(unboxed_closures)] + +fn foo<F: Fn(usize)>(_: F) {} +fn bar<F: Fn<usize>>(_: F) {} +fn main() { + fn f(_: u64) {} + foo(|_: isize| {}); + bar(|_: isize| {}); + foo(f); + bar(f); +} diff --git a/src/test/ui/mismatched_types/E0631.stderr b/src/test/ui/mismatched_types/E0631.stderr new file mode 100644 index 00000000000..235e7a10063 --- /dev/null +++ b/src/test/ui/mismatched_types/E0631.stderr @@ -0,0 +1,44 @@ +error[E0631]: type mismatch in closure arguments + --> $DIR/E0631.rs:17:5 + | +17 | foo(|_: isize| {}); + | ^^^ ------------- found signature of `fn(isize) -> _` + | | + | expected signature of `fn(usize) -> _` + | + = note: required by `foo` + +error[E0631]: type mismatch in closure arguments + --> $DIR/E0631.rs:18:5 + | +18 | bar(|_: isize| {}); + | ^^^ ------------- found signature of `fn(isize) -> _` + | | + | expected signature of `fn(usize) -> _` + | + = note: required by `bar` + +error[E0631]: type mismatch in function arguments + --> $DIR/E0631.rs:19:5 + | +19 | foo(f); + | ^^^ + | | + | expected signature of `fn(usize) -> _` + | found signature of `fn(u64) -> _` + | + = note: required by `foo` + +error[E0631]: type mismatch in function arguments + --> $DIR/E0631.rs:20:5 + | +20 | bar(f); + | ^^^ + | | + | expected signature of `fn(usize) -> _` + | found signature of `fn(u64) -> _` + | + = note: required by `bar` + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/mismatched_types/closure-arg-count.rs b/src/test/ui/mismatched_types/closure-arg-count.rs index 284f82d86eb..f94471a73ca 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.rs +++ b/src/test/ui/mismatched_types/closure-arg-count.rs @@ -8,8 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(unboxed_closures)] + +fn f<F: Fn<usize>>(_: F) {} fn main() { [1, 2, 3].sort_by(|| panic!()); [1, 2, 3].sort_by(|tuple| panic!()); [1, 2, 3].sort_by(|(tuple, tuple2)| panic!()); + f(|| panic!()); } diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr index ca71154e872..3031a77b1e8 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.stderr +++ b/src/test/ui/mismatched_types/closure-arg-count.stderr @@ -1,35 +1,45 @@ error[E0593]: closure takes 0 arguments but 2 arguments are required - --> $DIR/closure-arg-count.rs:12:15 + --> $DIR/closure-arg-count.rs:15:15 | -12 | [1, 2, 3].sort_by(|| panic!()); +15 | [1, 2, 3].sort_by(|| panic!()); | ^^^^^^^ ----------- takes 0 arguments | | | expected closure that takes 2 arguments error[E0593]: closure takes 1 argument but 2 arguments are required - --> $DIR/closure-arg-count.rs:13:15 + --> $DIR/closure-arg-count.rs:16:15 | -13 | [1, 2, 3].sort_by(|tuple| panic!()); +16 | [1, 2, 3].sort_by(|tuple| panic!()); | ^^^^^^^ ---------------- takes 1 argument | | | expected closure that takes 2 arguments error[E0308]: mismatched types - --> $DIR/closure-arg-count.rs:14:24 + --> $DIR/closure-arg-count.rs:17:24 | -14 | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!()); +17 | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!()); | ^^^^^^^^^^^^^^^ expected &{integer}, found tuple | = note: expected type `&{integer}` found type `(_, _)` error[E0593]: closure takes 1 argument but 2 arguments are required - --> $DIR/closure-arg-count.rs:14:15 + --> $DIR/closure-arg-count.rs:17:15 | -14 | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!()); +17 | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!()); | ^^^^^^^ -------------------------- takes 1 argument | | | expected closure that takes 2 arguments -error: aborting due to 4 previous errors +error[E0593]: closure takes 0 arguments but 1 argument is required + --> $DIR/closure-arg-count.rs:18:5 + | +18 | f(|| panic!()); + | ^ ----------- takes 0 arguments + | | + | expected closure that takes 1 argument + | + = note: required by `f` + +error: aborting due to 5 previous errors diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs new file mode 100644 index 00000000000..aa9dba4c3f4 --- /dev/null +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs @@ -0,0 +1,21 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let a = [(1u32, 2u32)]; + a.iter().map(|_: (u32, u32)| 45); + a.iter().map(|_: &(u16, u16)| 45); + a.iter().map(|_: (u16, u16)| 45); +} + +fn baz<F: Fn(*mut &u32)>(_: F) {} +fn _test<'a>(f: fn(*mut &'a u32)) { + baz(f); +} diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr new file mode 100644 index 00000000000..866a024ab08 --- /dev/null +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -0,0 +1,45 @@ +error[E0631]: type mismatch in closure arguments + --> $DIR/closure-arg-type-mismatch.rs:13:14 + | +13 | a.iter().map(|_: (u32, u32)| 45); + | ^^^ ------------------ found signature of `fn((u32, u32)) -> _` + | | + | expected signature of `fn(&(u32, u32)) -> _` + +error[E0631]: type mismatch in closure arguments + --> $DIR/closure-arg-type-mismatch.rs:14:14 + | +14 | a.iter().map(|_: &(u16, u16)| 45); + | ^^^ ------------------- found signature of `for<'r> fn(&'r (u16, u16)) -> _` + | | + | expected signature of `fn(&(u32, u32)) -> _` + +error[E0631]: type mismatch in closure arguments + --> $DIR/closure-arg-type-mismatch.rs:15:14 + | +15 | a.iter().map(|_: (u16, u16)| 45); + | ^^^ ------------------ found signature of `fn((u16, u16)) -> _` + | | + | expected signature of `fn(&(u32, u32)) -> _` + +error[E0631]: type mismatch in function arguments + --> $DIR/closure-arg-type-mismatch.rs:20:5 + | +20 | baz(f); + | ^^^ + | | + | expected signature of `for<'r> fn(*mut &'r u32) -> _` + | found signature of `fn(*mut &'a u32) -> _` + | + = note: required by `baz` + +error[E0271]: type mismatch resolving `for<'r> <fn(*mut &'a u32) as std::ops::FnOnce<(*mut &'r u32,)>>::Output == ()` + --> $DIR/closure-arg-type-mismatch.rs:20:5 + | +20 | baz(f); + | ^^^ expected bound lifetime parameter, found concrete lifetime + | + = note: required by `baz` + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr index d928a6a0a8e..a54fd118cc5 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-mismatch.stderr @@ -7,14 +7,13 @@ error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/closure-mismatch.r = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:18:9: 18:15]` = note: required by `baz` -error[E0281]: type mismatch: `[closure@$DIR/closure-mismatch.rs:18:9: 18:15]` implements the trait `std::ops::Fn<(_,)>`, but the trait `for<'r> std::ops::Fn<(&'r (),)>` is required +error[E0631]: type mismatch in closure arguments --> $DIR/closure-mismatch.rs:18:5 | 18 | baz(|_| ()); - | ^^^ ------ implements `std::ops::Fn<(_,)>` + | ^^^ ------ found signature of `fn(_) -> _` | | - | expected concrete lifetime, found bound lifetime parameter - | requires `for<'r> std::ops::Fn<(&'r (),)>` + | expected signature of `for<'r> fn(&'r ()) -> _` | = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:18:9: 18:15]` = note: required by `baz` diff --git a/src/test/ui/mismatched_types/fn-variance-1.stderr b/src/test/ui/mismatched_types/fn-variance-1.stderr index 120fb87cdc8..09a90ef3d6b 100644 --- a/src/test/ui/mismatched_types/fn-variance-1.stderr +++ b/src/test/ui/mismatched_types/fn-variance-1.stderr @@ -1,16 +1,22 @@ -error[E0281]: type mismatch: `fn(&mut isize) {takes_mut}` implements the trait `for<'r> std::ops::FnOnce<(&'r mut isize,)>`, but the trait `std::ops::FnOnce<(&{integer},)>` is required +error[E0631]: type mismatch in function arguments --> $DIR/fn-variance-1.rs:21:5 | 21 | apply(&3, takes_mut); - | ^^^^^ types differ in mutability + | ^^^^^ + | | + | expected signature of `fn(&{integer}) -> _` + | found signature of `for<'r> fn(&'r mut isize) -> _` | = note: required by `apply` -error[E0281]: type mismatch: `fn(&isize) {takes_imm}` implements the trait `for<'r> std::ops::FnOnce<(&'r isize,)>`, but the trait `std::ops::FnOnce<(&mut {integer},)>` is required +error[E0631]: type mismatch in function arguments --> $DIR/fn-variance-1.rs:27:5 | 27 | apply(&mut 3, takes_imm); - | ^^^^^ types differ in mutability + | ^^^^^ + | | + | expected signature of `fn(&mut {integer}) -> _` + | found signature of `for<'r> fn(&'r isize) -> _` | = note: required by `apply` diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index e2e2019307f..71a3a0a5714 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -8,14 +8,13 @@ error[E0599]: no method named `count` found for type `std::iter::Filter<std::ite `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:17:39: 17:53]> : std::iter::Iterator` `&mut std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:17:39: 17:53]> : std::iter::Iterator` -error[E0281]: type mismatch: `[closure@$DIR/issue-36053-2.rs:17:39: 17:53]` implements the trait `for<'r> std::ops::FnMut<(&'r str,)>`, but the trait `for<'r> std::ops::FnMut<(&'r &str,)>` is required +error[E0631]: type mismatch in closure arguments --> $DIR/issue-36053-2.rs:17:32 | 17 | once::<&str>("str").fuse().filter(|a: &str| true).count(); - | ^^^^^^ -------------- implements `for<'r> std::ops::FnMut<(&'r str,)>` + | ^^^^^^ -------------- found signature of `for<'r> fn(&'r str) -> _` | | - | expected &str, found str - | requires `for<'r> std::ops::FnMut<(&'r &str,)>` + | expected signature of `for<'r> fn(&'r &str) -> _` error: aborting due to 2 previous errors diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr index f14e711b23a..59883649280 100644 --- a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr +++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr @@ -1,14 +1,11 @@ -error[E0281]: type mismatch: `[closure@$DIR/unboxed-closures-vtable-mismatch.rs:22:23: 22:73]` implements the trait `std::ops::FnMut<(usize, isize)>`, but the trait `std::ops::FnMut<(isize, isize)>` is required +error[E0631]: type mismatch in closure arguments --> $DIR/unboxed-closures-vtable-mismatch.rs:25:13 | 22 | let f = to_fn_mut(|x: usize, y: isize| -> isize { (x as isize) + y }); - | -------------------------------------------------- implements `std::ops::FnMut<(usize, isize)>` + | -------------------------------------------------- found signature of `fn(usize, isize) -> _` ... 25 | let z = call_it(3, f); - | ^^^^^^^ - | | - | expected isize, found usize - | requires `std::ops::FnMut<(isize, isize)>` + | ^^^^^^^ expected signature of `fn(isize, isize) -> _` | = note: required by `call_it` diff --git a/src/test/ui/path-lookahead.stderr b/src/test/ui/path-lookahead.stderr index 9936a1eb81e..1d4ab35046b 100644 --- a/src/test/ui/path-lookahead.stderr +++ b/src/test/ui/path-lookahead.stderr @@ -9,10 +9,8 @@ warning: unnecessary parentheses around `return` value warning: function is never used: `with_parens` --> $DIR/path-lookahead.rs:17:1 | -17 | / fn with_parens<T: ToString>(arg: T) -> String { //~WARN function is never used: `with_parens` -18 | | return (<T as ToString>::to_string(&arg)); //~WARN unnecessary parentheses around `return` value -19 | | } - | |_^ +17 | fn with_parens<T: ToString>(arg: T) -> String { //~WARN function is never used: `with_parens` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: lint level defined here --> $DIR/path-lookahead.rs:13:9 @@ -24,8 +22,6 @@ note: lint level defined here warning: function is never used: `no_parens` --> $DIR/path-lookahead.rs:21:1 | -21 | / fn no_parens<T: ToString>(arg: T) -> String { //~WARN function is never used: `no_parens` -22 | | return <T as ToString>::to_string(&arg); -23 | | } - | |_^ +21 | fn no_parens<T: ToString>(arg: T) -> String { //~WARN function is never used: `no_parens` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr index ee1481ec6f2..f7e5c602644 100644 --- a/src/test/ui/resolve/privacy-struct-ctor.stderr +++ b/src/test/ui/resolve/privacy-struct-ctor.stderr @@ -10,7 +10,7 @@ error[E0423]: expected value, found struct `Z` | help: possible better candidate is found in another module, you can import it into scope | -16 | use m::n::Z; +22 | use m::n::Z; | error[E0423]: expected value, found struct `S` @@ -24,7 +24,7 @@ error[E0423]: expected value, found struct `S` | help: possible better candidate is found in another module, you can import it into scope | -15 | use m::S; +32 | use m::S; | error[E0423]: expected value, found struct `xcrate::S` @@ -38,7 +38,7 @@ error[E0423]: expected value, found struct `xcrate::S` | help: possible better candidate is found in another module, you can import it into scope | -15 | use m::S; +32 | use m::S; | error[E0603]: tuple struct `Z` is private diff --git a/src/test/ui/resolve/use_suggestion_placement.rs b/src/test/ui/resolve/use_suggestion_placement.rs index e0027fed4d6..a43b8fc99df 100644 --- a/src/test/ui/resolve/use_suggestion_placement.rs +++ b/src/test/ui/resolve/use_suggestion_placement.rs @@ -16,6 +16,15 @@ mod m { pub const A: i32 = 0; } +mod foo { + #[derive(Debug)] + pub struct Foo; + + // test whether the use suggestion isn't + // placed into the expansion of `#[derive(Debug)] + type Bar = Path; +} + fn main() { y!(); let _ = A; diff --git a/src/test/ui/resolve/use_suggestion_placement.stderr b/src/test/ui/resolve/use_suggestion_placement.stderr index 5c74d8bed66..8a4dfdc8027 100644 --- a/src/test/ui/resolve/use_suggestion_placement.stderr +++ b/src/test/ui/resolve/use_suggestion_placement.stderr @@ -1,7 +1,18 @@ +error[E0412]: cannot find type `Path` in this scope + --> $DIR/use_suggestion_placement.rs:25:16 + | +25 | type Bar = Path; + | ^^^^ not found in this scope + | +help: possible candidate is found in another module, you can import it into scope + | +21 | use std::path::Path; + | + error[E0425]: cannot find value `A` in this scope - --> $DIR/use_suggestion_placement.rs:21:13 + --> $DIR/use_suggestion_placement.rs:30:13 | -21 | let _ = A; +30 | let _ = A; | ^ not found in this scope | help: possible candidate is found in another module, you can import it into scope @@ -10,9 +21,9 @@ help: possible candidate is found in another module, you can import it into scop | error[E0412]: cannot find type `HashMap` in this scope - --> $DIR/use_suggestion_placement.rs:26:23 + --> $DIR/use_suggestion_placement.rs:35:23 | -26 | type Dict<K, V> = HashMap<K, V>; +35 | type Dict<K, V> = HashMap<K, V>; | ^^^^^^^ not found in this scope | help: possible candidates are found in other modules, you can import them into scope @@ -23,16 +34,16 @@ help: possible candidates are found in other modules, you can import them into s | error[E0091]: type parameter `K` is unused - --> $DIR/use_suggestion_placement.rs:26:15 + --> $DIR/use_suggestion_placement.rs:35:15 | -26 | type Dict<K, V> = HashMap<K, V>; +35 | type Dict<K, V> = HashMap<K, V>; | ^ unused type parameter error[E0091]: type parameter `V` is unused - --> $DIR/use_suggestion_placement.rs:26:18 + --> $DIR/use_suggestion_placement.rs:35:18 | -26 | type Dict<K, V> = HashMap<K, V>; +35 | type Dict<K, V> = HashMap<K, V>; | ^ unused type parameter -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors diff --git a/src/test/ui/rfc_1940-must_use_on_functions/fn_must_use.rs b/src/test/ui/rfc_1940-must_use_on_functions/fn_must_use.rs index 7eb4c32972a..3741ba4f3ae 100644 --- a/src/test/ui/rfc_1940-must_use_on_functions/fn_must_use.rs +++ b/src/test/ui/rfc_1940-must_use_on_functions/fn_must_use.rs @@ -11,6 +11,7 @@ #![feature(fn_must_use)] #![warn(unused_must_use)] +#[derive(PartialEq, Eq)] struct MyStruct { n: usize, } @@ -58,13 +59,18 @@ fn main() { need_to_use_this_value(); let mut m = MyStruct { n: 2 }; + let n = MyStruct { n: 3 }; + m.need_to_use_this_method_value(); m.is_even(); // trait method! - m.replace(3); + m.replace(3); // won't warn (annotation needs to be in trait definition) + // comparison methods are `must_use` 2.eq(&3); + m.eq(&n); - // FIXME: operators should probably be `must_use` if underlying method is + // lint includes comparison operators 2 == 3; + m == n; } diff --git a/src/test/ui/rfc_1940-must_use_on_functions/fn_must_use.stderr b/src/test/ui/rfc_1940-must_use_on_functions/fn_must_use.stderr index 69755c89b48..fdd0a591bc7 100644 --- a/src/test/ui/rfc_1940-must_use_on_functions/fn_must_use.stderr +++ b/src/test/ui/rfc_1940-must_use_on_functions/fn_must_use.stderr @@ -1,7 +1,7 @@ warning: unused return value of `need_to_use_this_value` which must be used: it's important - --> $DIR/fn_must_use.rs:58:5 + --> $DIR/fn_must_use.rs:59:5 | -58 | need_to_use_this_value(); +59 | need_to_use_this_value(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: lint level defined here @@ -11,20 +11,38 @@ note: lint level defined here | ^^^^^^^^^^^^^^^ warning: unused return value of `MyStruct::need_to_use_this_method_value` which must be used - --> $DIR/fn_must_use.rs:61:5 + --> $DIR/fn_must_use.rs:64:5 | -61 | m.need_to_use_this_method_value(); +64 | m.need_to_use_this_method_value(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused return value of `EvenNature::is_even` which must be used: no side effects - --> $DIR/fn_must_use.rs:62:5 + --> $DIR/fn_must_use.rs:65:5 | -62 | m.is_even(); // trait method! +65 | m.is_even(); // trait method! | ^^^^^^^^^^^^ warning: unused return value of `std::cmp::PartialEq::eq` which must be used - --> $DIR/fn_must_use.rs:66:5 + --> $DIR/fn_must_use.rs:70:5 | -66 | 2.eq(&3); +70 | 2.eq(&3); | ^^^^^^^^^ +warning: unused return value of `std::cmp::PartialEq::eq` which must be used + --> $DIR/fn_must_use.rs:71:5 + | +71 | m.eq(&n); + | ^^^^^^^^^ + +warning: unused comparison which must be used + --> $DIR/fn_must_use.rs:74:5 + | +74 | 2 == 3; + | ^^^^^^ + +warning: unused comparison which must be used + --> $DIR/fn_must_use.rs:75:5 + | +75 | m == n; + | ^^^^^^ + diff --git a/src/test/ui/span/issue-35987.stderr b/src/test/ui/span/issue-35987.stderr index 0cd7e1046f6..b57b58e3d2a 100644 --- a/src/test/ui/span/issue-35987.stderr +++ b/src/test/ui/span/issue-35987.stderr @@ -6,7 +6,7 @@ error[E0404]: expected trait, found type parameter `Add` | help: possible better candidate is found in another module, you can import it into scope | -11 | use std::ops::Add; +13 | use std::ops::Add; | error[E0601]: main function not found diff --git a/src/test/ui/span/issue-43927-non-ADT-derive.rs b/src/test/ui/span/issue-43927-non-ADT-derive.rs new file mode 100644 index 00000000000..cf2a4b8d037 --- /dev/null +++ b/src/test/ui/span/issue-43927-non-ADT-derive.rs @@ -0,0 +1,16 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(dead_code)] + +#![derive(Debug, PartialEq, Eq)] // should be an outer attribute! +struct DerivedOn; + +fn main() {} diff --git a/src/test/ui/span/issue-43927-non-ADT-derive.stderr b/src/test/ui/span/issue-43927-non-ADT-derive.stderr new file mode 100644 index 00000000000..a0485bed2f4 --- /dev/null +++ b/src/test/ui/span/issue-43927-non-ADT-derive.stderr @@ -0,0 +1,8 @@ +error: `derive` may only be applied to structs, enums and unions + --> $DIR/issue-43927-non-ADT-derive.rs:13:1 + | +13 | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute! + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try an outer attribute: `#[derive(Debug, PartialEq, Eq)]` + +error: aborting due to previous error + diff --git a/src/test/ui/span/unused-warning-point-at-signature.rs b/src/test/ui/span/unused-warning-point-at-signature.rs new file mode 100644 index 00000000000..eb659d08da0 --- /dev/null +++ b/src/test/ui/span/unused-warning-point-at-signature.rs @@ -0,0 +1,40 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-pass + +#![warn(unused)] + +enum Enum { + A, + B, + C, + D, +} + +struct Struct { + a: usize, + b: usize, + c: usize, + d: usize, +} + +fn func() -> usize { + 3 +} + +fn +func_complete_span() +-> usize +{ + 3 +} + +fn main() {} diff --git a/src/test/ui/span/unused-warning-point-at-signature.stderr b/src/test/ui/span/unused-warning-point-at-signature.stderr new file mode 100644 index 00000000000..8e658670e9c --- /dev/null +++ b/src/test/ui/span/unused-warning-point-at-signature.stderr @@ -0,0 +1,36 @@ +warning: enum is never used: `Enum` + --> $DIR/unused-warning-point-at-signature.rs:15:1 + | +15 | enum Enum { + | ^^^^^^^^^ + | +note: lint level defined here + --> $DIR/unused-warning-point-at-signature.rs:13:9 + | +13 | #![warn(unused)] + | ^^^^^^ + = note: #[warn(dead_code)] implied by #[warn(unused)] + +warning: struct is never used: `Struct` + --> $DIR/unused-warning-point-at-signature.rs:22:1 + | +22 | struct Struct { + | ^^^^^^^^^^^^^ + +warning: function is never used: `func` + --> $DIR/unused-warning-point-at-signature.rs:29:1 + | +29 | fn func() -> usize { + | ^^^^^^^^^^^^^^^^^^ + +warning: function is never used: `func_complete_span` + --> $DIR/unused-warning-point-at-signature.rs:33:1 + | +33 | / fn +34 | | func_complete_span() +35 | | -> usize +36 | | { +37 | | 3 +38 | | } + | |_^ + diff --git a/src/test/ui/suggestions/suggest-methods.rs b/src/test/ui/suggestions/suggest-methods.rs new file mode 100644 index 00000000000..b02881dc7ee --- /dev/null +++ b/src/test/ui/suggestions/suggest-methods.rs @@ -0,0 +1,40 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Foo; + +impl Foo { + fn bar(self) {} + fn baz(&self, x: f64) {} +} + +trait FooT { + fn bag(&self); +} + +impl FooT for Foo { + fn bag(&self) {} +} + +fn main() { + let f = Foo; + f.bat(1.0); + + let s = "foo".to_string(); + let _ = s.is_emtpy(); + + // Generates a warning for `count_zeros()`. `count_ones()` is also a close + // match, but the former is closer. + let _ = 63u32.count_eos(); + + // Does not generate a warning + let _ = 63u32.count_o(); + +} diff --git a/src/test/ui/suggestions/suggest-methods.stderr b/src/test/ui/suggestions/suggest-methods.stderr new file mode 100644 index 00000000000..41beb73b1bc --- /dev/null +++ b/src/test/ui/suggestions/suggest-methods.stderr @@ -0,0 +1,32 @@ +error[E0599]: no method named `bat` found for type `Foo` in the current scope + --> $DIR/suggest-methods.rs:28:7 + | +28 | f.bat(1.0); + | ^^^ + | + = help: did you mean `bar`? + +error[E0599]: no method named `is_emtpy` found for type `std::string::String` in the current scope + --> $DIR/suggest-methods.rs:31:15 + | +31 | let _ = s.is_emtpy(); + | ^^^^^^^^ + | + = help: did you mean `is_empty`? + +error[E0599]: no method named `count_eos` found for type `u32` in the current scope + --> $DIR/suggest-methods.rs:35:19 + | +35 | let _ = 63u32.count_eos(); + | ^^^^^^^^^ + | + = help: did you mean `count_zeros`? + +error[E0599]: no method named `count_o` found for type `u32` in the current scope + --> $DIR/suggest-methods.rs:38:19 + | +38 | let _ = 63u32.count_o(); + | ^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/suggestions/try-on-option.rs b/src/test/ui/suggestions/try-on-option.rs new file mode 100644 index 00000000000..4cd8cd81151 --- /dev/null +++ b/src/test/ui/suggestions/try-on-option.rs @@ -0,0 +1,25 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(try_trait)] + +fn main() {} + +fn foo() -> Result<u32, ()> { + let x: Option<u32> = None; + x?; + Ok(22) +} + +fn bar() -> u32 { + let x: Option<u32> = None; + x?; + 22 +} diff --git a/src/test/ui/suggestions/try-on-option.stderr b/src/test/ui/suggestions/try-on-option.stderr new file mode 100644 index 00000000000..86d4510cad3 --- /dev/null +++ b/src/test/ui/suggestions/try-on-option.stderr @@ -0,0 +1,22 @@ +error[E0277]: the trait bound `(): std::convert::From<std::option::NoneError>` is not satisfied + --> $DIR/try-on-option.rs:17:5 + | +17 | x?; + | ^^ the trait `std::convert::From<std::option::NoneError>` is not implemented for `()` + | + = note: required by `std::convert::From::from` + +error[E0277]: the `?` operator can only be used in a function that returns `Result` (or another type that implements `std::ops::Try`) + --> $DIR/try-on-option.rs:23:5 + | +23 | x?; + | -- + | | + | cannot use the `?` operator in a function that returns `u32` + | in this macro invocation + | + = help: the trait `std::ops::Try` is not implemented for `u32` + = note: required by `std::ops::Try::from_error` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/type-check/issue-41314.rs b/src/test/ui/type-check/issue-41314.rs new file mode 100644 index 00000000000..5127a8ce174 --- /dev/null +++ b/src/test/ui/type-check/issue-41314.rs @@ -0,0 +1,19 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +enum X { + Y(u32) +} + +fn main() { + match X::Y(0) { + X::Y { number } => {} + } +} diff --git a/src/test/ui/type-check/issue-41314.stderr b/src/test/ui/type-check/issue-41314.stderr new file mode 100644 index 00000000000..acae7a35087 --- /dev/null +++ b/src/test/ui/type-check/issue-41314.stderr @@ -0,0 +1,16 @@ +error[E0026]: variant `X::Y` does not have a field named `number` + --> $DIR/issue-41314.rs:17:16 + | +17 | X::Y { number } => {} + | ^^^^^^ variant `X::Y` does not have field `number` + +error[E0027]: pattern does not mention field `0` + --> $DIR/issue-41314.rs:17:9 + | +17 | X::Y { number } => {} + | ^^^^^^^^^^^^^^^ missing field `0` + | + = note: trying to match a tuple variant with a struct variant pattern + +error: aborting due to 2 previous errors + diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 0e91fa9c602..db957a7a0fc 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -50,6 +50,7 @@ static TARGETS: &'static [&'static str] = &[ "aarch64-unknown-fuchsia", "aarch64-linux-android", "aarch64-unknown-linux-gnu", + "aarch64-unknown-linux-musl", "arm-linux-androideabi", "arm-unknown-linux-gnueabi", "arm-unknown-linux-gnueabihf", @@ -108,6 +109,7 @@ struct Manifest { manifest_version: String, date: String, pkg: BTreeMap<String, Package>, + renames: BTreeMap<String, Rename> } #[derive(Serialize)] @@ -118,6 +120,11 @@ struct Package { } #[derive(Serialize)] +struct Rename { + to: String, +} + +#[derive(Serialize)] struct Target { available: bool, url: Option<String>, @@ -236,6 +243,7 @@ impl Builder { manifest_version: "2".to_string(), date: self.date.to_string(), pkg: BTreeMap::new(), + renames: BTreeMap::new(), }; self.package("rustc", &mut manifest.pkg, HOSTS); @@ -244,14 +252,11 @@ impl Builder { self.package("rust-std", &mut manifest.pkg, TARGETS); self.package("rust-docs", &mut manifest.pkg, TARGETS); self.package("rust-src", &mut manifest.pkg, &["*"]); - let rls_package_name = if self.rust_release == "nightly" { - "rls" - } else { - "rls-preview" - }; - self.package(rls_package_name, &mut manifest.pkg, HOSTS); + self.package("rls-preview", &mut manifest.pkg, HOSTS); self.package("rust-analysis", &mut manifest.pkg, TARGETS); + manifest.renames.insert("rls".to_owned(), Rename { to: "rls-preview".to_owned() }); + let mut pkg = Package { version: self.cached_version("rust").to_string(), git_commit_hash: self.cached_git_commit_hash("rust").clone(), @@ -287,7 +292,7 @@ impl Builder { } extensions.push(Component { - pkg: rls_package_name.to_string(), + pkg: "rls-preview".to_string(), target: host.to_string(), }); extensions.push(Component { @@ -319,7 +324,7 @@ impl Builder { } manifest.pkg.insert("rust".to_string(), pkg); - return manifest + return manifest; } fn package(&mut self, @@ -452,6 +457,7 @@ impl Builder { cmd.arg("--no-tty") .arg("--yes") .arg("--passphrase-fd").arg("0") + .arg("--personal-digest-preferences").arg("SHA512") .arg("--armor") .arg("--output").arg(&asc) .arg("--detach-sign").arg(path) diff --git a/src/tools/cargo b/src/tools/cargo -Subproject 8118b02ac5ce49b22e049ff03316d5e1574852c +Subproject e447ac7e94b7f56ab13e361f9e324dafe3eb0a3 diff --git a/src/tools/cargotest/main.rs b/src/tools/cargotest/main.rs index 012ee835494..0a9da26d996 100644 --- a/src/tools/cargotest/main.rs +++ b/src/tools/cargotest/main.rs @@ -49,7 +49,7 @@ const TEST_REPOS: &'static [Test] = &[ Test { name: "xsv", repo: "https://github.com/BurntSushi/xsv", - sha: "a9a7163f2a2953cea426fee1216bec914fe2f56a", + sha: "4b308adbe48ac81657fd124b90b44f7c3263f771", lock: None, }, ]; diff --git a/src/tools/rls b/src/tools/rls -Subproject 7221e38023c41ff2532ebbf54a7da296fd488b5 +Subproject 93b47d14cef5720bba7cfb4dcb8078fbf1f706c diff --git a/src/tools/rustfmt b/src/tools/rustfmt -Subproject a1fd68da464fc51585f351c81fc2b867211c197 +Subproject 22eb5241c0ee5bb7eaf95e270a2b1500e82bf76 diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index e9e4b55402c..38df6577694 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -35,8 +35,11 @@ static EXCEPTIONS: &'static [&'static str] = &[ "thread-id", // Apache-2.0, mdbook "cssparser", // MPL-2.0, rustdoc "smallvec", // MPL-2.0, rustdoc + // FIXME: remove magenta references when "everything" has moved over to using the zircon name. "magenta-sys", // BSD-3-Clause, rustdoc "magenta", // BSD-3-Clause, rustdoc + "zircon-sys", // BSD-3-Clause, rustdoc + "zircon", // BSD-3-Clause, rustdoc "cssparser-macros", // MPL-2.0, rustdoc "selectors", // MPL-2.0, rustdoc ]; diff --git a/src/tools/toolstate.toml b/src/tools/toolstate.toml index 707b316190d..1700daa0aff 100644 --- a/src/tools/toolstate.toml +++ b/src/tools/toolstate.toml @@ -23,7 +23,14 @@ # Each tool has a list of people to ping # ping @oli-obk @RalfJung @eddyb -miri = "Testing" +miri = "Broken" # ping @Manishearth @llogiq @mcarton @oli-obk clippy = "Broken" + +# ping @nrc +rls = "Testing" + +# ping @nrc +rustfmt = "Testing" + |
