diff --git a/.gitignore b/.gitignore index ff839c34df1..b54bab177d0 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,7 @@ .hg/ .hgignore .idea +*.iml __pycache__/ *.py[cod] *$py.class diff --git a/.travis.yml b/.travis.yml index b95196da356..21877ecb43e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -171,16 +171,22 @@ before_script: if [[ "$SKIP_BUILD" == true ]]; then export RUN_SCRIPT="echo 'skipping, not a full build'"; else - RUN_SCRIPT="stamp src/ci/init_repo.sh . $HOME/rustsrc"; + RUN_SCRIPT="src/ci/init_repo.sh . $HOME/rustsrc"; if [ "$TRAVIS_OS_NAME" = "osx" ]; then - export RUN_SCRIPT="$RUN_SCRIPT && stamp src/ci/run.sh"; + export RUN_SCRIPT="$RUN_SCRIPT && src/ci/run.sh"; else - export RUN_SCRIPT="$RUN_SCRIPT && stamp src/ci/docker/run.sh $IMAGE"; + export RUN_SCRIPT="$RUN_SCRIPT && src/ci/docker/run.sh $IMAGE"; fi fi +# Log time information from this machine and an external machine for insight into possible +# clock drift. Timezones don't matter since relative deltas give all the necessary info. script: - - sh -x -c "$RUN_SCRIPT" + - > + date && curl -s --head https://google.com | grep ^Date: | sed 's/Date: //g' + - stamp sh -x -c "$RUN_SCRIPT" + - > + date && curl -s --head https://google.com | grep ^Date: | sed 's/Date: //g' after_success: - > diff --git a/README.md b/README.md index 0b209fd3e94..a1f01861075 100644 --- a/README.md +++ b/README.md @@ -40,8 +40,9 @@ Read ["Installation"] from [The Book]. > ***Note:*** Install locations can be adjusted by copying the config file > from `./src/bootstrap/config.toml.example` to `./config.toml`, and - > adjusting the `prefix` option under `[install]`. Various other options are - > also supported, and are documented in the config file. + > adjusting the `prefix` option under `[install]`. Various other options, such + > as enabling debug information, are also supported, and are documented in + > the config file. When complete, `sudo ./x.py install` will place several programs into `/usr/local/bin`: `rustc`, the Rust compiler, and `rustdoc`, the diff --git a/src/Cargo.lock b/src/Cargo.lock index e8f0ed6ed2c..dc94ee27e93 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -129,7 +129,7 @@ dependencies = [ "gcc 0.3.51 (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.24 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -157,7 +157,7 @@ dependencies = [ [[package]] name = "cargo" version = "0.21.0" -source = "git+https://github.com/rust-lang/cargo#50b1c24d146fa072db71f12005deed319ac5ba9a" +source = "git+https://github.com/rust-lang/cargo#eb6cf012a6cc23c9c89c4009564de9fccc38b9cb" replace = "cargo 0.21.0" [[package]] @@ -170,8 +170,8 @@ dependencies = [ "cargotest 0.1.0", "crates-io 0.10.0", "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "docopt 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "curl 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "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.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -188,7 +188,7 @@ dependencies = [ "libgit2-sys 0.6.12 (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.5.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.14 (registry+https://github.com/rust-lang/crates.io-index)", "psapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -201,8 +201,8 @@ dependencies = [ "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)", "termcolor 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -224,7 +224,7 @@ dependencies = [ "serde_json 1.0.2 (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)", - "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -301,12 +301,12 @@ dependencies = [ name = "crates-io" version = "0.10.0" dependencies = [ - "curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "curl 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -316,19 +316,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "curl" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "curl-sys 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", + "curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.24 (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.14 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.2.1 (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.12" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", @@ -365,7 +366,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "docopt" -version = "0.8.0" +version = "0.8.1" 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)", @@ -474,7 +475,7 @@ dependencies = [ "libgit2-sys 0.6.12 (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.14 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -482,10 +483,10 @@ name = "git2-curl" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "curl 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "git2 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -575,14 +576,14 @@ dependencies = [ [[package]] name = "languageserver-types" -version = "0.10.0" +version = "0.11.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.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.5.0 (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)", ] @@ -609,7 +610,7 @@ version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", - "curl-sys 0.3.12 (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.51 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", "libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -798,7 +799,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "num_cpus" -version = "1.5.1" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", @@ -936,11 +937,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "racer" -version = "2.0.8" +version = "2.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.5 (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)", "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -984,7 +986,7 @@ dependencies = [ "aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1013,39 +1015,30 @@ dependencies = [ "cargo 0.21.0 (git+https://github.com/rust-lang/cargo)", "derive-new 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "languageserver-types 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "languageserver-types 0.11.0 (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.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-analysis 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-data 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "racer 2.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-analysis 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-data 0.7.0 (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.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustfmt-nightly 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-vfs 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rustfmt-nightly 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.2 (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)", ] [[package]] name = "rls-analysis" -version = "0.3.2" +version = "0.4.1" 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)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-data 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rls-data" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ + "rls-data 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1071,10 +1064,10 @@ dependencies = [ [[package]] name = "rls-vfs" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "racer 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "racer 2.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1396,6 +1389,7 @@ dependencies = [ "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-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_back 0.0.0", "rustc_bitflags 0.0.0", "rustc_const_math 0.0.0", @@ -1463,7 +1457,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "0.1.3" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1477,8 +1471,8 @@ dependencies = [ "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (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.5 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.1 (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.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1579,6 +1573,18 @@ name = "shell-escape" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "socket2" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.1 (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.24 (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)", +] + [[package]] name = "stable_deref_trait" version = "1.0.0" @@ -1697,7 +1703,7 @@ dependencies = [ "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)", - "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1720,7 +1726,7 @@ dependencies = [ "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)", "syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1748,7 +1754,7 @@ version = "0.0.0" [[package]] name = "term" -version = "0.4.5" +version = "0.4.6" 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)", @@ -1790,15 +1796,6 @@ dependencies = [ "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "thread-id" -version = "3.1.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.24 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "thread_local" version = "0.2.7" @@ -1809,11 +1806,11 @@ dependencies = [ [[package]] name = "thread_local" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "thread-id 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1846,7 +1843,7 @@ dependencies = [ [[package]] name = "toml" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1892,7 +1889,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "unreachable" -version = "0.1.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1907,7 +1904,7 @@ dependencies = [ [[package]] name = "url" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "idna 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1921,7 +1918,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2026,12 +2023,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b8f69e518f967224e628896b54e41ff6acfb4dcfefc5076325c36525dac900f" "checksum cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ebbb35d3dc9cd09497168f33de1acb79b265d350ab0ac34133b98f8509af1f" "checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97" -"checksum curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c90e1240ef340dd4027ade439e5c7c2064dd9dc652682117bd50d1486a3add7b" -"checksum curl-sys 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "f00c8ba847fb0730c293069b4d1203dc01bf3c2e1f90b4e55f426ed8f4a1eeac" +"checksum curl 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6689276ab61f97c660669a5ecc117c36875dfc1ba301c986b16c653415bdf9d7" +"checksum curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d5481162dc4f424d088581db2f979fa7d4c238fe9794595de61d8d7522e277de" "checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850" "checksum derive-new 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41be6ca3b99e0c0483fb2389685448f650459c3ecbe4e18d7705d8010ec4ab8e" "checksum diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0a515461b6c8c08419850ced27bc29e86166dcdcde8fbe76f8b1f0589bb49472" -"checksum docopt 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63e408eee8a772c5c61f62353992e3ebf51ef5c832dd04d986b3dc7d48c5b440" +"checksum docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b5b93718f8b3e5544fcc914c43de828ca6c6ace23e0332c6080a2977b49787a" "checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90" "checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180" "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f" @@ -2053,7 +2050,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c" "checksum jobserver 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4e28adc987f6d0521ef66ad60b055968107b164b3bb3cf3dc8474e0a380474a6" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum languageserver-types 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97c2985bfcbbcb0189cfa25e1c10c1ac7111df2b6214b652c690127aefdf4e5b" +"checksum languageserver-types 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c178b944c3187527293fb9f8a0b0db3c5fb62eb127cacd65296f651a2440f5b1" "checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf" "checksum libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)" = "38f5c2b18a287cf78b4097db62e20f43cace381dc76ae5c0a3073067f78b7ddc" "checksum libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "df18a822100352d9863b302faf6f8f25c0e77f0e60feb40e5dbe1238b7f13b1d" @@ -2075,7 +2072,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d1891bd7b936f12349b7d1403761c8a0b85a18b148e9da4429d5d102c1a41e" "checksum num-rational 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "33c881e104a26e1accc09449374c095ff2312c8e0c27fab7bbefe16eac7c776d" "checksum num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "1708c0628602a98b52fad936cf3edb9a107af06e52e49fdf0707e884456a6af6" -"checksum num_cpus 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6e416ba127a4bb3ff398cb19546a8d0414f73352efe2857f4060d36f5fe5983a" +"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.14 (registry+https://github.com/rust-lang/crates.io-index)" = "11ba043cb65fc9af71a431b8a36ffe8686cd4751cdf70a473ec1d01066ac7e41" "checksum openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d98df0270d404ccd3c050a41d579c52d1db15375168bb3471e04ec0f5f378daf" @@ -2090,20 +2087,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum quick-error 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c36987d4978eb1be2e422b1e0423a557923a5c3e7e6f31d5699e9aafaefa469" "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.8 (registry+https://github.com/rust-lang/crates.io-index)" = "edf2dfc188373ef96168bec3646a0415c5c21111c6144c0c36104fc720587ecd" +"checksum racer 2.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9079a128fdb6f0c8850010e1478b215d4c00134654bf995bfda41824951ce9bd" "checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d" "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.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d77d58e8933752142b5b92e3f8ba6d6f1630be6da5627c492268a43f79ffbda" -"checksum rls-data 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "374a8fad31cc0681a7bfd8a04079dd4afd0e981d34e18a171b1a467445bdf51e" +"checksum rls-analysis 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "78a05b130793ebc781c2d933299d7214a10d014fdebe5184eb652c81ba8d3184" "checksum rls-data 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e502ac679bc35e023e982506c32d0278ef89e29af1e4ad21cb70c44b525b87a9" "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a" -"checksum rls-vfs 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ace07060dd154731b39254864245cbdd33c8f5f64fe1f630a089c72e2468f854" +"checksum rls-vfs 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1f19246a0fda45f2fb6eb34addef2a692c044cbf1c90ec7695583450fb5f23e7" "checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" -"checksum rustfmt-nightly 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "277deb9c0ee9c4788ee94faef5988fa334179cd7363bf281a2cae027edbbc8bf" +"checksum rustfmt-nightly 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "31ac6fe40a9844ee2de3d51d0be2bbcdb361bad6f3667a02db8c4e2330afbbb5" "checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7" "checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d" "checksum semver 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd61b85a0fa777f7fb7c454b9189b2941b110d1385ce84d7f76efdf1606a85" @@ -2116,6 +2112,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum serde_json 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ad8bcf487be7d2e15d3d543f04312de991d631cfe1b43ea0ade69e6a8a5b16a1" "checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b" "checksum shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dd5cc96481d54583947bfe88bf30c23d53f883c6cd0145368b69989d97b84ef8" +"checksum socket2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "12cdbddbaa27bf94cc194b8e37f5811db6fe83cea96cf99cf1f8e92b65a41371" "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b" "checksum strings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da75d8bf2c4d210d63dd09581a041b036001f9f6e03d9b151dbff810fb7ba26a" "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" @@ -2127,17 +2124,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum syntex_syntax 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "76a302e717e348aa372ff577791c3832395650073b8d8432f8b3cb170b34afde" "checksum tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "281285b717926caa919ad905ef89c63d75805c7d89437fb873100925a53f2b1b" "checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6" -"checksum term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d168af3930b369cfe245132550579d47dfd873d69470755a19c2c6568dbbd989" +"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.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9a5193a56b8d82014662c4b933dea6bec851daf018a2b01722e007daaf5f9dca" "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" -"checksum thread-id 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8df7875b676fddfadffd96deea3b1124e5ede707d4884248931077518cf1f773" "checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" -"checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7" +"checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14" "checksum toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "0590d72182e50e879c4da3b11c6488dae18fccb1ae0c7a3eda18e16795844796" "checksum toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4" "checksum toml 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd86ad9ebee246fdedd610e0f6d0587b754a3d81438db930a244d0480ed7878f" -"checksum toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4cc5dbfb20a481e64b99eb7ae280859ec76730c7191570ba5edaa962394edb0a" +"checksum toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b0601da6c97135c8d330c7a13a013ca6cd4143221b01de2f8d4edc50a9e551c7" "checksum typed-arena 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5934776c3ac1bea4a9d56620d6bf2d483b20d394e49581db40f187e1118ff667" "checksum unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a6a2c4e3710edd365cd7e78383153ed739fa31af19f9172f72d3575060f5a43a" "checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f" @@ -2145,8 +2141,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" "checksum unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" -"checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91" -"checksum url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a69a2e36a5e5ed3f3063c8c64a3b028c4d50d689fa6c862abd7cfe65f882595c" +"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +"checksum url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb819346883532a271eb626deb43c4a1bb4c4dd47c519bd78137c3e72a4fe27" "checksum url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e7d099f1ee52f823d4bdd60c93c3602043c728f5db3b97bdb548467f7bddea" "checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 8c6eaee24f2..7232208b522 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -75,16 +75,11 @@ fn main() { Err(_) => 0, }; - // Build scripts always use the snapshot compiler which is guaranteed to be - // able to produce an executable, whereas intermediate compilers may not - // have the standard library built yet and may not be able to produce an - // executable. Otherwise we just use the standard compiler we're - // bootstrapping with. - // - // Also note that cargo will detect the version of the compiler to trigger - // a rebuild when the compiler changes. If this happens, we want to make - // sure to use the actual compiler instead of the snapshot compiler becase - // that's the one that's actually changing. + // Use a different compiler for build scripts, since there may not yet be a + // libstd for the real compiler to use. However, if Cargo is attempting to + // determine the version of the compiler, the real compiler needs to be + // used. Currently, these two states are differentiated based on whether + // --target and -vV is/isn't passed. let (rustc, libdir) = if target.is_none() && version.is_none() { ("RUSTC_SNAPSHOT", "RUSTC_SNAPSHOT_LIBDIR") } else { diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 8dc2875ec42..eaf2a40f2fa 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -25,10 +25,11 @@ from time import time def get(url, path, verbose=False): - sha_url = url + ".sha256" + suffix = '.sha256' + sha_url = url + suffix with tempfile.NamedTemporaryFile(delete=False) as temp_file: temp_path = temp_file.name - with tempfile.NamedTemporaryFile(suffix=".sha256", delete=False) as sha_file: + with tempfile.NamedTemporaryFile(suffix=suffix, delete=False) as sha_file: sha_path = sha_file.name try: @@ -55,6 +56,7 @@ def get(url, path, verbose=False): def delete_if_present(path, verbose): + """Remove the given file if present""" if os.path.isfile(path): if verbose: print("removing " + path) @@ -92,12 +94,13 @@ def _download(path, url, probably_big, verbose, exception): def verify(path, sha_path, verbose): + """Check if the sha256 sum of the given path is valid""" if verbose: print("verifying " + path) - with open(path, "rb") as f: - found = hashlib.sha256(f.read()).hexdigest() - with open(sha_path, "r") as f: - expected = f.readline().split()[0] + with open(path, "rb") as source: + found = hashlib.sha256(source.read()).hexdigest() + with open(sha_path, "r") as sha256sum: + expected = sha256sum.readline().split()[0] verified = found == expected if not verified: print("invalid checksum:\n" @@ -107,6 +110,7 @@ def verify(path, sha_path, verbose): def unpack(tarball, dst, verbose=False, match=None): + """Unpack the given tarball file""" print("extracting " + tarball) fname = os.path.basename(tarball).replace(".tar.gz", "") with contextlib.closing(tarfile.open(tarball)) as tar: @@ -128,6 +132,7 @@ def unpack(tarball, dst, verbose=False, match=None): shutil.move(tp, fp) shutil.rmtree(os.path.join(dst, fname)) + def run(args, verbose=False, exception=False, **kwargs): if verbose: print("running: " + ' '.join(args)) @@ -245,7 +250,8 @@ class RustBuild(object): return # At this point we're pretty sure the user is running NixOS - print("info: you seem to be running NixOS. Attempting to patch " + fname) + nix_os_msg = "info: you seem to be running NixOS. Attempting to patch" + print(nix_os_msg, fname) try: interpreter = subprocess.check_output( @@ -293,18 +299,22 @@ class RustBuild(object): return self._cargo_channel def rustc_stamp(self): + """Return the path for .rustc-stamp""" return os.path.join(self.bin_root(), '.rustc-stamp') def cargo_stamp(self): + """Return the path for .cargo-stamp""" return os.path.join(self.bin_root(), '.cargo-stamp') def rustc_out_of_date(self): + """Check if rustc is out of date""" if not os.path.exists(self.rustc_stamp()) or self.clean: return True with open(self.rustc_stamp(), 'r') as f: return self.stage0_date() != f.read() def cargo_out_of_date(self): + """Check if cargo is out of date""" if not os.path.exists(self.cargo_stamp()) or self.clean: return True with open(self.cargo_stamp(), 'r') as f: @@ -357,8 +367,7 @@ class RustBuild(object): def exe_suffix(self): if sys.platform == 'win32': return '.exe' - else: - return '' + return '' def print_what_it_means_to_bootstrap(self): if hasattr(self, 'printed'): @@ -366,7 +375,7 @@ class RustBuild(object): self.printed = True if os.path.exists(self.bootstrap_binary()): return - if not '--help' in sys.argv or len(sys.argv) == 1: + if '--help' not in sys.argv or len(sys.argv) == 1: return print('info: the build system for Rust is written in Rust, so this') @@ -461,8 +470,8 @@ class RustBuild(object): # always emit 'i386' on x86/amd64 systems). As such, isainfo -k # must be used instead. try: - cputype = subprocess.check_output(['isainfo', - '-k']).strip().decode(default_encoding) + cputype = subprocess.check_output( + ['isainfo', '-k']).strip().decode(default_encoding) except (subprocess.CalledProcessError, OSError): err = "isainfo not found" if self.verbose: @@ -562,21 +571,26 @@ class RustBuild(object): default_encoding = sys.getdefaultencoding() run(["git", "submodule", "-q", "sync"], cwd=self.rust_root) submodules = [s.split(' ', 1)[1] for s in subprocess.check_output( - ["git", "config", "--file", os.path.join(self.rust_root, ".gitmodules"), + ["git", "config", "--file", + os.path.join(self.rust_root, ".gitmodules"), "--get-regexp", "path"] ).decode(default_encoding).splitlines()] submodules = [module for module in submodules if not ((module.endswith("llvm") and - (self.get_toml('llvm-config') or self.get_mk('CFG_LLVM_ROOT'))) or + (self.get_toml('llvm-config') or + self.get_mk('CFG_LLVM_ROOT'))) or (module.endswith("jemalloc") and - (self.get_toml('jemalloc') or self.get_mk('CFG_JEMALLOC_ROOT')))) - ] + (self.get_toml('jemalloc') or + self.get_mk('CFG_JEMALLOC_ROOT'))))] run(["git", "submodule", "update", - "--init"] + submodules, cwd=self.rust_root, verbose=self.verbose) + "--init"] + submodules, + cwd=self.rust_root, verbose=self.verbose) run(["git", "submodule", "-q", "foreach", "git", - "reset", "-q", "--hard"], cwd=self.rust_root, verbose=self.verbose) + "reset", "-q", "--hard"], + cwd=self.rust_root, verbose=self.verbose) run(["git", "submodule", "-q", "foreach", "git", - "clean", "-qdfx"], cwd=self.rust_root, verbose=self.verbose) + "clean", "-qdfx"], + cwd=self.rust_root, verbose=self.verbose) def bootstrap(): @@ -692,5 +706,6 @@ def main(): format_build_time(time() - start_time)) sys.exit(exit_code) + if __name__ == '__main__': main() diff --git a/src/bootstrap/cc.rs b/src/bootstrap/cc.rs index 54c8194678e..7c7161916ee 100644 --- a/src/bootstrap/cc.rs +++ b/src/bootstrap/cc.rs @@ -42,10 +42,13 @@ use config::Target; 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.config.target.iter() { + // + // This includes targets that aren't necessarily passed on the commandline + // (FIXME: Perhaps it shouldn't?) + for target in &build.config.target { let mut cfg = gcc::Config::new(); cfg.cargo_metadata(false).opt_level(0).debug(false) - .target(target).host(&build.config.build); + .target(target).host(&build.build); let config = build.config.target_config.get(target); if let Some(cc) = config.and_then(|c| c.cc.as_ref()) { @@ -64,10 +67,13 @@ pub fn find(build: &mut Build) { } // For all host triples we need to find a C++ compiler as well - for host in build.config.host.iter() { + // + // This includes hosts that aren't necessarily passed on the commandline + // (FIXME: Perhaps it shouldn't?) + for host in &build.config.host { let mut cfg = gcc::Config::new(); cfg.cargo_metadata(false).opt_level(0).debug(false).cpp(true) - .target(host).host(&build.config.build); + .target(host).host(&build.build); let config = build.config.target_config.get(host); if let Some(cxx) = config.and_then(|c| c.cxx.as_ref()) { cfg.compiler(cxx); diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs index 4664b1f765e..1153acfa57d 100644 --- a/src/bootstrap/channel.rs +++ b/src/bootstrap/channel.rs @@ -23,12 +23,12 @@ use build_helper::output; use Build; // The version number -pub const CFG_RELEASE_NUM: &'static str = "1.20.0"; +pub const CFG_RELEASE_NUM: &str = "1.20.0"; // An optional number to put after the label, e.g. '.2' -> '-beta.2' // Be sure to make this starts with a dot to conform to semver pre-release // versions (section 9) -pub const CFG_PRERELEASE_VERSION: &'static str = ".1"; +pub const CFG_PRERELEASE_VERSION: &str = ".1"; pub struct GitInfo { inner: Option, @@ -99,6 +99,10 @@ impl GitInfo { version.push_str(&inner.commit_date); version.push_str(")"); } - return version + version + } + + pub fn is_git(&self) -> bool { + self.inner.is_some() } } diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 277728b90b7..b3b5ae8d67d 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -13,23 +13,22 @@ //! This file implements the various regression test suites that we execute on //! our CI. -extern crate build_helper; - use std::collections::HashSet; use std::env; +use std::iter; use std::fmt; use std::fs::{self, File}; use std::path::{PathBuf, Path}; use std::process::Command; use std::io::Read; -use build_helper::output; +use build_helper::{self, output}; use {Build, Compiler, Mode}; use dist; use util::{self, dylib_path, dylib_path_var, exe}; -const ADB_TEST_DIR: &'static str = "/data/tmp/work"; +const ADB_TEST_DIR: &str = "/data/tmp/work"; /// The two modes of the test runner; tests or benchmarks. #[derive(Copy, Clone)] @@ -60,7 +59,7 @@ impl fmt::Display for TestKind { } fn try_run(build: &Build, cmd: &mut Command) { - if build.flags.cmd.no_fail_fast() { + if !build.fail_fast { if !build.try_run(cmd) { let failures = build.delayed_failures.get(); build.delayed_failures.set(failures + 1); @@ -71,7 +70,7 @@ fn try_run(build: &Build, cmd: &mut Command) { } fn try_run_quiet(build: &Build, cmd: &mut Command) { - if build.flags.cmd.no_fail_fast() { + if !build.fail_fast { if !build.try_run_quiet(cmd) { let failures = build.delayed_failures.get(); build.delayed_failures.set(failures + 1); @@ -99,7 +98,7 @@ pub fn linkcheck(build: &Build, host: &str) { /// This tool in `src/tools` will check out a few Rust projects and run `cargo /// test` to ensure that we don't regress the test suites there. pub fn cargotest(build: &Build, stage: u32, host: &str) { - let ref compiler = Compiler::new(stage, host); + let compiler = Compiler::new(stage, host); // Note that this is a short, cryptic, and not scoped directory name. This // is currently to minimize the length of path on Windows where we otherwise @@ -109,11 +108,11 @@ pub fn cargotest(build: &Build, stage: u32, host: &str) { let _time = util::timeit(); let mut cmd = Command::new(build.tool(&Compiler::new(0, host), "cargotest")); - build.prepare_tool_cmd(compiler, &mut cmd); - try_run(build, cmd.arg(&build.cargo) + build.prepare_tool_cmd(&compiler, &mut cmd); + try_run(build, cmd.arg(&build.initial_cargo) .arg(&out_dir) - .env("RUSTC", build.compiler_path(compiler)) - .env("RUSTDOC", build.rustdoc(compiler))); + .env("RUSTC", build.compiler_path(&compiler)) + .env("RUSTDOC", build.rustdoc(&compiler))); } /// Runs `cargo test` for `cargo` packaged with Rust. @@ -124,13 +123,12 @@ pub fn cargo(build: &Build, stage: u32, host: &str) { // and not RUSTC because the Cargo test suite has tests that will // fail if rustc is not spelled `rustc`. let path = build.sysroot(compiler).join("bin"); - let old_path = ::std::env::var("PATH").expect(""); - let sep = if cfg!(windows) { ";" } else {":" }; - let ref newpath = format!("{}{}{}", path.display(), sep, old_path); + let old_path = env::var_os("PATH").unwrap_or_default(); + let newpath = env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect(""); let mut cargo = build.cargo(compiler, Mode::Tool, host, "test"); cargo.arg("--manifest-path").arg(build.src.join("src/tools/cargo/Cargo.toml")); - if build.flags.cmd.no_fail_fast() { + if !build.fail_fast { cargo.arg("--no-fail-fast"); } @@ -198,9 +196,9 @@ pub fn compiletest(build: &Build, cmd.arg("--mode").arg(mode); cmd.arg("--target").arg(target); cmd.arg("--host").arg(compiler.host); - cmd.arg("--llvm-filecheck").arg(build.llvm_filecheck(&build.config.build)); + cmd.arg("--llvm-filecheck").arg(build.llvm_filecheck(&build.build)); - if let Some(nodejs) = build.config.nodejs.as_ref() { + if let Some(ref nodejs) = build.config.nodejs { cmd.arg("--nodejs").arg(nodejs); } @@ -224,7 +222,7 @@ pub fn compiletest(build: &Build, cmd.arg("--docck-python").arg(build.python()); - if build.config.build.ends_with("apple-darwin") { + if build.build.ends_with("apple-darwin") { // Force /usr/bin/python on macOS for LLDB tests because we're loading the // LLDB plugin's compiled module which only works with the system python // (namely not Homebrew-installed python) @@ -251,7 +249,7 @@ pub fn compiletest(build: &Build, cmd.args(&build.flags.cmd.test_args()); - if build.config.verbose() || build.flags.verbose() { + if build.is_verbose() { cmd.arg("--verbose"); } @@ -279,7 +277,7 @@ pub fn compiletest(build: &Build, if build.remote_tested(target) { cmd.arg("--remote-test-client") - .arg(build.tool(&Compiler::new(0, &build.config.build), + .arg(build.tool(&Compiler::new(0, &build.build), "remote-test-client")); } @@ -368,7 +366,7 @@ pub fn error_index(build: &Build, compiler: &Compiler) { "error_index_generator") .arg("markdown") .arg(&output) - .env("CFG_BUILD", &build.config.build)); + .env("CFG_BUILD", &build.build)); markdown_test(build, compiler, &output); } @@ -450,7 +448,7 @@ pub fn krate(build: &Build, cargo.arg("--manifest-path") .arg(build.src.join(path).join("Cargo.toml")) .arg("--features").arg(features); - if test_kind.subcommand() == "test" && build.flags.cmd.no_fail_fast() { + if test_kind.subcommand() == "test" && !build.fail_fast { cargo.arg("--no-fail-fast"); } @@ -520,16 +518,14 @@ fn krate_emscripten(build: &Build, compiler: &Compiler, target: &str, mode: Mode) { - let mut tests = Vec::new(); let out_dir = build.cargo_out(compiler, mode, target); - find_tests(&out_dir.join("deps"), target, &mut tests); + let tests = find_tests(&out_dir.join("deps"), target); + let nodejs = build.config.nodejs.as_ref().expect("nodejs not configured"); for test in tests { - let test_file_name = test.to_string_lossy().into_owned(); - println!("running {}", test_file_name); - let nodejs = build.config.nodejs.as_ref().expect("nodejs not configured"); + println!("running {}", test.display()); let mut cmd = Command::new(nodejs); - cmd.arg(&test_file_name); + cmd.arg(&test); if build.config.quiet_tests { cmd.arg("--quiet"); } @@ -541,11 +537,10 @@ fn krate_remote(build: &Build, compiler: &Compiler, target: &str, mode: Mode) { - let mut tests = Vec::new(); let out_dir = build.cargo_out(compiler, mode, target); - find_tests(&out_dir.join("deps"), target, &mut tests); + let tests = find_tests(&out_dir.join("deps"), target); - let tool = build.tool(&Compiler::new(0, &build.config.build), + let tool = build.tool(&Compiler::new(0, &build.build), "remote-test-client"); for test in tests { let mut cmd = Command::new(&tool); @@ -559,9 +554,8 @@ fn krate_remote(build: &Build, } } -fn find_tests(dir: &Path, - target: &str, - dst: &mut Vec) { +fn find_tests(dir: &Path, target: &str) -> Vec { + let mut dst = Vec::new(); for e in t!(dir.read_dir()).map(|e| t!(e)) { let file_type = t!(e.file_type()); if !file_type.is_file() { @@ -576,6 +570,7 @@ fn find_tests(dir: &Path, dst.push(e.path()); } } + dst } pub fn remote_copy_libs(build: &Build, compiler: &Compiler, target: &str) { @@ -590,7 +585,7 @@ pub fn remote_copy_libs(build: &Build, compiler: &Compiler, target: &str) { .join(exe("remote-test-server", target)); // Spawn the emulator and wait for it to come online - let tool = build.tool(&Compiler::new(0, &build.config.build), + let tool = build.tool(&Compiler::new(0, &build.build), "remote-test-client"); let mut cmd = Command::new(&tool); cmd.arg("spawn-emulator") @@ -616,7 +611,7 @@ pub fn remote_copy_libs(build: &Build, compiler: &Compiler, target: &str) { /// Run "distcheck", a 'make check' from a tarball pub fn distcheck(build: &Build) { - if build.config.build != "x86_64-unknown-linux-gnu" { + if build.build != "x86_64-unknown-linux-gnu" { return } if !build.config.host.iter().any(|s| s == "x86_64-unknown-linux-gnu") { @@ -641,7 +636,7 @@ pub fn distcheck(build: &Build) { .args(&build.config.configure_args) .arg("--enable-vendor") .current_dir(&dir)); - build.run(Command::new(build_helper::make(&build.config.build)) + build.run(Command::new(build_helper::make(&build.build)) .arg("check") .current_dir(&dir)); @@ -659,7 +654,7 @@ pub fn distcheck(build: &Build) { build.run(&mut cmd); let toml = dir.join("rust-src/lib/rustlib/src/rust/src/libstd/Cargo.toml"); - build.run(Command::new(&build.cargo) + build.run(Command::new(&build.initial_cargo) .arg("generate-lockfile") .arg("--manifest-path") .arg(&toml) @@ -668,13 +663,13 @@ pub fn distcheck(build: &Build) { /// Test the build system itself pub fn bootstrap(build: &Build) { - let mut cmd = Command::new(&build.cargo); + let mut cmd = Command::new(&build.initial_cargo); cmd.arg("test") .current_dir(build.src.join("src/bootstrap")) .env("CARGO_TARGET_DIR", build.out.join("bootstrap")) .env("RUSTC_BOOTSTRAP", "1") - .env("RUSTC", &build.rustc); - if build.flags.cmd.no_fail_fast() { + .env("RUSTC", &build.initial_rustc); + if !build.fail_fast { cmd.arg("--no-fail-fast"); } cmd.arg("--").args(&build.flags.cmd.test_args()); diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index c8ab3a8fc1d..5a3106c7d5e 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -50,7 +50,7 @@ pub fn std(build: &Build, target: &str, compiler: &Compiler) { let mut cargo = build.cargo(compiler, Mode::Libstd, target, "build"); let mut features = build.std_features(); - if let Ok(target) = env::var("MACOSX_STD_DEPLOYMENT_TARGET") { + if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") { cargo.env("MACOSX_DEPLOYMENT_TARGET", target); } @@ -158,7 +158,7 @@ pub fn build_startup_objects(build: &Build, for_compiler: &Compiler, target: &st return } - let compiler = Compiler::new(0, &build.config.build); + let compiler = Compiler::new(0, &build.build); let compiler_path = build.compiler_path(&compiler); let src_dir = &build.src.join("src/rtstartup"); let dst_dir = &build.native_dir(target).join("rtstartup"); @@ -199,7 +199,7 @@ pub fn test(build: &Build, target: &str, compiler: &Compiler) { let out_dir = build.cargo_out(compiler, Mode::Libtest, target); build.clear_if_dirty(&out_dir, &libstd_stamp(build, compiler, target)); let mut cargo = build.cargo(compiler, Mode::Libtest, target, "build"); - if let Ok(target) = env::var("MACOSX_STD_DEPLOYMENT_TARGET") { + if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") { cargo.env("MACOSX_DEPLOYMENT_TARGET", target); } cargo.arg("--manifest-path") @@ -247,7 +247,7 @@ pub fn rustc(build: &Build, target: &str, compiler: &Compiler) { cargo.env("CFG_RELEASE", build.rust_release()) .env("CFG_RELEASE_CHANNEL", &build.config.channel) .env("CFG_VERSION", build.rust_version()) - .env("CFG_PREFIX", build.config.prefix.clone().unwrap_or(PathBuf::new())); + .env("CFG_PREFIX", build.config.prefix.clone().unwrap_or_default()); if compiler.stage == 0 { cargo.env("CFG_LIBDIR_RELATIVE", "lib"); @@ -276,10 +276,6 @@ pub fn rustc(build: &Build, target: &str, compiler: &Compiler) { if build.is_rust_llvm(target) { cargo.env("LLVM_RUSTLLVM", "1"); } - if let Some(ref cfg_file) = build.flags.config { - let cfg_path = t!(PathBuf::from(cfg_file).canonicalize()); - cargo.env("CFG_LLVM_TOML", cfg_path.into_os_string()); - } cargo.env("LLVM_CONFIG", build.llvm_config(target)); let target_config = build.config.target_config.get(target); if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) { @@ -355,7 +351,7 @@ pub fn create_sysroot(build: &Build, compiler: &Compiler) { /// Prepare a new compiler from the artifacts in `stage` /// /// This will assemble a compiler in `build/$host/stage$stage`. The compiler -/// must have been previously produced by the `stage - 1` build.config.build +/// must have been previously produced by the `stage - 1` build.build /// compiler. pub fn assemble_rustc(build: &Build, stage: u32, host: &str) { // nothing to do in stage0 @@ -369,7 +365,7 @@ pub fn assemble_rustc(build: &Build, stage: u32, host: &str) { let target_compiler = Compiler::new(stage, host); // The compiler that compiled the compiler we're assembling - let build_compiler = Compiler::new(stage - 1, &build.config.build); + let build_compiler = Compiler::new(stage - 1, &build.build); // Link in all dylibs to the libdir let sysroot = build.sysroot(&target_compiler); @@ -389,7 +385,7 @@ pub fn assemble_rustc(build: &Build, stage: u32, host: &str) { let rustc = out_dir.join(exe("rustc", host)); let bindir = sysroot.join("bin"); t!(fs::create_dir_all(&bindir)); - let compiler = build.compiler_path(&Compiler::new(stage, host)); + let compiler = build.compiler_path(&target_compiler); let _ = fs::remove_file(&compiler); copy(&rustc, &compiler); @@ -411,6 +407,8 @@ fn add_to_sysroot(sysroot_dst: &Path, stamp: &Path) { t!(fs::create_dir_all(&sysroot_dst)); let mut contents = Vec::new(); t!(t!(File::open(stamp)).read_to_end(&mut contents)); + // This is the method we use for extracting paths from the stamp file passed to us. See + // run_cargo for more information (in this file). for part in contents.split(|b| *b == 0) { if part.is_empty() { continue @@ -425,7 +423,7 @@ fn add_to_sysroot(sysroot_dst: &Path, stamp: &Path) { /// This will build the specified tool with the specified `host` compiler in /// `stage` into the normal cargo output directory. pub fn maybe_clean_tools(build: &Build, stage: u32, target: &str, mode: Mode) { - let compiler = Compiler::new(stage, &build.config.build); + let compiler = Compiler::new(stage, &build.build); let stamp = match mode { Mode::Libstd => libstd_stamp(build, &compiler, target), @@ -445,7 +443,7 @@ pub fn tool(build: &Build, stage: u32, target: &str, tool: &str) { let _folder = build.fold_output(|| format!("stage{}-{}", stage, tool)); println!("Building stage{} tool {} ({})", stage, tool, target); - let compiler = Compiler::new(stage, &build.config.build); + let compiler = Compiler::new(stage, &build.build); let mut cargo = build.cargo(&compiler, Mode::Tool, target, "build"); let dir = build.src.join("src/tools").join(tool); @@ -561,23 +559,24 @@ fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path) { // If this was an output file in the "host dir" we don't actually // worry about it, it's not relevant for us. if filename.starts_with(&host_root_dir) { - continue + continue; + } // If this was output in the `deps` dir then this is a precise file // name (hash included) so we start tracking it. - } else if filename.starts_with(&target_deps_dir) { + if filename.starts_with(&target_deps_dir) { deps.push(filename.to_path_buf()); + continue; + } // Otherwise this was a "top level artifact" which right now doesn't // have a hash in the name, but there's a version of this file in // the `deps` folder which *does* have a hash in the name. That's // the one we'll want to we'll probe for it later. - } else { - toplevel.push((filename.file_stem().unwrap() - .to_str().unwrap().to_string(), - filename.extension().unwrap().to_owned() - .to_str().unwrap().to_string())); - } + toplevel.push((filename.file_stem().unwrap() + .to_str().unwrap().to_string(), + filename.extension().unwrap().to_owned() + .to_str().unwrap().to_string())); } } diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 3ada846e382..34628852ab3 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -81,8 +81,6 @@ pub struct Config { pub build: String, pub host: Vec, pub target: Vec, - pub rustc: Option, - pub cargo: Option, pub local_rebuild: bool, // dist misc @@ -114,11 +112,18 @@ pub struct Config { pub python: Option, pub configure_args: Vec, pub openssl_static: bool, + + + // These are either the stage0 downloaded binaries or the locally installed ones. + pub initial_cargo: PathBuf, + pub initial_rustc: PathBuf, + } /// Per-target configuration stored in the global configuration structure. #[derive(Default)] pub struct Target { + /// Some(path to llvm-config) if using an external LLVM. pub llvm_config: Option, pub jemalloc: Option, pub cc: Option, @@ -307,8 +312,6 @@ impl Config { config.target.push(target.clone()); } } - config.rustc = build.rustc.map(PathBuf::from); - config.cargo = build.cargo.map(PathBuf::from); config.nodejs = build.nodejs.map(PathBuf::from); config.gdb = build.gdb.map(PathBuf::from); config.python = build.python.map(PathBuf::from); @@ -410,13 +413,25 @@ impl Config { set(&mut config.rust_dist_src, t.src_tarball); } + let cwd = t!(env::current_dir()); + let out = cwd.join("build"); + + let stage0_root = out.join(&config.build).join("stage0/bin"); + config.initial_rustc = match build.rustc { + Some(s) => PathBuf::from(s), + None => stage0_root.join(exe("rustc", &config.build)), + }; + config.initial_cargo = match build.cargo { + Some(s) => PathBuf::from(s), + None => stage0_root.join(exe("cargo", &config.build)), + }; // compat with `./configure` while we're still using that if fs::metadata("config.mk").is_ok() { config.update_with_config_mk(); } - return config + config } /// "Temporary" routine to parse `config.mk` into this configuration. @@ -609,8 +624,8 @@ impl Config { } "CFG_LOCAL_RUST_ROOT" if value.len() > 0 => { let path = parse_configure_path(value); - self.rustc = Some(push_exe_path(path.clone(), &["bin", "rustc"])); - self.cargo = Some(push_exe_path(path, &["bin", "cargo"])); + self.initial_rustc = push_exe_path(path.clone(), &["bin", "rustc"]); + self.initial_cargo = push_exe_path(path, &["bin", "cargo"]); } "CFG_PYTHON" if value.len() > 0 => { let path = parse_configure_path(value); diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 753bd1df0d8..efc33bcee9b 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -50,7 +50,7 @@ pub fn tmpdir(build: &Build) -> PathBuf { } fn rust_installer(build: &Build) -> Command { - build.tool_cmd(&Compiler::new(0, &build.config.build), "rust-installer") + build.tool_cmd(&Compiler::new(0, &build.build), "rust-installer") } /// Builds the `rust-docs` installer component. @@ -89,7 +89,7 @@ pub fn docs(build: &Build, stage: u32, host: &str) { // As part of this step, *also* copy the docs directory to a directory which // buildbot typically uploads. - if host == build.config.build { + if host == build.build { let dst = distdir(build).join("doc").join(build.rust_package_vers()); t!(fs::create_dir_all(&dst)); cp_r(&src, &dst); @@ -97,7 +97,7 @@ pub fn docs(build: &Build, stage: u32, host: &str) { } fn find_files(files: &[&str], path: &[PathBuf]) -> Vec { - let mut found = Vec::new(); + let mut found = Vec::with_capacity(files.len()); for file in files { let file_path = @@ -119,17 +119,9 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build: //Ask gcc where it keeps its stuff let mut cmd = Command::new(build.cc(target_triple)); cmd.arg("-print-search-dirs"); - build.run_quiet(&mut cmd); - let gcc_out = - String::from_utf8( - cmd - .output() - .expect("failed to execute gcc") - .stdout).expect("gcc.exe output was not utf8"); + let gcc_out = output(&mut cmd); - let mut bin_path: Vec<_> = - env::split_paths(&env::var_os("PATH").unwrap_or_default()) - .collect(); + let mut bin_path: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect(); let mut lib_path = Vec::new(); for line in gcc_out.lines() { @@ -140,7 +132,7 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build: line[(idx + 1)..] .trim_left_matches(trim_chars) .split(';') - .map(|s| PathBuf::from(s)); + .map(PathBuf::from); if key == "programs" { bin_path.extend(value); @@ -149,7 +141,7 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build: } } - let target_tools = vec!["gcc.exe", "ld.exe", "ar.exe", "dlltool.exe", "libwinpthread-1.dll"]; + let target_tools = ["gcc.exe", "ld.exe", "ar.exe", "dlltool.exe", "libwinpthread-1.dll"]; let mut rustc_dlls = vec!["libstdc++-6.dll", "libwinpthread-1.dll"]; if target_triple.starts_with("i686-") { rustc_dlls.push("libgcc_s_dw2-1.dll"); @@ -157,7 +149,7 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build: rustc_dlls.push("libgcc_s_seh-1.dll"); } - let target_libs = vec![ //MinGW libs + let target_libs = [ //MinGW libs "libgcc.a", "libgcc_eh.a", "libgcc_s.a", @@ -203,7 +195,7 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build: let target_libs = find_files(&target_libs, &lib_path); fn copy_to_folder(src: &Path, dest_folder: &Path) { - let file_name = src.file_name().unwrap().to_os_string(); + let file_name = src.file_name().unwrap(); let dest = dest_folder.join(file_name); copy(src, &dest); } @@ -234,8 +226,6 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build: /// /// This contains all the bits and pieces to run the MinGW Windows targets /// without any extra installed software (e.g. we bundle gcc, libraries, etc). -/// Currently just shells out to a python script, but that should be rewritten -/// in Rust. pub fn mingw(build: &Build, host: &str) { println!("Dist mingw ({})", host); let name = pkgname(build, "rust-mingw"); @@ -366,9 +356,9 @@ pub fn rustc(build: &Build, stage: u32, host: &str) { pub fn debugger_scripts(build: &Build, sysroot: &Path, host: &str) { + let dst = sysroot.join("lib/rustlib/etc"); + t!(fs::create_dir_all(&dst)); let cp_debugger_script = |file: &str| { - let dst = sysroot.join("lib/rustlib/etc"); - t!(fs::create_dir_all(&dst)); install(&build.src.join("src/etc/").join(file), &dst, 0o644); }; if host.contains("windows-msvc") { @@ -404,7 +394,7 @@ pub fn std(build: &Build, compiler: &Compiler, target: &str) { // The only true set of target libraries came from the build triple, so // let's reduce redundant work by only producing archives from that host. - if compiler.host != build.config.build { + if compiler.host != build.build { println!("\tskipping, not a build host"); return } @@ -450,7 +440,7 @@ pub fn analysis(build: &Build, compiler: &Compiler, target: &str) { assert!(build.config.extended); println!("Dist analysis"); - if compiler.host != build.config.build { + if compiler.host != build.build { println!("\tskipping, not a build host"); return; } @@ -498,12 +488,11 @@ fn copy_src_dirs(build: &Build, src_dirs: &[&str], exclude_dirs: &[&str], dst_di if spath.ends_with("~") || spath.ends_with(".pyc") { return false } - if spath.contains("llvm/test") || spath.contains("llvm\\test") { - if spath.ends_with(".ll") || - spath.ends_with(".td") || - spath.ends_with(".s") { - return false - } + if (spath.contains("llvm/test") || spath.contains("llvm\\test")) && + (spath.ends_with(".ll") || + spath.ends_with(".td") || + spath.ends_with(".s")) { + return false } let full_path = Path::new(dir).join(path); @@ -595,7 +584,7 @@ pub fn rust_src(build: &Build) { t!(fs::remove_dir_all(&image)); } -const CARGO_VENDOR_VERSION: &'static str = "0.1.4"; +const CARGO_VENDOR_VERSION: &str = "0.1.4"; /// Creates the plain source tarball pub fn plain_source_tarball(build: &Build) { @@ -634,26 +623,26 @@ pub fn plain_source_tarball(build: &Build) { write_file(&plain_dst_src.join("version"), build.rust_version().as_bytes()); // If we're building from git sources, we need to vendor a complete distribution. - if build.src_is_git { + if build.rust_info.is_git() { // Get cargo-vendor installed, if it isn't already. let mut has_cargo_vendor = false; - let mut cmd = Command::new(&build.cargo); + let mut cmd = Command::new(&build.initial_cargo); for line in output(cmd.arg("install").arg("--list")).lines() { has_cargo_vendor |= line.starts_with("cargo-vendor "); } if !has_cargo_vendor { - let mut cmd = Command::new(&build.cargo); + let mut cmd = Command::new(&build.initial_cargo); cmd.arg("install") .arg("--force") .arg("--debug") .arg("--vers").arg(CARGO_VENDOR_VERSION) .arg("cargo-vendor") - .env("RUSTC", &build.rustc); + .env("RUSTC", &build.initial_rustc); build.run(&mut cmd); } // Vendor all Cargo dependencies - let mut cmd = Command::new(&build.cargo); + let mut cmd = Command::new(&build.initial_cargo); cmd.arg("vendor") .current_dir(&plain_dst_src.join("src")); build.run(&mut cmd); @@ -716,7 +705,7 @@ fn write_file(path: &Path, data: &[u8]) { pub fn cargo(build: &Build, stage: u32, target: &str) { println!("Dist cargo stage{} ({})", stage, target); - let compiler = Compiler::new(stage, &build.config.build); + let compiler = Compiler::new(stage, &build.build); let src = build.src.join("src/tools/cargo"); let etc = src.join("src/etc"); @@ -777,7 +766,7 @@ pub fn cargo(build: &Build, stage: u32, target: &str) { pub fn rls(build: &Build, stage: u32, target: &str) { assert!(build.config.extended); println!("Dist RLS stage{} ({})", stage, target); - let compiler = Compiler::new(stage, &build.config.build); + let compiler = Compiler::new(stage, &build.build); let src = build.src.join("src/tools/rls"); let release_num = build.release_num("rls"); @@ -1209,7 +1198,7 @@ fn add_env(build: &Build, cmd: &mut Command, target: &str) { } pub fn hash_and_sign(build: &Build) { - let compiler = Compiler::new(0, &build.config.build); + let compiler = Compiler::new(0, &build.build); let mut cmd = build.tool_cmd(&compiler, "build-manifest"); let sign = build.config.dist_sign_folder.as_ref().unwrap_or_else(|| { panic!("\n\nfailed to specify `dist.sign-folder` in `config.toml`\n\n") diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 30f631ca2df..7dbc3e55539 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -45,7 +45,7 @@ pub fn rustbook_src(build: &Build, target: &str, name: &str, src: &Path) { t!(fs::create_dir_all(&out)); let out = out.join(name); - let compiler = Compiler::new(0, &build.config.build); + let compiler = Compiler::new(0, &build.build); let src = src.join(name); let index = out.join("index.html"); let rustbook = build.tool(&compiler, "rustbook"); @@ -95,7 +95,7 @@ pub fn book(build: &Build, target: &str, name: &str) { fn invoke_rustdoc(build: &Build, target: &str, markdown: &str) { let out = build.doc_out(target); - let compiler = Compiler::new(0, &build.config.build); + let compiler = Compiler::new(0, &build.build); let path = build.src.join("src/doc").join(markdown); @@ -150,7 +150,7 @@ pub fn standalone(build: &Build, target: &str) { let out = build.doc_out(target); t!(fs::create_dir_all(&out)); - let compiler = Compiler::new(0, &build.config.build); + let compiler = Compiler::new(0, &build.build); let favicon = build.src.join("src/doc/favicon.inc"); let footer = build.src.join("src/doc/footer.inc"); @@ -217,7 +217,7 @@ pub fn std(build: &Build, stage: u32, target: &str) { println!("Documenting stage{} std ({})", stage, target); let out = build.doc_out(target); t!(fs::create_dir_all(&out)); - let compiler = Compiler::new(stage, &build.config.build); + let compiler = Compiler::new(stage, &build.build); let compiler = if build.force_use_stage1(&compiler, target) { Compiler::new(1, compiler.host) } else { @@ -276,7 +276,7 @@ pub fn test(build: &Build, stage: u32, target: &str) { println!("Documenting stage{} test ({})", stage, target); let out = build.doc_out(target); t!(fs::create_dir_all(&out)); - let compiler = Compiler::new(stage, &build.config.build); + let compiler = Compiler::new(stage, &build.build); let compiler = if build.force_use_stage1(&compiler, target) { Compiler::new(1, compiler.host) } else { @@ -306,7 +306,7 @@ pub fn rustc(build: &Build, stage: u32, target: &str) { println!("Documenting stage{} compiler ({})", stage, target); let out = build.doc_out(target); t!(fs::create_dir_all(&out)); - let compiler = Compiler::new(stage, &build.config.build); + let compiler = Compiler::new(stage, &build.build); let compiler = if build.force_use_stage1(&compiler, target) { Compiler::new(1, compiler.host) } else { @@ -351,13 +351,13 @@ pub fn error_index(build: &Build, target: &str) { println!("Documenting error index ({})", target); let out = build.doc_out(target); t!(fs::create_dir_all(&out)); - let compiler = Compiler::new(0, &build.config.build); + let compiler = Compiler::new(0, &build.build); let mut index = build.tool_cmd(&compiler, "error_index_generator"); index.arg("html"); index.arg(out.join("error-index.html")); // FIXME: shouldn't have to pass this env var - index.env("CFG_BUILD", &build.config.build); + index.env("CFG_BUILD", &build.build); build.run(&mut index); } @@ -367,7 +367,7 @@ pub fn unstable_book_gen(build: &Build, target: &str) { let out = build.md_doc_out(target).join("unstable-book"); t!(fs::create_dir_all(&out)); t!(fs::remove_dir_all(&out)); - let compiler = Compiler::new(0, &build.config.build); + let compiler = Compiler::new(0, &build.build); let mut cmd = build.tool_cmd(&compiler, "unstable-book-gen"); cmd.arg(build.src.join("src")); cmd.arg(out); diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index dc9dac73627..5804df34e8b 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -35,22 +35,12 @@ pub struct Flags { pub host: Vec, pub target: Vec, pub config: Option, - pub src: Option, + pub src: PathBuf, pub jobs: Option, pub cmd: Subcommand, pub incremental: bool, } -impl Flags { - pub fn verbose(&self) -> bool { - self.verbose > 0 - } - - pub fn very_verbose(&self) -> bool { - self.verbose > 1 - } -} - pub enum Subcommand { Build { paths: Vec, @@ -61,7 +51,7 @@ pub enum Subcommand { Test { paths: Vec, test_args: Vec, - no_fail_fast: bool, + fail_fast: bool, }, Bench { paths: Vec, @@ -122,16 +112,15 @@ To learn more about a subcommand, run `./x.py -h`"); // the subcommand. Therefore we must manually identify the subcommand first, so that we can // complete the definition of the options. Then we can use the getopt::Matches object from // there on out. - let mut possible_subcommands = args.iter().collect::>(); - possible_subcommands.retain(|&s| - (s == "build") - || (s == "test") - || (s == "bench") - || (s == "doc") - || (s == "clean") - || (s == "dist") - || (s == "install")); - let subcommand = match possible_subcommands.first() { + let subcommand = args.iter().find(|&s| + (s == "build") + || (s == "test") + || (s == "bench") + || (s == "doc") + || (s == "clean") + || (s == "dist") + || (s == "install")); + let subcommand = match subcommand { Some(s) => s, None => { // No subcommand -- show the general usage and subcommand help @@ -164,7 +153,7 @@ To learn more about a subcommand, run `./x.py -h`"); let mut pass_sanity_check = true; match matches.free.get(0) { Some(check_subcommand) => { - if &check_subcommand != subcommand { + if check_subcommand != subcommand { pass_sanity_check = false; } }, @@ -279,7 +268,7 @@ Arguments: Subcommand::Test { paths: paths, test_args: matches.opt_strs("test-args"), - no_fail_fast: matches.opt_present("no-fail-fast"), + fail_fast: !matches.opt_present("no-fail-fast"), } } "bench" => { @@ -316,12 +305,15 @@ Arguments: let mut stage = matches.opt_str("stage").map(|j| j.parse().unwrap()); - if matches.opt_present("incremental") { - if stage.is_none() { - stage = Some(1); - } + if matches.opt_present("incremental") && stage.is_none() { + stage = Some(1); } + let cwd = t!(env::current_dir()); + let src = matches.opt_str("src").map(PathBuf::from) + .or_else(|| env::var_os("SRC").map(PathBuf::from)) + .unwrap_or(cwd); + Flags { verbose: matches.opt_count("verbose"), stage: stage, @@ -333,7 +325,7 @@ Arguments: host: split(matches.opt_strs("host")), target: split(matches.opt_strs("target")), config: cfg_file, - src: matches.opt_str("src").map(PathBuf::from), + src: src, jobs: matches.opt_str("jobs").map(|j| j.parse().unwrap()), cmd: cmd, incremental: matches.opt_present("incremental"), @@ -352,9 +344,9 @@ impl Subcommand { } } - pub fn no_fail_fast(&self) -> bool { + pub fn fail_fast(&self) -> bool { match *self { - Subcommand::Test { no_fail_fast, .. } => no_fail_fast, + Subcommand::Test { fail_fast, .. } => fail_fast, _ => false, } } diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index 21e21628dc9..8e2ef527b16 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -146,5 +146,5 @@ fn add_destdir(path: &Path, destdir: &Option) -> PathBuf { _ => {} } } - return ret + ret } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index ce7cde8fc94..69b0c4a2756 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -161,25 +161,35 @@ pub struct Build { flags: Flags, // Derived properties from the above two configurations - cargo: PathBuf, - rustc: PathBuf, src: PathBuf, out: PathBuf, rust_info: channel::GitInfo, cargo_info: channel::GitInfo, rls_info: channel::GitInfo, local_rebuild: bool, + fail_fast: bool, + verbosity: usize, + + // Targets for which to build. + build: String, + hosts: Vec, + targets: Vec, + + // Stage 0 (downloaded) compiler and cargo or their local rust equivalents. + initial_rustc: PathBuf, + initial_cargo: PathBuf, // Probed tools at runtime lldb_version: Option, lldb_python_dir: Option, // Runtime state filled in later on + // target -> (cc, ar) cc: HashMap)>, + // host -> (cc, ar) cxx: HashMap, crates: HashMap, is_sudo: bool, - src_is_git: bool, ci_env: CiEnv, delayed_failures: Cell, } @@ -202,20 +212,16 @@ struct Crate { /// build system, with each mod generating output in a different directory. #[derive(Clone, Copy, PartialEq, Eq)] pub enum Mode { - /// This cargo is going to build the standard library, placing output in the - /// "stageN-std" directory. + /// Build the standard library, placing output in the "stageN-std" directory. Libstd, - /// This cargo is going to build libtest, placing output in the - /// "stageN-test" directory. + /// Build libtest, placing output in the "stageN-test" directory. Libtest, - /// This cargo is going to build librustc and compiler libraries, placing - /// output in the "stageN-rustc" directory. + /// Build librustc and compiler libraries, placing output in the "stageN-rustc" directory. Librustc, - /// This cargo is going to build some tool, placing output in the - /// "stageN-tools" directory. + /// Build some tool, placing output in the "stageN-tools" directory. Tool, } @@ -226,22 +232,9 @@ impl Build { /// By default all build output will be placed in the current directory. pub fn new(flags: Flags, config: Config) -> Build { let cwd = t!(env::current_dir()); - let src = flags.src.clone().or_else(|| { - env::var_os("SRC").map(|x| x.into()) - }).unwrap_or(cwd.clone()); + let src = flags.src.clone(); let out = cwd.join("build"); - let stage0_root = out.join(&config.build).join("stage0/bin"); - let rustc = match config.rustc { - Some(ref s) => PathBuf::from(s), - None => stage0_root.join(exe("rustc", &config.build)), - }; - let cargo = match config.cargo { - Some(ref s) => PathBuf::from(s), - None => stage0_root.join(exe("cargo", &config.build)), - }; - let local_rebuild = config.local_rebuild; - let is_sudo = match env::var_os("SUDO_USER") { Some(sudo_user) => { match env::var_os("USER") { @@ -254,32 +247,64 @@ impl Build { let rust_info = channel::GitInfo::new(&src); let cargo_info = channel::GitInfo::new(&src.join("src/tools/cargo")); let rls_info = channel::GitInfo::new(&src.join("src/tools/rls")); - let src_is_git = src.join(".git").exists(); + + let hosts = if !flags.host.is_empty() { + for host in flags.host.iter() { + if !config.host.contains(host) { + panic!("specified host `{}` is not in configuration", host); + } + } + flags.host.clone() + } else { + config.host.clone() + }; + let targets = if !flags.target.is_empty() { + for target in flags.target.iter() { + if !config.target.contains(target) { + panic!("specified target `{}` is not in configuration", target); + } + } + flags.target.clone() + } else { + config.target.clone() + }; Build { + initial_rustc: config.initial_rustc.clone(), + initial_cargo: config.initial_cargo.clone(), + local_rebuild: config.local_rebuild, + fail_fast: flags.cmd.fail_fast(), + verbosity: cmp::max(flags.verbose, config.verbose), + + build: config.host[0].clone(), + hosts: hosts, + targets: targets, + flags: flags, config: config, - cargo: cargo, - rustc: rustc, src: src, out: out, rust_info: rust_info, cargo_info: cargo_info, rls_info: rls_info, - local_rebuild: local_rebuild, cc: HashMap::new(), cxx: HashMap::new(), crates: HashMap::new(), lldb_version: None, lldb_python_dir: None, is_sudo: is_sudo, - src_is_git: src_is_git, ci_env: CiEnv::current(), delayed_failures: Cell::new(0), } } + fn build_slice(&self) -> &[String] { + unsafe { + std::slice::from_raw_parts(&self.build, 1) + } + } + /// Executes the entire build, as configured by the flags and configuration. pub fn build(&mut self) { unsafe { @@ -296,7 +321,7 @@ impl Build { sanity::check(self); // If local-rust is the same major.minor as the current version, then force a local-rebuild let local_version_verbose = output( - Command::new(&self.rustc).arg("--version").arg("--verbose")); + Command::new(&self.initial_rustc).arg("--version").arg("--verbose")); let local_release = local_version_verbose .lines().filter(|x| x.starts_with("release:")) .next().unwrap().trim_left_matches("release:").trim(); @@ -338,7 +363,7 @@ impl Build { mode: Mode, target: &str, cmd: &str) -> Command { - let mut cargo = Command::new(&self.cargo); + let mut cargo = Command::new(&self.initial_cargo); let out_dir = self.stage_out(compiler, mode); cargo.env("CARGO_TARGET_DIR", out_dir) .arg(cmd) @@ -347,7 +372,7 @@ impl Build { // FIXME: Temporary fix for https://github.com/rust-lang/cargo/issues/3005 // Force cargo to output binaries with disambiguating hashes in the name - cargo.env("__CARGO_DEFAULT_LIB_METADATA", "1"); + cargo.env("__CARGO_DEFAULT_LIB_METADATA", &self.config.channel); let stage; if compiler.stage == 0 && self.local_rebuild { @@ -422,7 +447,7 @@ impl Build { // library up and running, so we can use the normal compiler to compile // build scripts in that situation. if mode == Mode::Libstd { - cargo.env("RUSTC_SNAPSHOT", &self.rustc) + cargo.env("RUSTC_SNAPSHOT", &self.initial_rustc) .env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_snapshot_libdir()); } else { cargo.env("RUSTC_SNAPSHOT", self.compiler_path(compiler)) @@ -441,8 +466,7 @@ impl Build { cargo.env("RUSTC_ON_FAIL", on_fail); } - let verbose = cmp::max(self.config.verbose, self.flags.verbose); - cargo.env("RUSTC_VERBOSE", format!("{}", verbose)); + cargo.env("RUSTC_VERBOSE", format!("{}", self.verbosity)); // Specify some various options for build scripts used throughout // the build. @@ -480,7 +504,7 @@ impl Build { // FIXME: should update code to not require this env var cargo.env("CFG_COMPILER_HOST_TRIPLE", target); - if self.config.verbose() || self.flags.verbose() { + if self.is_verbose() { cargo.arg("-v"); } // FIXME: cargo bench does not accept `--release` @@ -496,13 +520,13 @@ impl Build { self.ci_env.force_coloring_in_ci(&mut cargo); - return cargo + cargo } /// Get a path to the compiler specified. fn compiler_path(&self, compiler: &Compiler) -> PathBuf { if compiler.is_snapshot(self) { - self.rustc.clone() + self.initial_rustc.clone() } else { self.sysroot(compiler).join("bin").join(exe("rustc", compiler.host)) } @@ -519,7 +543,7 @@ impl Build { let mut rustdoc = self.compiler_path(compiler); rustdoc.pop(); rustdoc.push(exe("rustdoc", compiler.host)); - return rustdoc + rustdoc } /// Get a `Command` which is ready to run `tool` in `stage` built for @@ -527,7 +551,7 @@ impl Build { fn tool_cmd(&self, compiler: &Compiler, tool: &str) -> Command { let mut cmd = Command::new(self.tool(&compiler, tool)); self.prepare_tool_cmd(compiler, &mut cmd); - return cmd + cmd } /// Prepares the `cmd` provided to be able to run the `compiler` provided. @@ -578,7 +602,7 @@ impl Build { if self.config.profiler { features.push_str(" profiler"); } - return features + features } /// Get the space-separated set of activated features for the compiler. @@ -587,7 +611,7 @@ impl Build { if self.config.use_jemalloc { features.push_str(" jemalloc"); } - return features + features } /// Component directory that Cargo will produce output into (e.g. @@ -760,7 +784,7 @@ impl Build { /// Returns the libdir of the snapshot compiler. fn rustc_snapshot_libdir(&self) -> PathBuf { - self.rustc.parent().unwrap().parent().unwrap() + self.initial_rustc.parent().unwrap().parent().unwrap() .join(libdir(&self.config.build)) } @@ -792,9 +816,17 @@ impl Build { try_run_suppressed(cmd) } + pub fn is_verbose(&self) -> bool { + self.verbosity > 0 + } + + pub fn is_very_verbose(&self) -> bool { + self.verbosity > 1 + } + /// Prints a message if this build is configured in verbose mode. fn verbose(&self, msg: &str) { - if self.flags.verbose() || self.config.verbose() { + if self.is_verbose() { println!("{}", msg); } } @@ -802,7 +834,7 @@ impl Build { /// Returns the number of parallel jobs that have been configured for this /// build. fn jobs(&self) -> u32 { - self.flags.jobs.unwrap_or(num_cpus::get() as u32) + self.flags.jobs.unwrap_or_else(|| num_cpus::get() as u32) } /// Returns the path to the C compiler for the target specified. @@ -834,7 +866,7 @@ impl Build { if target == "i686-pc-windows-gnu" { base.push("-fno-omit-frame-pointer".into()); } - return base + base } /// Returns the path to the `ar` archive utility for the target specified. @@ -866,7 +898,7 @@ impl Build { !target.contains("emscripten") { base.push(format!("-Clinker={}", self.cc(target).display())); } - return base + base } /// Returns the "musl root" for this `target`, if defined @@ -1047,7 +1079,7 @@ impl<'a> Compiler<'a> { /// Returns whether this is a snapshot compiler for `build`'s configuration fn is_snapshot(&self, build: &Build) -> bool { - self.stage == 0 && self.host == build.config.build + self.stage == 0 && self.host == build.build } /// Returns if this compiler should be treated as a final stage one in the diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/metadata.rs index 7b6b01655df..9326bb7129a 100644 --- a/src/bootstrap/metadata.rs +++ b/src/bootstrap/metadata.rs @@ -56,7 +56,7 @@ fn build_krate(build: &mut Build, krate: &str) { // of packages we're going to have to know what `-p` arguments to pass it // to know what crates to test. Here we run `cargo metadata` to learn about // the dependency graph and what `-p` arguments there are. - let mut cargo = Command::new(&build.cargo); + let mut cargo = Command::new(&build.initial_cargo); cargo.arg("metadata") .arg("--format-version").arg("1") .arg("--manifest-path").arg(build.src.join(krate).join("Cargo.toml")); diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index f150df6cdcd..20eec97d8e5 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -94,7 +94,7 @@ pub fn llvm(build: &Build, target: &str) { let assertions = if build.config.llvm_assertions {"ON"} else {"OFF"}; cfg.target(target) - .host(&build.config.build) + .host(&build.build) .out_dir(&out_dir) .profile(profile) .define("LLVM_ENABLE_ASSERTIONS", assertions) @@ -129,11 +129,11 @@ pub fn llvm(build: &Build, target: &str) { } // http://llvm.org/docs/HowToCrossCompileLLVM.html - if target != build.config.build { + if target != build.build { // FIXME: if the llvm root for the build triple is overridden then we // should use llvm-tblgen from there, also should verify that it // actually exists most of the time in normal installs of LLVM. - let host = build.llvm_out(&build.config.build).join("bin/llvm-tblgen"); + let host = build.llvm_out(&build.build).join("bin/llvm-tblgen"); cfg.define("CMAKE_CROSSCOMPILING", "True") .define("LLVM_TABLEGEN", &host); } @@ -243,7 +243,7 @@ pub fn test_helpers(build: &Build, target: &str) { cfg.cargo_metadata(false) .out_dir(&dst) .target(target) - .host(&build.config.build) + .host(&build.build) .opt_level(0) .debug(false) .file(build.src.join("src/rt/rust_test_helpers.c")) diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 46d047bb015..a9c1b023dd4 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -18,9 +18,9 @@ //! In theory if we get past this phase it's a bug if a build fails, but in //! practice that's likely not true! -use std::collections::HashSet; +use std::collections::HashMap; use std::env; -use std::ffi::{OsStr, OsString}; +use std::ffi::{OsString, OsStr}; use std::fs; use std::process::Command; use std::path::PathBuf; @@ -29,45 +29,59 @@ use build_helper::output; use Build; +struct Finder { + cache: HashMap>, + path: OsString, +} + +impl Finder { + fn new() -> Self { + Self { + cache: HashMap::new(), + path: env::var_os("PATH").unwrap_or_default() + } + } + + fn maybe_have>(&mut self, cmd: S) -> Option { + let cmd: OsString = cmd.as_ref().into(); + let path = self.path.clone(); + self.cache.entry(cmd.clone()).or_insert_with(|| { + for path in env::split_paths(&path) { + let target = path.join(&cmd); + let mut cmd_alt = cmd.clone(); + cmd_alt.push(".exe"); + if target.is_file() || // some/path/git + target.with_extension("exe").exists() || // some/path/git.exe + target.join(&cmd_alt).exists() { // some/path/git/git.exe + return Some(target); + } + } + None + }).clone() + } + + fn must_have>(&mut self, cmd: S) -> PathBuf { + self.maybe_have(&cmd).unwrap_or_else(|| { + panic!("\n\ncouldn't find required command: {:?}\n\n", cmd.as_ref()); + }) + } +} + pub fn check(build: &mut Build) { - let mut checked = HashSet::new(); - let path = env::var_os("PATH").unwrap_or(OsString::new()); + let path = env::var_os("PATH").unwrap_or_default(); // On Windows, quotes are invalid characters for filename paths, and if // one is present as part of the PATH then that can lead to the system // being unable to identify the files properly. See // https://github.com/rust-lang/rust/issues/34959 for more details. - if cfg!(windows) { - if path.to_string_lossy().contains("\"") { - panic!("PATH contains invalid character '\"'"); - } + if cfg!(windows) && path.to_string_lossy().contains("\"") { + panic!("PATH contains invalid character '\"'"); } - let have_cmd = |cmd: &OsStr| { - for path in env::split_paths(&path) { - let target = path.join(cmd); - let mut cmd_alt = cmd.to_os_string(); - cmd_alt.push(".exe"); - if target.is_file() || - target.with_extension("exe").exists() || - target.join(cmd_alt).exists() { - return Some(target); - } - } - return None; - }; - - let mut need_cmd = |cmd: &OsStr| { - if !checked.insert(cmd.to_owned()) { - return - } - if have_cmd(cmd).is_none() { - panic!("\n\ncouldn't find required command: {:?}\n\n", cmd); - } - }; + let mut cmd_finder = Finder::new(); // If we've got a git directory we're gona need git to update // submodules and learn about various other aspects. - if build.src_is_git { - need_cmd("git".as_ref()); + if build.rust_info.is_git() { + cmd_finder.must_have("git"); } // We need cmake, but only if we're actually building LLVM or sanitizers. @@ -75,57 +89,32 @@ pub fn check(build: &mut Build) { .filter_map(|host| build.config.target_config.get(host)) .any(|config| config.llvm_config.is_none()); if building_llvm || build.config.sanitizers { - need_cmd("cmake".as_ref()); + cmd_finder.must_have("cmake"); } // Ninja is currently only used for LLVM itself. - if building_llvm && build.config.ninja { - // Some Linux distros rename `ninja` to `ninja-build`. - // CMake can work with either binary name. - if have_cmd("ninja-build".as_ref()).is_none() { - need_cmd("ninja".as_ref()); - } + // Some Linux distros rename `ninja` to `ninja-build`. + // CMake can work with either binary name. + if building_llvm && build.config.ninja && cmd_finder.maybe_have("ninja-build").is_none() { + cmd_finder.must_have("ninja"); } - if build.config.python.is_none() { - // set by bootstrap.py - if let Some(v) = env::var_os("BOOTSTRAP_PYTHON") { - build.config.python = Some(PathBuf::from(v)); - } - } - if build.config.python.is_none() { - build.config.python = have_cmd("python2.7".as_ref()); - } - if build.config.python.is_none() { - build.config.python = have_cmd("python2".as_ref()); - } - if build.config.python.is_none() { - need_cmd("python".as_ref()); - build.config.python = Some("python".into()); - } - need_cmd(build.config.python.as_ref().unwrap().as_ref()); + build.config.python = build.config.python.take().map(|p| cmd_finder.must_have(p)) + .or_else(|| env::var_os("BOOTSTRAP_PYTHON").map(PathBuf::from)) // set by bootstrap.py + .or_else(|| cmd_finder.maybe_have("python2.7")) + .or_else(|| cmd_finder.maybe_have("python2")) + .or_else(|| Some(cmd_finder.must_have("python"))); + build.config.nodejs = build.config.nodejs.take().map(|p| cmd_finder.must_have(p)) + .or_else(|| cmd_finder.maybe_have("node")) + .or_else(|| cmd_finder.maybe_have("nodejs")); - if let Some(ref s) = build.config.nodejs { - need_cmd(s.as_ref()); - } else { - // Look for the nodejs command, needed for emscripten testing - if let Some(node) = have_cmd("node".as_ref()) { - build.config.nodejs = Some(node); - } else if let Some(node) = have_cmd("nodejs".as_ref()) { - build.config.nodejs = Some(node); - } - } - - if let Some(ref gdb) = build.config.gdb { - need_cmd(gdb.as_ref()); - } else { - build.config.gdb = have_cmd("gdb".as_ref()); - } + build.config.gdb = build.config.gdb.take().map(|p| cmd_finder.must_have(p)) + .or_else(|| cmd_finder.maybe_have("gdb")); // We're gonna build some custom C code here and there, host triples // also build some C++ shims for LLVM so we need a C++ compiler. - for target in build.config.target.iter() { + for target in &build.config.target { // On emscripten we don't actually need the C compiler to just // build the target artifacts, only for testing. For the sake // of easier bot configuration, just skip detection. @@ -133,33 +122,32 @@ pub fn check(build: &mut Build) { continue; } - need_cmd(build.cc(target).as_ref()); + cmd_finder.must_have(build.cc(target)); if let Some(ar) = build.ar(target) { - need_cmd(ar.as_ref()); + cmd_finder.must_have(ar); } } - for host in build.config.host.iter() { - need_cmd(build.cxx(host).unwrap().as_ref()); - } - // The msvc hosts don't use jemalloc, turn it off globally to - // avoid packaging the dummy liballoc_jemalloc on that platform. for host in build.config.host.iter() { + cmd_finder.must_have(build.cxx(host).unwrap()); + + // The msvc hosts don't use jemalloc, turn it off globally to + // avoid packaging the dummy liballoc_jemalloc on that platform. if host.contains("msvc") { build.config.use_jemalloc = false; } } // Externally configured LLVM requires FileCheck to exist - let filecheck = build.llvm_filecheck(&build.config.build); + let filecheck = build.llvm_filecheck(&build.build); if !filecheck.starts_with(&build.out) && !filecheck.exists() && build.config.codegen_tests { panic!("FileCheck executable {:?} does not exist", filecheck); } - for target in build.config.target.iter() { + for target in &build.config.target { // Can't compile for iOS unless we're on macOS if target.contains("apple-ios") && - !build.config.build.contains("apple-darwin") { + !build.build.contains("apple-darwin") { panic!("the iOS target is only supported on macOS"); } @@ -206,18 +194,6 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake } } - for host in build.flags.host.iter() { - if !build.config.host.contains(host) { - panic!("specified host `{}` is not in the ./configure list", host); - } - } - for target in build.flags.target.iter() { - if !build.config.target.contains(target) { - panic!("specified target `{}` is not in the ./configure list", - target); - } - } - let run = |cmd: &mut Command| { cmd.output().map(|output| { String::from_utf8_lossy(&output.stdout) @@ -231,6 +207,6 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake } if let Some(ref s) = build.config.ccache { - need_cmd(s.as_ref()); + cmd_finder.must_have(s); } } diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index 5f0724c6577..c221d707683 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -104,10 +104,10 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { rules.build("llvm", "src/llvm") .host(true) .dep(move |s| { - if s.target == build.config.build { + if s.target == build.build { Step::noop() } else { - s.target(&build.config.build) + s.target(&build.build) } }) .run(move |s| native::llvm(build, s.target)); @@ -124,7 +124,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { Step::noop() } else { s.name("librustc") - .host(&build.config.build) + .host(&build.build) .stage(s.stage - 1) } }) @@ -148,7 +148,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { } } } - return ret + ret }; // ======================================================================== @@ -215,29 +215,29 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { let mut rule = rules.build(&krate, "path/to/nowhere"); rule.dep(move |s| { if build.force_use_stage1(&s.compiler(), s.target) { - s.host(&build.config.build).stage(1) - } else if s.host == build.config.build { + s.host(&build.build).stage(1) + } else if s.host == build.build { s.name(dep) } else { - s.host(&build.config.build) + s.host(&build.build) } }) .run(move |s| { if build.force_use_stage1(&s.compiler(), s.target) { link(build, - &s.stage(1).host(&build.config.build).compiler(), + &s.stage(1).host(&build.build).compiler(), &s.compiler(), s.target) - } else if s.host == build.config.build { + } else if s.host == build.build { link(build, &s.compiler(), &s.compiler(), s.target) } else { link(build, - &s.host(&build.config.build).compiler(), + &s.host(&build.build).compiler(), &s.compiler(), s.target) } }); - return rule + rule } // Similar to the `libstd`, `libtest`, and `librustc` rules above, except @@ -269,7 +269,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { for (krate, path, _default) in krates("std") { rules.build(&krate.build_step, path) .dep(|s| s.name("startup-objects")) - .dep(move |s| s.name("rustc").host(&build.config.build).target(s.host)) + .dep(move |s| s.name("rustc").host(&build.build).target(s.host)) .run(move |s| compile::std(build, s.target, &s.compiler())); } for (krate, path, _default) in krates("test") { @@ -280,7 +280,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { for (krate, path, _default) in krates("rustc-main") { rules.build(&krate.build_step, path) .dep(|s| s.name("libtest-link")) - .dep(move |s| s.name("llvm").host(&build.config.build).stage(0)) + .dep(move |s| s.name("llvm").host(&build.build).stage(0)) .dep(|s| s.name("may-run-build-script")) .run(move |s| compile::rustc(build, s.target, &s.compiler())); } @@ -291,8 +291,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { rules.build("may-run-build-script", "path/to/nowhere") .dep(move |s| { s.name("libstd-link") - .host(&build.config.build) - .target(&build.config.build) + .host(&build.build) + .target(&build.build) }); rules.build("startup-objects", "src/rtstartup") .dep(|s| s.name("create-sysroot").target(s.host)) @@ -332,7 +332,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { "incremental"); } - if build.config.build.contains("msvc") { + if build.build.contains("msvc") { // nothing to do for debuginfo tests } else { rules.test("check-debuginfo-lldb", "src/test/debuginfo-lldb") @@ -352,7 +352,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { "debuginfo-gdb", "debuginfo")); let mut rule = rules.test("check-debuginfo", "src/test/debuginfo"); rule.default(true); - if build.config.build.contains("apple") { + if build.build.contains("apple") { rule.dep(|s| s.name("check-debuginfo-lldb")); } else { rule.dep(|s| s.name("check-debuginfo-gdb")); @@ -594,8 +594,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { // Cargo depends on procedural macros, which requires a full host // compiler to be available, so we need to depend on that. s.name("librustc-link") - .target(&build.config.build) - .host(&build.config.build) + .target(&build.build) + .host(&build.build) }) .run(move |s| compile::tool(build, s.stage, s.target, "cargo")); rules.build("tool-rls", "src/tools/rls") @@ -606,8 +606,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { .dep(move |s| { // rls, like cargo, uses procedural macros s.name("librustc-link") - .target(&build.config.build) - .host(&build.config.build) + .target(&build.build) + .host(&build.build) }) .run(move |s| compile::tool(build, s.stage, s.target, "rls")); @@ -635,8 +635,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { rules.doc("doc-book", "src/doc/book") .dep(move |s| { s.name("tool-rustbook") - .host(&build.config.build) - .target(&build.config.build) + .host(&build.build) + .target(&build.build) .stage(0) }) .default(build.config.docs) @@ -644,8 +644,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { rules.doc("doc-nomicon", "src/doc/nomicon") .dep(move |s| { s.name("tool-rustbook") - .host(&build.config.build) - .target(&build.config.build) + .host(&build.build) + .target(&build.build) .stage(0) }) .default(build.config.docs) @@ -653,8 +653,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { rules.doc("doc-reference", "src/doc/reference") .dep(move |s| { s.name("tool-rustbook") - .host(&build.config.build) - .target(&build.config.build) + .host(&build.build) + .target(&build.build) .stage(0) }) .default(build.config.docs) @@ -662,8 +662,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { rules.doc("doc-unstable-book", "src/doc/unstable-book") .dep(move |s| { s.name("tool-rustbook") - .host(&build.config.build) - .target(&build.config.build) + .host(&build.build) + .target(&build.build) .stage(0) }) .dep(move |s| s.name("doc-unstable-book-gen")) @@ -675,14 +675,14 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { rules.doc("doc-standalone", "src/doc") .dep(move |s| { s.name("rustc") - .host(&build.config.build) - .target(&build.config.build) + .host(&build.build) + .target(&build.build) .stage(0) }) .default(build.config.docs) .run(move |s| doc::standalone(build, s.target)); rules.doc("doc-error-index", "src/tools/error_index_generator") - .dep(move |s| s.name("tool-error-index").target(&build.config.build).stage(0)) + .dep(move |s| s.name("tool-error-index").target(&build.build).stage(0)) .dep(move |s| s.name("librustc-link")) .default(build.config.docs) .host(true) @@ -690,8 +690,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { rules.doc("doc-unstable-book-gen", "src/tools/unstable-book-gen") .dep(move |s| { s.name("tool-unstable-book-gen") - .host(&build.config.build) - .target(&build.config.build) + .host(&build.build) + .target(&build.build) .stage(0) }) .dep(move |s| s.name("libstd-link")) @@ -725,7 +725,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { // ======================================================================== // Distribution targets rules.dist("dist-rustc", "src/librustc") - .dep(move |s| s.name("rustc").host(&build.config.build)) + .dep(move |s| s.name("rustc").host(&build.build)) .host(true) .only_host_build(true) .default(true) @@ -811,7 +811,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { .host(true) .only_build(true) .only_host_build(true) - .dep(move |s| s.name("tool-build-manifest").target(&build.config.build).stage(0)) + .dep(move |s| s.name("tool-build-manifest").target(&build.build).stage(0)) .run(move |_| dist::hash_and_sign(build)); rules.install("install-docs", "src/doc") @@ -861,8 +861,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { /// Helper to depend on a stage0 build-only rust-installer tool. fn tool_rust_installer<'a>(build: &'a Build, step: &Step<'a>) -> Step<'a> { step.name("tool-rust-installer") - .host(&build.config.build) - .target(&build.config.build) + .host(&build.build) + .target(&build.build) .stage(0) } } @@ -1058,8 +1058,8 @@ impl<'a> Rules<'a> { build: build, sbuild: Step { stage: build.flags.stage.unwrap_or(2), - target: &build.config.build, - host: &build.config.build, + target: &build.build, + host: &build.build, name: "", }, rules: BTreeMap::new(), @@ -1218,16 +1218,9 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd? rules.into_iter().flat_map(|(rule, _)| { let hosts = if rule.only_host_build || rule.only_build { - &self.build.config.host[..1] - } else if self.build.flags.host.len() > 0 { - &self.build.flags.host + self.build.build_slice() } else { - &self.build.config.host - }; - let targets = if self.build.flags.target.len() > 0 { - &self.build.flags.target - } else { - &self.build.config.target + &self.build.hosts }; // Determine the actual targets participating in this rule. // NOTE: We should keep the full projection from build triple to @@ -1236,19 +1229,18 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd? // the original non-shadowed hosts array is used below. let arr = if rule.host { // If --target was specified but --host wasn't specified, - // don't run any host-only tests. Also, respect any `--host` - // overrides as done for `hosts`. + // don't run any host-only tests. if self.build.flags.host.len() > 0 { - &self.build.flags.host[..] + &self.build.hosts } else if self.build.flags.target.len() > 0 { &[] } else if rule.only_build { - &self.build.config.host[..1] + self.build.build_slice() } else { - &self.build.config.host[..] + &self.build.hosts } } else { - targets + &self.build.targets }; hosts.iter().flat_map(move |host| { @@ -1326,7 +1318,7 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd? for idx in 0..nodes.len() { self.topo_sort(idx, &idx_to_node, &edges, &mut visited, &mut order); } - return order + order } /// Builds the dependency graph rooted at `step`. @@ -1365,7 +1357,7 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd? } edges.entry(idx).or_insert(HashSet::new()).extend(deps); - return idx + idx } /// Given a dependency graph with a finished list of `nodes`, fill out more @@ -1494,8 +1486,8 @@ mod tests { let step = super::Step { name: "", stage: 2, - host: &build.config.build, - target: &build.config.build, + host: &build.build, + target: &build.build, }; assert!(plan.contains(&step.name("dist-docs"))); @@ -1517,8 +1509,8 @@ mod tests { let step = super::Step { name: "", stage: 2, - host: &build.config.build, - target: &build.config.build, + host: &build.build, + target: &build.build, }; assert!(plan.contains(&step.name("dist-docs"))); @@ -1545,8 +1537,8 @@ mod tests { let step = super::Step { name: "", stage: 2, - host: &build.config.build, - target: &build.config.build, + host: &build.build, + target: &build.build, }; assert!(!plan.iter().any(|s| s.host == "B")); @@ -1575,8 +1567,8 @@ mod tests { let step = super::Step { name: "", stage: 2, - host: &build.config.build, - target: &build.config.build, + host: &build.build, + target: &build.build, }; assert!(!plan.iter().any(|s| s.host == "B")); @@ -1612,8 +1604,8 @@ mod tests { let step = super::Step { name: "", stage: 2, - host: &build.config.build, - target: &build.config.build, + host: &build.build, + target: &build.build, }; assert!(!plan.iter().any(|s| s.target == "A")); @@ -1639,8 +1631,8 @@ mod tests { let step = super::Step { name: "", stage: 2, - host: &build.config.build, - target: &build.config.build, + host: &build.build, + target: &build.build, }; assert!(!plan.iter().any(|s| s.target == "A")); @@ -1683,8 +1675,8 @@ mod tests { let step = super::Step { name: "", stage: 2, - host: &build.config.build, - target: &build.config.build, + host: &build.build, + target: &build.build, }; // rustc built for all for of (A, B) x (A, B) diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index 61bd85e76c5..092fb04637b 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -14,7 +14,6 @@ //! not a lot of interesting happenings here unfortunately. use std::env; -use std::ffi::OsString; use std::fs; use std::io::{self, Write}; use std::path::{Path, PathBuf}; @@ -32,16 +31,9 @@ pub fn staticlib(name: &str, target: &str) -> String { } } -/// Copies a file from `src` to `dst`, attempting to use hard links and then -/// falling back to an actually filesystem copy if necessary. +/// Copies a file from `src` to `dst` pub fn copy(src: &Path, dst: &Path) { - // A call to `hard_link` will fail if `dst` exists, so remove it if it - // already exists so we can try to help `hard_link` succeed. let _ = fs::remove_file(&dst); - - // Attempt to "easy copy" by creating a hard link (symlinks don't work on - // windows), but if that fails just fall back to a slow `copy` operation. - // let res = fs::hard_link(src, dst); let res = fs::copy(src, dst); if let Err(e) = res { panic!("failed to copy `{}` to `{}`: {}", src.display(), @@ -149,8 +141,7 @@ pub fn dylib_path_var() -> &'static str { /// Parses the `dylib_path_var()` environment variable, returning a list of /// paths that are members of this lookup path. pub fn dylib_path() -> Vec { - env::split_paths(&env::var_os(dylib_path_var()).unwrap_or(OsString::new())) - .collect() + env::split_paths(&env::var_os(dylib_path_var()).unwrap_or_default()).collect() } /// `push` all components to `buf`. On windows, append `.exe` to the last component. @@ -422,4 +413,4 @@ impl CiEnv { cmd.env("TERM", "xterm").args(&["--color", "always"]); } } -} \ No newline at end of file +} diff --git a/src/doc/unstable-book/src/language-features/compile-error.md b/src/doc/unstable-book/src/language-features/compile-error.md index 1b25eeda3f6..4b24c0a6a0d 100644 --- a/src/doc/unstable-book/src/language-features/compile-error.md +++ b/src/doc/unstable-book/src/language-features/compile-error.md @@ -2,7 +2,7 @@ The tracking issue for this feature is: [#40872] -[#29599]: https://github.com/rust-lang/rust/issues/40872 +[#40872]: https://github.com/rust-lang/rust/issues/40872 ------------------------ diff --git a/src/doc/unstable-book/src/language-features/lang-items.md b/src/doc/unstable-book/src/language-features/lang-items.md index 375b8bd6b82..a2368ee5f4a 100644 --- a/src/doc/unstable-book/src/language-features/lang-items.md +++ b/src/doc/unstable-book/src/language-features/lang-items.md @@ -143,7 +143,8 @@ pub extern fn rust_eh_unwind_resume() { #[no_mangle] pub extern fn rust_begin_panic(_msg: core::fmt::Arguments, _file: &'static str, - _line: u32) -> ! { + _line: u32, + _column: u32) -> ! { unsafe { intrinsics::abort() } } ``` @@ -187,7 +188,8 @@ pub extern fn rust_eh_unwind_resume() { #[no_mangle] pub extern fn rust_begin_panic(_msg: core::fmt::Arguments, _file: &'static str, - _line: u32) -> ! { + _line: u32, + _column: u32) -> ! { unsafe { intrinsics::abort() } } ``` diff --git a/src/doc/unstable-book/src/language-features/unsized-tuple-coercion.md b/src/doc/unstable-book/src/language-features/unsized-tuple-coercion.md new file mode 100644 index 00000000000..200a9c19462 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/unsized-tuple-coercion.md @@ -0,0 +1,27 @@ +# `unsized_tuple_coercion` + +The tracking issue for this feature is: [#42877] + +[#42877]: https://github.com/rust-lang/rust/issues/42877 + +------------------------ + +This is a part of [RFC0401]. According to the RFC, there should be an implementation like this: + +```rust +impl<..., T, U: ?Sized> Unsized<(..., U)> for (..., T) where T: Unsized {} +``` + +This implementation is currently gated behind `#[feature(unsized_tuple_coercion)]` to avoid insta-stability. Therefore you can use it like this: + +```rust +#![feature(unsized_tuple_coercion)] + +fn main() { + let x : ([i32; 3], [i32; 3]) = ([1, 2, 3], [4, 5, 6]); + let y : &([i32; 3], [i32]) = &x; + assert_eq!(y.1[0], 4); +} +``` + +[RFC0401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md diff --git a/src/doc/unstable-book/src/library-features/iterator-for-each.md b/src/doc/unstable-book/src/library-features/iterator-for-each.md new file mode 100644 index 00000000000..ebeb5f6a1de --- /dev/null +++ b/src/doc/unstable-book/src/library-features/iterator-for-each.md @@ -0,0 +1,17 @@ +# `iterator_for_each` + +The tracking issue for this feature is: [#42986] + +[#42986]: https://github.com/rust-lang/rust/issues/42986 + +------------------------ + +To call a closure on each element of an iterator, you can use `for_each`: + +```rust +#![feature(iterator_for_each)] + +fn main() { + (0..10).for_each(|i| println!("{}", i)); +} +``` diff --git a/src/doc/unstable-book/src/library-features/more-io-inner-methods.md b/src/doc/unstable-book/src/library-features/more-io-inner-methods.md deleted file mode 100644 index c84f40e7ee5..00000000000 --- a/src/doc/unstable-book/src/library-features/more-io-inner-methods.md +++ /dev/null @@ -1,11 +0,0 @@ -# `more_io_inner_methods` - -The tracking issue for this feature is: [#41519] - -[#41519]: https://github.com/rust-lang/rust/issues/41519 - ------------------------- - -This feature enables several internal accessor methods on structures in -`std::io` including `Take::{get_ref, get_mut}` and `Chain::{into_inner, get_ref, -get_mut}`. diff --git a/src/doc/unstable-book/src/library-features/sort-unstable.md b/src/doc/unstable-book/src/library-features/sort-unstable.md deleted file mode 100644 index 9effcfc774c..00000000000 --- a/src/doc/unstable-book/src/library-features/sort-unstable.md +++ /dev/null @@ -1,40 +0,0 @@ -# `sort_unstable` - -The tracking issue for this feature is: [#40585] - -[#40585]: https://github.com/rust-lang/rust/issues/40585 - ------------------------- - -The default `sort` method on slices is stable. In other words, it guarantees -that the original order of equal elements is preserved after sorting. The -method has several undesirable characteristics: - -1. It allocates a sizable chunk of memory. -2. If you don't need stability, it is not as performant as it could be. - -An alternative is the new `sort_unstable` feature, which includes these -methods for sorting slices: - -1. `sort_unstable` -2. `sort_unstable_by` -3. `sort_unstable_by_key` - -Unstable sorting is generally faster and makes no allocations. The majority -of real-world sorting needs doesn't require stability, so these methods can -very often come in handy. - -Another important difference is that `sort` lives in `libstd` and -`sort_unstable` lives in `libcore`. The reason is that the former makes -allocations and the latter doesn't. - -A simple example: - -```rust -#![feature(sort_unstable)] - -let mut v = [-5, 4, 1, -3, 2]; - -v.sort_unstable(); -assert!(v == [-5, -3, 1, 2, 4]); -``` diff --git a/src/liballoc/allocator.rs b/src/liballoc/allocator.rs index 9bddce29957..bf38629ed38 100644 --- a/src/liballoc/allocator.rs +++ b/src/liballoc/allocator.rs @@ -873,7 +873,7 @@ pub unsafe trait Alloc { { let k = Layout::new::(); if k.size() > 0 { - unsafe { self.alloc(k).map(|p|Unique::new(*p as *mut T)) } + unsafe { self.alloc(k).map(|p| Unique::new(p as *mut T)) } } else { Err(AllocErr::invalid_input("zero-sized type invalid for alloc_one")) } diff --git a/src/liballoc/benches/lib.rs b/src/liballoc/benches/lib.rs index 958020d0b0e..174628ccd07 100644 --- a/src/liballoc/benches/lib.rs +++ b/src/liballoc/benches/lib.rs @@ -14,9 +14,9 @@ #![feature(rand)] #![feature(repr_simd)] #![feature(slice_rotate)] -#![feature(sort_unstable)] #![feature(test)] +extern crate rand; extern crate test; mod btree; diff --git a/src/liballoc/benches/slice.rs b/src/liballoc/benches/slice.rs index aa5a438b35e..d99270e7f31 100644 --- a/src/liballoc/benches/slice.rs +++ b/src/liballoc/benches/slice.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::{mem, ptr}; -use std::__rand::{Rng, thread_rng}; +use std::__rand::{thread_rng}; +use std::mem; +use std::ptr; +use rand::{Rng, SeedableRng, XorShiftRng}; use test::{Bencher, black_box}; #[bench] @@ -191,17 +193,17 @@ fn gen_descending(len: usize) -> Vec { } fn gen_random(len: usize) -> Vec { - let mut rng = thread_rng(); + let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]); rng.gen_iter::().take(len).collect() } fn gen_random_bytes(len: usize) -> Vec { - let mut rng = thread_rng(); + let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]); rng.gen_iter::().take(len).collect() } fn gen_mostly_ascending(len: usize) -> Vec { - let mut rng = thread_rng(); + let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]); let mut v = gen_ascending(len); for _ in (0usize..).take_while(|x| x * x <= len) { let x = rng.gen::() % len; @@ -212,7 +214,7 @@ fn gen_mostly_ascending(len: usize) -> Vec { } fn gen_mostly_descending(len: usize) -> Vec { - let mut rng = thread_rng(); + let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]); let mut v = gen_descending(len); for _ in (0usize..).take_while(|x| x * x <= len) { let x = rng.gen::() % len; @@ -223,7 +225,7 @@ fn gen_mostly_descending(len: usize) -> Vec { } fn gen_strings(len: usize) -> Vec { - let mut rng = thread_rng(); + let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]); let mut v = vec![]; for _ in 0..len { let n = rng.gen::() % 20 + 1; @@ -233,7 +235,7 @@ fn gen_strings(len: usize) -> Vec { } fn gen_big_random(len: usize) -> Vec<[u64; 16]> { - let mut rng = thread_rng(); + let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]); rng.gen_iter().map(|x| [x; 16]).take(len).collect() } @@ -241,18 +243,32 @@ macro_rules! sort { ($f:ident, $name:ident, $gen:expr, $len:expr) => { #[bench] fn $name(b: &mut Bencher) { - b.iter(|| $gen($len).$f()); + let v = $gen($len); + b.iter(|| v.clone().$f()); b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64; } } } +macro_rules! sort_strings { + ($f:ident, $name:ident, $gen:expr, $len:expr) => { + #[bench] + fn $name(b: &mut Bencher) { + let v = $gen($len); + let v = v.iter().map(|s| &**s).collect::>(); + b.iter(|| v.clone().$f()); + b.bytes = $len * mem::size_of::<&str>() as u64; + } + } +} + macro_rules! sort_expensive { ($f:ident, $name:ident, $gen:expr, $len:expr) => { #[bench] fn $name(b: &mut Bencher) { + let v = $gen($len); b.iter(|| { - let mut v = $gen($len); + let mut v = v.clone(); let mut count = 0; v.$f(|a: &u64, b: &u64| { count += 1; @@ -263,7 +279,7 @@ macro_rules! sort_expensive { }); black_box(count); }); - b.bytes = $len as u64 * mem::size_of::() as u64; + b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64; } } } @@ -271,30 +287,30 @@ macro_rules! sort_expensive { sort!(sort, sort_small_ascending, gen_ascending, 10); sort!(sort, sort_small_descending, gen_descending, 10); sort!(sort, sort_small_random, gen_random, 10); -sort!(sort, sort_small_big_random, gen_big_random, 10); +sort!(sort, sort_small_big, gen_big_random, 10); sort!(sort, sort_medium_random, gen_random, 100); sort!(sort, sort_large_ascending, gen_ascending, 10000); sort!(sort, sort_large_descending, gen_descending, 10000); sort!(sort, sort_large_mostly_ascending, gen_mostly_ascending, 10000); sort!(sort, sort_large_mostly_descending, gen_mostly_descending, 10000); sort!(sort, sort_large_random, gen_random, 10000); -sort!(sort, sort_large_big_random, gen_big_random, 10000); -sort!(sort, sort_large_strings, gen_strings, 10000); -sort_expensive!(sort_by, sort_large_random_expensive, gen_random, 10000); +sort!(sort, sort_large_big, gen_big_random, 10000); +sort_strings!(sort, sort_large_strings, gen_strings, 10000); +sort_expensive!(sort_by, sort_large_expensive, gen_random, 10000); sort!(sort_unstable, sort_unstable_small_ascending, gen_ascending, 10); sort!(sort_unstable, sort_unstable_small_descending, gen_descending, 10); sort!(sort_unstable, sort_unstable_small_random, gen_random, 10); -sort!(sort_unstable, sort_unstable_small_big_random, gen_big_random, 10); +sort!(sort_unstable, sort_unstable_small_big, gen_big_random, 10); sort!(sort_unstable, sort_unstable_medium_random, gen_random, 100); sort!(sort_unstable, sort_unstable_large_ascending, gen_ascending, 10000); sort!(sort_unstable, sort_unstable_large_descending, gen_descending, 10000); sort!(sort_unstable, sort_unstable_large_mostly_ascending, gen_mostly_ascending, 10000); sort!(sort_unstable, sort_unstable_large_mostly_descending, gen_mostly_descending, 10000); sort!(sort_unstable, sort_unstable_large_random, gen_random, 10000); -sort!(sort_unstable, sort_unstable_large_big_random, gen_big_random, 10000); -sort!(sort_unstable, sort_unstable_large_strings, gen_strings, 10000); -sort_expensive!(sort_unstable_by, sort_unstable_large_random_expensive, gen_random, 10000); +sort!(sort_unstable, sort_unstable_large_big, gen_big_random, 10000); +sort_strings!(sort_unstable, sort_unstable_large_strings, gen_strings, 10000); +sort_expensive!(sort_unstable_by, sort_unstable_large_expensive, gen_random, 10000); macro_rules! reverse { ($name:ident, $ty:ty, $f:expr) => { diff --git a/src/liballoc/fmt.rs b/src/liballoc/fmt.rs index 1bd95fb82aa..4847b21c0b3 100644 --- a/src/liballoc/fmt.rs +++ b/src/liballoc/fmt.rs @@ -498,12 +498,10 @@ pub use core::fmt::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple}; use string; -/// The format function takes a precompiled format string and a list of -/// arguments, to return the resulting formatted string. +/// The `format` function takes an `Arguments` struct and returns the resulting +/// formatted string. /// -/// # Arguments -/// -/// * args - a structure of arguments generated via the `format_args!` macro. +/// The `Arguments` instance can be created with the `format_args!` macro. /// /// # Examples /// diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index ca52943ea97..23da2913136 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -83,7 +83,6 @@ #![cfg_attr(not(test), feature(core_float))] #![cfg_attr(not(test), feature(exact_size_is_empty))] #![cfg_attr(not(test), feature(slice_rotate))] -#![cfg_attr(not(test), feature(sort_unstable))] #![cfg_attr(not(test), feature(str_checked_slicing))] #![cfg_attr(test, feature(rand, test))] #![feature(allocator)] diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 88876999d76..f4c2b9d054b 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -1144,6 +1144,10 @@ impl [T] { /// /// This sort is stable (i.e. does not reorder equal elements) and `O(n log n)` worst-case. /// + /// When applicable, unstable sorting is preferred because it is generally faster than stable + /// sorting and it doesn't allocate auxiliary memory. + /// See [`sort_unstable`](#method.sort_unstable). + /// /// # Current implementation /// /// The current algorithm is an adaptive, iterative merge sort inspired by @@ -1174,6 +1178,10 @@ impl [T] { /// /// This sort is stable (i.e. does not reorder equal elements) and `O(n log n)` worst-case. /// + /// When applicable, unstable sorting is preferred because it is generally faster than stable + /// sorting and it doesn't allocate auxiliary memory. + /// See [`sort_unstable_by`](#method.sort_unstable_by). + /// /// # Current implementation /// /// The current algorithm is an adaptive, iterative merge sort inspired by @@ -1207,6 +1215,10 @@ impl [T] { /// /// This sort is stable (i.e. does not reorder equal elements) and `O(n log n)` worst-case. /// + /// When applicable, unstable sorting is preferred because it is generally faster than stable + /// sorting and it doesn't allocate auxiliary memory. + /// See [`sort_unstable_by_key`](#method.sort_unstable_by_key). + /// /// # Current implementation /// /// The current algorithm is an adaptive, iterative merge sort inspired by @@ -1251,8 +1263,6 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(sort_unstable)] - /// /// let mut v = [-5, 4, 1, -3, 2]; /// /// v.sort_unstable(); @@ -1260,8 +1270,7 @@ impl [T] { /// ``` /// /// [pdqsort]: https://github.com/orlp/pdqsort - // FIXME #40585: Mention `sort_unstable` in the documentation for `sort`. - #[unstable(feature = "sort_unstable", issue = "40585")] + #[stable(feature = "sort_unstable", since = "1.20.0")] #[inline] pub fn sort_unstable(&mut self) where T: Ord @@ -1288,8 +1297,6 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(sort_unstable)] - /// /// let mut v = [5, 4, 1, 3, 2]; /// v.sort_unstable_by(|a, b| a.cmp(b)); /// assert!(v == [1, 2, 3, 4, 5]); @@ -1300,8 +1307,7 @@ impl [T] { /// ``` /// /// [pdqsort]: https://github.com/orlp/pdqsort - // FIXME #40585: Mention `sort_unstable_by` in the documentation for `sort_by`. - #[unstable(feature = "sort_unstable", issue = "40585")] + #[stable(feature = "sort_unstable", since = "1.20.0")] #[inline] pub fn sort_unstable_by(&mut self, compare: F) where F: FnMut(&T, &T) -> Ordering @@ -1328,8 +1334,6 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(sort_unstable)] - /// /// let mut v = [-5i32, 4, 1, -3, 2]; /// /// v.sort_unstable_by_key(|k| k.abs()); @@ -1337,8 +1341,7 @@ impl [T] { /// ``` /// /// [pdqsort]: https://github.com/orlp/pdqsort - // FIXME #40585: Mention `sort_unstable_by_key` in the documentation for `sort_by_key`. - #[unstable(feature = "sort_unstable", issue = "40585")] + #[stable(feature = "sort_unstable", since = "1.20.0")] #[inline] pub fn sort_unstable_by_key(&mut self, f: F) where F: FnMut(&T) -> B, @@ -1794,7 +1797,7 @@ unsafe fn merge(v: &mut [T], mid: usize, buf: *mut T, is_less: &mut F) impl Drop for MergeHole { fn drop(&mut self) { - // `T` is not a zero-sized type, so it's okay to divide by it's size. + // `T` is not a zero-sized type, so it's okay to divide by its size. let len = (self.end as usize - self.start as usize) / mem::size_of::(); unsafe { ptr::copy_nonoverlapping(self.start, self.dest, len); } } @@ -1908,7 +1911,7 @@ fn merge_sort(v: &mut [T], mut is_less: F) // if `Some(r)` is returned, that means `runs[r]` and `runs[r + 1]` must be merged next. If the // algorithm should continue building a new run instead, `None` is returned. // - // TimSort is infamous for it's buggy implementations, as described here: + // TimSort is infamous for its buggy implementations, as described here: // http://envisage-project.eu/timsort-specification-and-verification/ // // The gist of the story is: we must enforce the invariants on the top four runs on the stack. diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 79d1ccf637d..622cc68964b 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -2008,10 +2008,10 @@ impl From> for String { } } -#[stable(feature = "box_from_str", since = "1.18.0")] -impl Into> for String { - fn into(self) -> Box { - self.into_boxed_str() +#[stable(feature = "box_from_str", since = "1.20.0")] +impl From for Box { + fn from(s: String) -> Box { + s.into_boxed_str() } } diff --git a/src/liballoc/tests/slice.rs b/src/liballoc/tests/slice.rs index 7fa65a2144e..c53bf15f1bf 100644 --- a/src/liballoc/tests/slice.rs +++ b/src/liballoc/tests/slice.rs @@ -396,18 +396,44 @@ fn test_sort() { let mut rng = thread_rng(); for len in (2..25).chain(500..510) { - for _ in 0..100 { - let mut v: Vec<_> = rng.gen_iter::().take(len).collect(); - let mut v1 = v.clone(); + for &modulus in &[5, 10, 100, 1000] { + for _ in 0..10 { + let orig: Vec<_> = rng.gen_iter::() + .map(|x| x % modulus) + .take(len) + .collect(); - v.sort(); - assert!(v.windows(2).all(|w| w[0] <= w[1])); + // Sort in default order. + let mut v = orig.clone(); + v.sort(); + assert!(v.windows(2).all(|w| w[0] <= w[1])); - v1.sort_by(|a, b| a.cmp(b)); - assert!(v1.windows(2).all(|w| w[0] <= w[1])); + // Sort in ascending order. + let mut v = orig.clone(); + v.sort_by(|a, b| a.cmp(b)); + assert!(v.windows(2).all(|w| w[0] <= w[1])); - v1.sort_by(|a, b| b.cmp(a)); - assert!(v1.windows(2).all(|w| w[0] >= w[1])); + // Sort in descending order. + let mut v = orig.clone(); + v.sort_by(|a, b| b.cmp(a)); + assert!(v.windows(2).all(|w| w[0] >= w[1])); + + // Sort with many pre-sorted runs. + let mut v = orig.clone(); + v.sort(); + v.reverse(); + for _ in 0..5 { + let a = rng.gen::() % len; + let b = rng.gen::() % len; + if a < b { + v[a..b].reverse(); + } else { + v.swap(a, b); + } + } + v.sort(); + assert!(v.windows(2).all(|w| w[0] <= w[1])); + } } } diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs index fdf453b39cf..17f1229c206 100644 --- a/src/liballoc/tests/vec.rs +++ b/src/liballoc/tests/vec.rs @@ -274,6 +274,11 @@ fn test_dedup_by() { vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b)); assert_eq!(vec, ["foo", "bar", "baz", "bar"]); + + let mut vec = vec![("foo", 1), ("foo", 2), ("bar", 3), ("bar", 4), ("bar", 5)]; + vec.dedup_by(|a, b| a.0 == b.0 && { b.1 += a.1; true }); + + assert_eq!(vec, [("foo", 3), ("bar", 12)]); } #[test] diff --git a/src/liballoc/tests/vec_deque.rs b/src/liballoc/tests/vec_deque.rs index a992351653d..f2935c05d4f 100644 --- a/src/liballoc/tests/vec_deque.rs +++ b/src/liballoc/tests/vec_deque.rs @@ -510,8 +510,7 @@ fn test_from_iter() { let u: Vec<_> = deq.iter().cloned().collect(); assert_eq!(u, v); - // FIXME #27741: Remove `.skip(0)` when Range::step_by is fully removed - let seq = (0..).skip(0).step_by(2).take(256); + let seq = (0..).step_by(2).take(256); let deq: VecDeque<_> = seq.collect(); for (i, &x) in deq.iter().enumerate() { assert_eq!(2 * i, x); diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 5d1999a4262..780a51aec3b 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -222,7 +222,7 @@ use Bound::{Excluded, Included, Unbounded}; /// on an empty Vec, it will not allocate memory. Similarly, if you store zero-sized /// types inside a `Vec`, it will not allocate space for them. *Note that in this case /// the `Vec` may not report a [`capacity`] of 0*. `Vec` will allocate if and only -/// if [`mem::size_of::`]` * capacity() > 0`. In general, `Vec`'s allocation +/// if [`mem::size_of::`]`() * capacity() > 0`. In general, `Vec`'s allocation /// details are subtle enough that it is strongly recommended that you only /// free memory allocated by a `Vec` by creating a new `Vec` and dropping it. /// @@ -823,7 +823,8 @@ impl Vec { } } - /// Removes consecutive elements in the vector that resolve to the same key. + /// Removes all but the first of consecutive elements in the vector that resolve to the same + /// key. /// /// If the vector is sorted, this removes all duplicates. /// @@ -842,11 +843,13 @@ impl Vec { self.dedup_by(|a, b| key(a) == key(b)) } - /// Removes consecutive elements in the vector according to a predicate. + /// Removes all but the first of consecutive elements in the vector satisfying a given equality + /// relation. /// /// The `same_bucket` function is passed references to two elements from the vector, and - /// returns `true` if the elements compare equal, or `false` if they do not. Only the first - /// of adjacent equal items is kept. + /// returns `true` if the elements compare equal, or `false` if they do not. The elements are + /// passed in opposite order from their order in the vector, so if `same_bucket(a, b)` returns + /// `true`, `a` is removed. /// /// If the vector is sorted, this removes all duplicates. /// diff --git a/src/liballoc_jemalloc/build.rs b/src/liballoc_jemalloc/build.rs index 23677bca9f1..085f62f4b0f 100644 --- a/src/liballoc_jemalloc/build.rs +++ b/src/liballoc_jemalloc/build.rs @@ -137,8 +137,6 @@ fn main() { cmd.arg("--enable-debug"); } - // Turn off broken quarantine (see jemalloc/jemalloc#161) - cmd.arg("--disable-fill"); cmd.arg(format!("--host={}", build_helper::gnu_target(&target))); cmd.arg(format!("--build={}", build_helper::gnu_target(&host))); diff --git a/src/libcore/benches/iter.rs b/src/libcore/benches/iter.rs index 93d38a5bc83..5b06229c21f 100644 --- a/src/libcore/benches/iter.rs +++ b/src/libcore/benches/iter.rs @@ -99,3 +99,50 @@ fn bench_zip_add(b: &mut Bencher) { add_zip(&source, &mut dst) }); } + +/// `Iterator::for_each` implemented as a plain loop. +fn for_each_loop(iter: I, mut f: F) where + I: Iterator, F: FnMut(I::Item) +{ + for item in iter { + f(item); + } +} + +/// `Iterator::for_each` implemented with `fold` for internal iteration. +/// (except when `by_ref()` effectively disables that optimization.) +fn for_each_fold(iter: I, mut f: F) where + I: Iterator, F: FnMut(I::Item) +{ + iter.fold((), move |(), item| f(item)); +} + +#[bench] +fn bench_for_each_chain_loop(b: &mut Bencher) { + b.iter(|| { + let mut acc = 0; + let iter = (0i64..1000000).chain(0..1000000).map(black_box); + for_each_loop(iter, |x| acc += x); + acc + }); +} + +#[bench] +fn bench_for_each_chain_fold(b: &mut Bencher) { + b.iter(|| { + let mut acc = 0; + let iter = (0i64..1000000).chain(0..1000000).map(black_box); + for_each_fold(iter, |x| acc += x); + acc + }); +} + +#[bench] +fn bench_for_each_chain_ref_fold(b: &mut Bencher) { + b.iter(|| { + let mut acc = 0; + let mut iter = (0i64..1000000).chain(0..1000000).map(black_box); + for_each_fold(iter.by_ref(), |x| acc += x); + acc + }); +} diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 6f35d0417f1..f133bd93c91 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -335,7 +335,6 @@ impl Ordering { /// Example usage: /// /// ``` -/// #![feature(reverse_cmp_key)] /// use std::cmp::Reverse; /// /// let mut v = vec![1, 2, 3, 4, 5, 6]; @@ -343,10 +342,10 @@ impl Ordering { /// assert_eq!(v, vec![3, 2, 1, 6, 5, 4]); /// ``` #[derive(PartialEq, Eq, Debug)] -#[unstable(feature = "reverse_cmp_key", issue = "40893")] -pub struct Reverse(pub T); +#[stable(feature = "reverse_cmp_key", since = "1.19.0")] +pub struct Reverse(#[stable(feature = "reverse_cmp_key", since = "1.19.0")] pub T); -#[unstable(feature = "reverse_cmp_key", issue = "40893")] +#[stable(feature = "reverse_cmp_key", since = "1.19.0")] impl PartialOrd for Reverse { #[inline] fn partial_cmp(&self, other: &Reverse) -> Option { @@ -363,7 +362,7 @@ impl PartialOrd for Reverse { fn gt(&self, other: &Self) -> bool { other.0 > self.0 } } -#[unstable(feature = "reverse_cmp_key", issue = "40893")] +#[stable(feature = "reverse_cmp_key", since = "1.19.0")] impl Ord for Reverse { #[inline] fn cmp(&self, other: &Reverse) -> Ordering { @@ -380,8 +379,9 @@ impl Ord for Reverse { /// /// ## Derivable /// -/// This trait can be used with `#[derive]`. When `derive`d, it will produce a lexicographic -/// ordering based on the top-to-bottom declaration order of the struct's members. +/// This trait can be used with `#[derive]`. When `derive`d on structs, it will produce a +/// lexicographic ordering based on the top-to-bottom declaration order of the struct's members. +/// When `derive`d on enums, variants are ordered by their top-to-bottom declaration order. /// /// ## How can I implement `Ord`? /// @@ -513,8 +513,9 @@ impl PartialOrd for Ordering { /// /// ## Derivable /// -/// This trait can be used with `#[derive]`. When `derive`d, it will produce a lexicographic -/// ordering based on the top-to-bottom declaration order of the struct's members. +/// This trait can be used with `#[derive]`. When `derive`d on structs, it will produce a +/// lexicographic ordering based on the top-to-bottom declaration order of the struct's members. +/// When `derive`d on enums, variants are ordered by their top-to-bottom declaration order. /// /// ## How can I implement `PartialOrd`? /// diff --git a/src/libcore/fmt/builders.rs b/src/libcore/fmt/builders.rs index 102e3c0bd7b..322df6e5b47 100644 --- a/src/libcore/fmt/builders.rs +++ b/src/libcore/fmt/builders.rs @@ -49,9 +49,37 @@ impl<'a, 'b: 'a> fmt::Write for PadAdapter<'a, 'b> { } } -/// A struct to help with `fmt::Debug` implementations. +/// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations. /// -/// Constructed by the `Formatter::debug_struct` method. +/// This is useful when you wish to output a formatted struct as a part of your +/// [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation. +/// +/// This can be constructed by the +/// [`Formatter::debug_struct`](struct.Formatter.html#method.debug_struct) +/// method. +/// +/// # Example +/// +/// ``` +/// use std::fmt; +/// +/// struct Foo { +/// bar: i32, +/// baz: String, +/// } +/// +/// impl fmt::Debug for Foo { +/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { +/// fmt.debug_struct("Foo") +/// .field("bar", &self.bar) +/// .field("baz", &self.baz) +/// .finish() +/// } +/// } +/// +/// // prints "Foo { bar: 10, baz: "Hello World" }" +/// println!("{:?}", Foo { bar: 10, baz: "Hello World".to_string() }); +/// ``` #[must_use] #[allow(missing_debug_implementations)] #[stable(feature = "debug_builders", since = "1.2.0")] @@ -116,9 +144,34 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { } } -/// A struct to help with `fmt::Debug` implementations. +/// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations. /// -/// Constructed by the `Formatter::debug_tuple` method. +/// This is useful when you wish to output a formatted tuple as a part of your +/// [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation. +/// +/// This can be constructed by the +/// [`Formatter::debug_tuple`](struct.Formatter.html#method.debug_tuple) +/// method. +/// +/// # Example +/// +/// ``` +/// use std::fmt; +/// +/// struct Foo(i32, String); +/// +/// impl fmt::Debug for Foo { +/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { +/// fmt.debug_tuple("Foo") +/// .field(&self.0) +/// .field(&self.1) +/// .finish() +/// } +/// } +/// +/// // prints "Foo(10, "Hello World")" +/// println!("{:?}", Foo(10, "Hello World".to_string())); +/// ``` #[must_use] #[allow(missing_debug_implementations)] #[stable(feature = "debug_builders", since = "1.2.0")] @@ -228,9 +281,31 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> { } } -/// A struct to help with `fmt::Debug` implementations. +/// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations. /// -/// Constructed by the `Formatter::debug_set` method. +/// This is useful when you wish to output a formatted set of items as a part +/// of your [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation. +/// +/// This can be constructed by the +/// [`Formatter::debug_set`](struct.Formatter.html#method.debug_set) +/// method. +/// +/// # Example +/// +/// ``` +/// use std::fmt; +/// +/// struct Foo(Vec); +/// +/// impl fmt::Debug for Foo { +/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { +/// fmt.debug_set().entries(self.0.iter()).finish() +/// } +/// } +/// +/// // prints "{10, 11}" +/// println!("{:?}", Foo(vec![10, 11])); +/// ``` #[must_use] #[allow(missing_debug_implementations)] #[stable(feature = "debug_builders", since = "1.2.0")] @@ -277,9 +352,31 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> { } } -/// A struct to help with `fmt::Debug` implementations. +/// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations. /// -/// Constructed by the `Formatter::debug_list` method. +/// This is useful when you wish to output a formatted list of items as a part +/// of your [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation. +/// +/// This can be constructed by the +/// [`Formatter::debug_list`](struct.Formatter.html#method.debug_list) +/// method. +/// +/// # Example +/// +/// ``` +/// use std::fmt; +/// +/// struct Foo(Vec); +/// +/// impl fmt::Debug for Foo { +/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { +/// fmt.debug_list().entries(self.0.iter()).finish() +/// } +/// } +/// +/// // prints "[10, 11]" +/// println!("{:?}", Foo(vec![10, 11])); +/// ``` #[must_use] #[allow(missing_debug_implementations)] #[stable(feature = "debug_builders", since = "1.2.0")] @@ -326,9 +423,31 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> { } } -/// A struct to help with `fmt::Debug` implementations. +/// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations. /// -/// Constructed by the `Formatter::debug_map` method. +/// This is useful when you wish to output a formatted map as a part of your +/// [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation. +/// +/// This can be constructed by the +/// [`Formatter::debug_map`](struct.Formatter.html#method.debug_map) +/// method. +/// +/// # Example +/// +/// ``` +/// use std::fmt; +/// +/// struct Foo(Vec<(String, i32)>); +/// +/// impl fmt::Debug for Foo { +/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { +/// fmt.debug_map().entries(self.0.iter().map(|&(ref k, ref v)| (k, v))).finish() +/// } +/// } +/// +/// // prints "{"A": 10, "B": 11}" +/// println!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])); +/// ``` #[must_use] #[allow(missing_debug_implementations)] #[stable(feature = "debug_builders", since = "1.2.0")] diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 8c3d3ce7d88..bcc6d53c81d 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -897,14 +897,11 @@ pub trait UpperExp { fn fmt(&self, f: &mut Formatter) -> Result; } -/// The `write` function takes an output stream, a precompiled format string, -/// and a list of arguments. The arguments will be formatted according to the -/// specified format string into the output stream provided. +/// The `write` function takes an output stream, and an `Arguments` struct +/// that can be precompiled with the `format_args!` macro. /// -/// # Arguments -/// -/// * output - the buffer to write output to -/// * args - the precompiled arguments generated by `format_args!` +/// The arguments will be formatted according to the specified format string +/// into the output stream provided. /// /// # Examples /// diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 30d09e5453b..d9887094fef 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -482,6 +482,53 @@ pub trait Iterator { Map{iter: self, f: f} } + /// Calls a closure on each element of an iterator. + /// + /// This is equivalent to using a [`for`] loop on the iterator, although + /// `break` and `continue` are not possible from a closure. It's generally + /// more idiomatic to use a `for` loop, but `for_each` may be more legible + /// when processing items at the end of longer iterator chains. In some + /// cases `for_each` may also be faster than a loop, because it will use + /// internal iteration on adaptors like `Chain`. + /// + /// [`for`]: ../../book/first-edition/loops.html#for + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(iterator_for_each)] + /// + /// use std::sync::mpsc::channel; + /// + /// let (tx, rx) = channel(); + /// (0..5).map(|x| x * 2 + 1) + /// .for_each(move |x| tx.send(x).unwrap()); + /// + /// let v: Vec<_> = rx.iter().collect(); + /// assert_eq!(v, vec![1, 3, 5, 7, 9]); + /// ``` + /// + /// For such a small example, a `for` loop may be cleaner, but `for_each` + /// might be preferable to keep a functional style with longer iterators: + /// + /// ``` + /// #![feature(iterator_for_each)] + /// + /// (0..5).flat_map(|x| x * 100 .. x * 110) + /// .enumerate() + /// .filter(|&(i, x)| (i + x) % 3 == 0) + /// .for_each(|(i, x)| println!("{}:{}", i, x)); + /// ``` + #[inline] + #[unstable(feature = "iterator_for_each", issue = "42986")] + fn for_each(self, mut f: F) where + Self: Sized, F: FnMut(Self::Item), + { + self.fold((), move |(), item| f(item)); + } + /// Creates an iterator which uses a closure to determine if an element /// should be yielded. /// diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index d6a9be4437d..decd718d65e 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -314,12 +314,6 @@ pub use self::iterator::Iterator; reason = "likely to be replaced by finer-grained traits", issue = "42168")] pub use self::range::Step; -#[unstable(feature = "step_by", reason = "recent addition", - issue = "27741")] -#[rustc_deprecated(since = "1.19.0", - reason = "replaced by `iter::StepBy`")] -#[allow(deprecated)] -pub use self::range::StepBy as DeprecatedStepBy; #[stable(feature = "rust1", since = "1.0.0")] pub use self::sources::{Repeat, repeat}; diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 9aea4477fb7..1dad8157948 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -244,219 +244,6 @@ step_impl_signed!(i64); step_impl_no_between!(u64 i64); step_impl_no_between!(u128 i128); -/// An adapter for stepping range iterators by a custom amount. -/// -/// The resulting iterator handles overflow by stopping. The `A` -/// parameter is the type being iterated over, while `R` is the range -/// type (usually one of `std::ops::{Range, RangeFrom, RangeInclusive}`. -#[derive(Clone, Debug)] -#[unstable(feature = "step_by", reason = "recent addition", - issue = "27741")] -#[rustc_deprecated(since = "1.19.0", - reason = "replaced by `iter::StepBy`")] -#[allow(deprecated)] -pub struct StepBy { - step_by: A, - range: R, -} - -impl ops::RangeFrom { - /// Creates an iterator starting at the same point, but stepping by - /// the given amount at each iteration. - /// - /// # Examples - /// - /// ``` - /// #![feature(step_by)] - /// fn main() { - /// let result: Vec<_> = (0..).step_by(2).take(5).collect(); - /// assert_eq!(result, vec![0, 2, 4, 6, 8]); - /// } - /// ``` - #[unstable(feature = "step_by", reason = "recent addition", - issue = "27741")] - #[rustc_deprecated(since = "1.19.0", - reason = "replaced by `Iterator::step_by`")] - #[allow(deprecated)] - pub fn step_by(self, by: A) -> StepBy { - StepBy { - step_by: by, - range: self - } - } -} - -impl ops::Range { - /// Creates an iterator with the same range, but stepping by the - /// given amount at each iteration. - /// - /// The resulting iterator handles overflow by stopping. - /// - /// # Examples - /// - /// ``` - /// #![feature(step_by)] - /// fn main() { - /// let result: Vec<_> = (0..10).step_by(2).collect(); - /// assert_eq!(result, vec![0, 2, 4, 6, 8]); - /// } - /// ``` - #[unstable(feature = "step_by", reason = "recent addition", - issue = "27741")] - #[rustc_deprecated(since = "1.19.0", - reason = "replaced by `Iterator::step_by`")] - #[allow(deprecated)] - pub fn step_by(self, by: A) -> StepBy { - StepBy { - step_by: by, - range: self - } - } -} - -impl ops::RangeInclusive { - /// Creates an iterator with the same range, but stepping by the - /// given amount at each iteration. - /// - /// The resulting iterator handles overflow by stopping. - /// - /// # Examples - /// - /// ``` - /// #![feature(step_by, inclusive_range_syntax)] - /// - /// let result: Vec<_> = (0...10).step_by(2).collect(); - /// assert_eq!(result, vec![0, 2, 4, 6, 8, 10]); - /// ``` - #[unstable(feature = "step_by", reason = "recent addition", - issue = "27741")] - #[rustc_deprecated(since = "1.19.0", - reason = "replaced by `Iterator::step_by`")] - #[allow(deprecated)] - pub fn step_by(self, by: A) -> StepBy { - StepBy { - step_by: by, - range: self - } - } -} - -#[unstable(feature = "step_by", reason = "recent addition", - issue = "27741")] -#[allow(deprecated)] -impl Iterator for StepBy> where - A: Clone, - for<'a> &'a A: Add<&'a A, Output = A> -{ - type Item = A; - - #[inline] - fn next(&mut self) -> Option { - let mut n = &self.range.start + &self.step_by; - mem::swap(&mut n, &mut self.range.start); - Some(n) - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - (usize::MAX, None) // Too bad we can't specify an infinite lower bound - } -} - -#[unstable(feature = "fused", issue = "35602")] -#[allow(deprecated)] -impl FusedIterator for StepBy> - where A: Clone, for<'a> &'a A: Add<&'a A, Output = A> {} - -#[unstable(feature = "step_by", reason = "recent addition", - issue = "27741")] -#[allow(deprecated)] -impl Iterator for StepBy> { - type Item = A; - - #[inline] - fn next(&mut self) -> Option { - let rev = self.step_by.is_negative(); - if (rev && self.range.start > self.range.end) || - (!rev && self.range.start < self.range.end) - { - match self.range.start.step(&self.step_by) { - Some(mut n) => { - mem::swap(&mut self.range.start, &mut n); - Some(n) - }, - None => { - let mut n = self.range.end.clone(); - mem::swap(&mut self.range.start, &mut n); - Some(n) - } - } - } else { - None - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - match Step::steps_between(&self.range.start, - &self.range.end, - &self.step_by) { - Some(hint) => (hint, Some(hint)), - None => (0, None) - } - } -} - -#[unstable(feature = "fused", issue = "35602")] -#[allow(deprecated)] -impl FusedIterator for StepBy> {} - -#[unstable(feature = "inclusive_range", - reason = "recently added, follows RFC", - issue = "28237")] -#[allow(deprecated)] -impl Iterator for StepBy> { - type Item = A; - - #[inline] - fn next(&mut self) -> Option { - let rev = self.step_by.is_negative(); - - if (rev && self.range.start >= self.range.end) || - (!rev && self.range.start <= self.range.end) - { - match self.range.start.step(&self.step_by) { - Some(n) => { - Some(mem::replace(&mut self.range.start, n)) - }, - None => { - let last = self.range.start.replace_one(); - self.range.end.replace_zero(); - self.step_by.replace_one(); - Some(last) - }, - } - } - else { - None - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - match Step::steps_between(&self.range.start, - &self.range.end, - &self.step_by) { - Some(hint) => (hint.saturating_add(1), hint.checked_add(1)), - None => (0, None) - } - } -} - -#[unstable(feature = "fused", issue = "35602")] -#[allow(deprecated)] -impl FusedIterator for StepBy> {} - macro_rules! range_exact_iter_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index b6ab1ecaf4e..97aaaffe8bc 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -36,12 +36,12 @@ //! These functions are often provided by the system libc, but can also be //! provided by the [rlibc crate](https://crates.io/crates/rlibc). //! -//! * `rust_begin_panic` - This function takes three arguments, a -//! `fmt::Arguments`, a `&'static str`, and a `u32`. These three arguments +//! * `rust_begin_panic` - This function takes four arguments, a +//! `fmt::Arguments`, a `&'static str`, and two `u32`'s. These four arguments //! dictate the panic message, the file at which panic was invoked, and the -//! line. It is up to consumers of this core library to define this panic -//! function; it is only required to never return. This requires a `lang` -//! attribute named `panic_fmt`. +//! line and column inside the file. It is up to consumers of this core +//! library to define this panic function; it is only required to never +//! return. This requires a `lang` attribute named `panic_fmt`. //! //! * `rust_eh_personality` - is used by the failure mechanisms of the //! compiler. This is often mapped to GCC's personality function, but crates diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 5bb6a772aeb..70820dce5f9 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -17,16 +17,18 @@ macro_rules! panic { panic!("explicit panic") ); ($msg:expr) => ({ - static _MSG_FILE_LINE: (&'static str, &'static str, u32) = ($msg, file!(), line!()); - $crate::panicking::panic(&_MSG_FILE_LINE) + static _MSG_FILE_LINE_COL: (&'static str, &'static str, u32, u32) = + ($msg, file!(), line!(), column!()); + $crate::panicking::panic(&_MSG_FILE_LINE_COL) }); ($fmt:expr, $($arg:tt)*) => ({ // The leading _'s are to avoid dead code warnings if this is // used inside a dead function. Just `#[allow(dead_code)]` is // insufficient, since the user may have // `#[forbid(dead_code)]` and which cannot be overridden. - static _FILE_LINE: (&'static str, u32) = (file!(), line!()); - $crate::panicking::panic_fmt(format_args!($fmt, $($arg)*), &_FILE_LINE) + static _MSG_FILE_LINE_COL: (&'static str, u32, u32) = + (file!(), line!(), column!()); + $crate::panicking::panic_fmt(format_args!($fmt, $($arg)*), &_MSG_FILE_LINE_COL) }); } diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index bba42752f50..6c1e8e8960f 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -506,59 +506,7 @@ pub unsafe fn uninitialized() -> T { #[stable(feature = "rust1", since = "1.0.0")] pub fn swap(x: &mut T, y: &mut T) { unsafe { - // The approach here is to utilize simd to swap x & y efficiently. Testing reveals - // that swapping either 32 bytes or 64 bytes at a time is most efficient for intel - // Haswell E processors. LLVM is more able to optimize if we give a struct a - // #[repr(simd)], even if we don't actually use this struct directly. - // - // FIXME repr(simd) broken on emscripten and redox - #[cfg_attr(not(any(target_os = "emscripten", target_os = "redox")), repr(simd))] - struct Block(u64, u64, u64, u64); - struct UnalignedBlock(u64, u64, u64, u64); - - let block_size = size_of::(); - - // Get raw pointers to the bytes of x & y for easier manipulation - let x = x as *mut T as *mut u8; - let y = y as *mut T as *mut u8; - - // Loop through x & y, copying them `Block` at a time - // The optimizer should unroll the loop fully for most types - // N.B. We can't use a for loop as the `range` impl calls `mem::swap` recursively - let len = size_of::(); - let mut i = 0; - while i + block_size <= len { - // Create some uninitialized memory as scratch space - // Declaring `t` here avoids aligning the stack when this loop is unused - let mut t: Block = uninitialized(); - let t = &mut t as *mut _ as *mut u8; - let x = x.offset(i as isize); - let y = y.offset(i as isize); - - // Swap a block of bytes of x & y, using t as a temporary buffer - // This should be optimized into efficient SIMD operations where available - ptr::copy_nonoverlapping(x, t, block_size); - ptr::copy_nonoverlapping(y, x, block_size); - ptr::copy_nonoverlapping(t, y, block_size); - i += block_size; - } - - - if i < len { - // Swap any remaining bytes, using aligned types to copy - // where appropriate (this information is lost by conversion - // to *mut u8, so restore it manually here) - let mut t: UnalignedBlock = uninitialized(); - let rem = len - i; - - let t = &mut t as *mut _ as *mut u8; - let x = x.offset(i as isize); - let y = y.offset(i as isize); - - ptr::copy_nonoverlapping(x, t, rem); - ptr::copy_nonoverlapping(y, x, rem); - ptr::copy_nonoverlapping(t, y, rem); - } + ptr::swap_nonoverlapping(x, y, 1); } } diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index cb28035682d..ebc30dc8b61 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -205,18 +205,25 @@ impl Float for f32 { } } - /// Returns `true` if `self` is positive, including `+0.0` and - /// `Float::infinity()`. + /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with + /// positive sign bit and positive infinity. #[inline] fn is_sign_positive(self) -> bool { - self > 0.0 || (1.0 / self) == INFINITY + !self.is_sign_negative() } - /// Returns `true` if `self` is negative, including `-0.0` and - /// `Float::neg_infinity()`. + /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with + /// negative sign bit and negative infinity. #[inline] fn is_sign_negative(self) -> bool { - self < 0.0 || (1.0 / self) == NEG_INFINITY + // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus + // applies to zeros and NaNs as well. + #[repr(C)] + union F32Bytes { + f: f32, + b: u32 + } + unsafe { F32Bytes { f: self }.b & 0x8000_0000 != 0 } } /// Returns the reciprocal (multiplicative inverse) of the number. diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index ac6b1e67cd2..1a1fe4d86e0 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -205,18 +205,23 @@ impl Float for f64 { } } - /// Returns `true` if `self` is positive, including `+0.0` and - /// `Float::infinity()`. + /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with + /// positive sign bit and positive infinity. #[inline] fn is_sign_positive(self) -> bool { - self > 0.0 || (1.0 / self) == INFINITY + !self.is_sign_negative() } - /// Returns `true` if `self` is negative, including `-0.0` and - /// `Float::neg_infinity()`. + /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with + /// negative sign bit and negative infinity. #[inline] fn is_sign_negative(self) -> bool { - self < 0.0 || (1.0 / self) == NEG_INFINITY + #[repr(C)] + union F64Bytes { + f: f64, + b: u64 + } + unsafe { F64Bytes { f: self }.b & 0x8000_0000_0000_0000 != 0 } } /// Returns the reciprocal (multiplicative inverse) of the number. diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs index 60b7669f3b2..f5a7e78d0fa 100644 --- a/src/libcore/panicking.rs +++ b/src/libcore/panicking.rs @@ -17,7 +17,7 @@ //! //! ``` //! # use std::fmt; -//! fn panic_impl(fmt: fmt::Arguments, file_line: &(&'static str, u32)) -> ! +//! fn panic_impl(fmt: fmt::Arguments, file_line_col: &(&'static str, u32, u32)) -> ! //! # { loop {} } //! ``` //! @@ -39,34 +39,55 @@ use fmt; #[cold] #[inline(never)] // this is the slow path, always -#[lang = "panic"] -pub fn panic(expr_file_line: &(&'static str, &'static str, u32)) -> ! { +#[cfg_attr(not(stage0), lang = "panic")] +pub fn panic(expr_file_line_col: &(&'static str, &'static str, u32, u32)) -> ! { // Use Arguments::new_v1 instead of format_args!("{}", expr) to potentially // reduce size overhead. The format_args! macro uses str's Display trait to // write expr, which calls Formatter::pad, which must accommodate string // truncation and padding (even though none is used here). Using // Arguments::new_v1 may allow the compiler to omit Formatter::pad from the // output binary, saving up to a few kilobytes. + let (expr, file, line, col) = *expr_file_line_col; + panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), &(file, line, col)) +} + +// FIXME: remove when SNAP +#[cold] #[inline(never)] +#[cfg(stage0)] +#[lang = "panic"] +pub fn panic_old(expr_file_line: &(&'static str, &'static str, u32)) -> ! { let (expr, file, line) = *expr_file_line; - panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), &(file, line)) + let expr_file_line_col = (expr, file, line, 0); + panic(&expr_file_line_col) } #[cold] #[inline(never)] -#[lang = "panic_bounds_check"] -fn panic_bounds_check(file_line: &(&'static str, u32), +#[cfg_attr(not(stage0), lang = "panic_bounds_check")] +fn panic_bounds_check(file_line_col: &(&'static str, u32, u32), index: usize, len: usize) -> ! { panic_fmt(format_args!("index out of bounds: the len is {} but the index is {}", - len, index), file_line) + len, index), file_line_col) +} + +// FIXME: remove when SNAP +#[cold] #[inline(never)] +#[cfg(stage0)] +#[lang = "panic_bounds_check"] +fn panic_bounds_check_old(file_line: &(&'static str, u32), + index: usize, len: usize) -> ! { + let (file, line) = *file_line; + panic_fmt(format_args!("index out of bounds: the len is {} but the index is {}", + len, index), &(file, line, 0)) } #[cold] #[inline(never)] -pub fn panic_fmt(fmt: fmt::Arguments, file_line: &(&'static str, u32)) -> ! { +pub fn panic_fmt(fmt: fmt::Arguments, file_line_col: &(&'static str, u32, u32)) -> ! { #[allow(improper_ctypes)] extern { #[lang = "panic_fmt"] #[unwind] - fn panic_impl(fmt: fmt::Arguments, file: &'static str, line: u32) -> !; + fn panic_impl(fmt: fmt::Arguments, file: &'static str, line: u32, col: u32) -> !; } - let (file, line) = *file_line; - unsafe { panic_impl(fmt, file, line) } + let (file, line, col) = *file_line_col; + unsafe { panic_impl(fmt, file, line, col) } } diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 54ae9e0d628..92470299366 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -117,6 +117,90 @@ pub unsafe fn swap(x: *mut T, y: *mut T) { mem::forget(tmp); } +/// Swaps a sequence of values at two mutable locations of the same type. +/// +/// # Safety +/// +/// The two arguments must each point to the beginning of `count` locations +/// of valid memory, and the two memory ranges must not overlap. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// #![feature(swap_nonoverlapping)] +/// +/// use std::ptr; +/// +/// let mut x = [1, 2, 3, 4]; +/// let mut y = [7, 8, 9]; +/// +/// unsafe { +/// ptr::swap_nonoverlapping(x.as_mut_ptr(), y.as_mut_ptr(), 2); +/// } +/// +/// assert_eq!(x, [7, 8, 3, 4]); +/// assert_eq!(y, [1, 2, 9]); +/// ``` +#[inline] +#[unstable(feature = "swap_nonoverlapping", issue = "42818")] +pub unsafe fn swap_nonoverlapping(x: *mut T, y: *mut T, count: usize) { + let x = x as *mut u8; + let y = y as *mut u8; + let len = mem::size_of::() * count; + swap_nonoverlapping_bytes(x, y, len) +} + +#[inline] +unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) { + // The approach here is to utilize simd to swap x & y efficiently. Testing reveals + // that swapping either 32 bytes or 64 bytes at a time is most efficient for intel + // Haswell E processors. LLVM is more able to optimize if we give a struct a + // #[repr(simd)], even if we don't actually use this struct directly. + // + // FIXME repr(simd) broken on emscripten and redox + #[cfg_attr(not(any(target_os = "emscripten", target_os = "redox")), repr(simd))] + struct Block(u64, u64, u64, u64); + struct UnalignedBlock(u64, u64, u64, u64); + + let block_size = mem::size_of::(); + + // Loop through x & y, copying them `Block` at a time + // The optimizer should unroll the loop fully for most types + // N.B. We can't use a for loop as the `range` impl calls `mem::swap` recursively + let mut i = 0; + while i + block_size <= len { + // Create some uninitialized memory as scratch space + // Declaring `t` here avoids aligning the stack when this loop is unused + let mut t: Block = mem::uninitialized(); + let t = &mut t as *mut _ as *mut u8; + let x = x.offset(i as isize); + let y = y.offset(i as isize); + + // Swap a block of bytes of x & y, using t as a temporary buffer + // This should be optimized into efficient SIMD operations where available + copy_nonoverlapping(x, t, block_size); + copy_nonoverlapping(y, x, block_size); + copy_nonoverlapping(t, y, block_size); + i += block_size; + } + + if i < len { + // Swap any remaining bytes + let mut t: UnalignedBlock = mem::uninitialized(); + let rem = len - i; + + let t = &mut t as *mut _ as *mut u8; + let x = x.offset(i as isize); + let y = y.offset(i as isize); + + copy_nonoverlapping(x, t, rem); + copy_nonoverlapping(y, x, rem); + copy_nonoverlapping(t, y, rem); + } +} + /// Replaces the value at `dest` with `src`, returning the old /// value, without dropping either. /// diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index ce5da9ec2d5..62c7e7aa1cc 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -212,15 +212,15 @@ pub trait SliceExt { #[stable(feature = "copy_from_slice", since = "1.9.0")] fn copy_from_slice(&mut self, src: &[Self::Item]) where Self::Item: Copy; - #[unstable(feature = "sort_unstable", issue = "40585")] + #[stable(feature = "sort_unstable", since = "1.20.0")] fn sort_unstable(&mut self) where Self::Item: Ord; - #[unstable(feature = "sort_unstable", issue = "40585")] + #[stable(feature = "sort_unstable", since = "1.20.0")] fn sort_unstable_by(&mut self, compare: F) where F: FnMut(&Self::Item, &Self::Item) -> Ordering; - #[unstable(feature = "sort_unstable", issue = "40585")] + #[stable(feature = "sort_unstable", since = "1.20.0")] fn sort_unstable_by_key(&mut self, f: F) where F: FnMut(&Self::Item) -> B, B: Ord; diff --git a/src/libcore/slice/rotate.rs b/src/libcore/slice/rotate.rs index 3b9ae5652c5..e4a4e33c172 100644 --- a/src/libcore/slice/rotate.rs +++ b/src/libcore/slice/rotate.rs @@ -76,7 +76,7 @@ pub unsafe fn ptr_rotate(mut left: usize, mid: *mut T, mut right: usize) { break; } - ptr_swap_n( + ptr::swap_nonoverlapping( mid.offset(-(left as isize)), mid.offset((right-delta) as isize), delta); @@ -103,10 +103,3 @@ pub unsafe fn ptr_rotate(mut left: usize, mid: *mut T, mut right: usize) { ptr::copy_nonoverlapping(buf, mid.offset(-(left as isize)), right); } } - -unsafe fn ptr_swap_n(a: *mut T, b: *mut T, n: usize) { - for i in 0..n { - // These are nonoverlapping, so use mem::swap instead of ptr::swap - mem::swap(&mut *a.offset(i as isize), &mut *b.offset(i as isize)); - } -} diff --git a/src/libcore/slice/sort.rs b/src/libcore/slice/sort.rs index 6f9f2915dfe..518d56095d6 100644 --- a/src/libcore/slice/sort.rs +++ b/src/libcore/slice/sort.rs @@ -351,7 +351,7 @@ fn partition_in_blocks(v: &mut [T], pivot: &T, is_less: &mut F) -> usize if start_l < end_l { // The left block remains. - // Move it's remaining out-of-order elements to the far right. + // Move its remaining out-of-order elements to the far right. debug_assert_eq!(width(l, r), block_l); while start_l < end_l { unsafe { @@ -363,7 +363,7 @@ fn partition_in_blocks(v: &mut [T], pivot: &T, is_less: &mut F) -> usize width(v.as_mut_ptr(), r) } else if start_r < end_r { // The right block remains. - // Move it's remaining out-of-order elements to the far left. + // Move its remaining out-of-order elements to the far left. debug_assert_eq!(width(l, r), block_r); while start_r < end_r { unsafe { diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 4f9951cd153..14f0260f571 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -12,15 +12,6 @@ use core::iter::*; use core::{i8, i16, isize}; use core::usize; -// FIXME #27741: This is here to simplify calling Iterator::step_by. Remove -// once Range::step_by is completely gone (not just deprecated). -trait IterEx: Sized { - fn iter_step_by(self, n: usize) -> StepBy; -} -impl IterEx for I { - fn iter_step_by(self, n: usize) -> StepBy { self.step_by(n) } -} - #[test] fn test_lt() { let empty: [isize; 0] = []; @@ -76,7 +67,7 @@ fn test_multi_iter() { #[test] fn test_counter_from_iter() { - let it = (0..).iter_step_by(5).take(10); + let it = (0..).step_by(5).take(10); let xs: Vec = FromIterator::from_iter(it); assert_eq!(xs, [0, 5, 10, 15, 20, 25, 30, 35, 40, 45]); } @@ -94,7 +85,7 @@ fn test_iterator_chain() { } assert_eq!(i, expected.len()); - let ys = (30..).iter_step_by(10).take(4); + let ys = (30..).step_by(10).take(4); let it = xs.iter().cloned().chain(ys); let mut i = 0; for x in it { @@ -156,13 +147,13 @@ fn test_iterator_chain_find() { #[test] fn test_iterator_step_by() { // Identity - let mut it = (0..).iter_step_by(1).take(3); + let mut it = (0..).step_by(1).take(3); assert_eq!(it.next(), Some(0)); assert_eq!(it.next(), Some(1)); assert_eq!(it.next(), Some(2)); assert_eq!(it.next(), None); - let mut it = (0..).iter_step_by(3).take(4); + let mut it = (0..).step_by(3).take(4); assert_eq!(it.next(), Some(0)); assert_eq!(it.next(), Some(3)); assert_eq!(it.next(), Some(6)); @@ -173,7 +164,7 @@ fn test_iterator_step_by() { #[test] #[should_panic] fn test_iterator_step_by_zero() { - let mut it = (0..).iter_step_by(0); + let mut it = (0..).step_by(0); it.next(); } @@ -252,7 +243,7 @@ fn test_iterator_step_by_size_hint() { #[test] fn test_filter_map() { - let it = (0..).iter_step_by(1).take(10) + let it = (0..).step_by(1).take(10) .filter_map(|x| if x % 2 == 0 { Some(x*x) } else { None }); assert_eq!(it.collect::>(), [0*0, 2*2, 4*4, 6*6, 8*8]); } @@ -654,7 +645,7 @@ fn test_iterator_scan() { fn test_iterator_flat_map() { let xs = [0, 3, 6]; let ys = [0, 1, 2, 3, 4, 5, 6, 7, 8]; - let it = xs.iter().flat_map(|&x| (x..).iter_step_by(1).take(3)); + let it = xs.iter().flat_map(|&x| (x..).step_by(1).take(3)); let mut i = 0; for x in it { assert_eq!(x, ys[i]); @@ -680,13 +671,13 @@ fn test_inspect() { #[test] fn test_cycle() { let cycle_len = 3; - let it = (0..).iter_step_by(1).take(cycle_len).cycle(); + let it = (0..).step_by(1).take(cycle_len).cycle(); assert_eq!(it.size_hint(), (usize::MAX, None)); for (i, x) in it.take(100).enumerate() { assert_eq!(i % cycle_len, x); } - let mut it = (0..).iter_step_by(1).take(0).cycle(); + let mut it = (0..).step_by(1).take(0).cycle(); assert_eq!(it.size_hint(), (0, Some(0))); assert_eq!(it.next(), None); } @@ -765,7 +756,7 @@ fn test_iterator_min() { #[test] fn test_iterator_size_hint() { - let c = (0..).iter_step_by(1); + let c = (0..).step_by(1); let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; let v2 = &[10, 11, 12]; let vi = v.iter(); @@ -1090,8 +1081,8 @@ fn test_range_step() { #![allow(deprecated)] assert_eq!((0..20).step_by(5).collect::>(), [0, 5, 10, 15]); - assert_eq!((20..0).step_by(-5).collect::>(), [20, 15, 10, 5]); - assert_eq!((20..0).step_by(-6).collect::>(), [20, 14, 8, 2]); + assert_eq!((1..21).rev().step_by(5).collect::>(), [20, 15, 10, 5]); + assert_eq!((1..21).rev().step_by(6).collect::>(), [20, 14, 8, 2]); assert_eq!((200..255).step_by(50).collect::>(), [200, 250]); assert_eq!((200..-5).step_by(1).collect::>(), []); assert_eq!((200..200).step_by(1).collect::>(), []); @@ -1099,13 +1090,12 @@ fn test_range_step() { assert_eq!((0..20).step_by(1).size_hint(), (20, Some(20))); assert_eq!((0..20).step_by(21).size_hint(), (1, Some(1))); assert_eq!((0..20).step_by(5).size_hint(), (4, Some(4))); - assert_eq!((20..0).step_by(-5).size_hint(), (4, Some(4))); - assert_eq!((20..0).step_by(-6).size_hint(), (4, Some(4))); + assert_eq!((1..21).rev().step_by(5).size_hint(), (4, Some(4))); + assert_eq!((1..21).rev().step_by(6).size_hint(), (4, Some(4))); assert_eq!((20..-5).step_by(1).size_hint(), (0, Some(0))); assert_eq!((20..20).step_by(1).size_hint(), (0, Some(0))); - assert_eq!((0..1).step_by(0).size_hint(), (0, None)); - assert_eq!((i8::MAX..i8::MIN).step_by(i8::MIN).size_hint(), (2, Some(2))); - assert_eq!((i16::MIN..i16::MAX).step_by(i16::MAX).size_hint(), (3, Some(3))); + assert_eq!((i8::MIN..i8::MAX).step_by(-(i8::MIN as i32) as usize).size_hint(), (2, Some(2))); + assert_eq!((i16::MIN..i16::MAX).step_by(i16::MAX as usize).size_hint(), (3, Some(3))); assert_eq!((isize::MIN..isize::MAX).step_by(1).size_hint(), (usize::MAX, Some(usize::MAX))); } diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 337f8aa31dc..8d3e367d237 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -34,9 +34,7 @@ #![feature(slice_patterns)] #![feature(slice_rotate)] #![feature(sort_internals)] -#![feature(sort_unstable)] #![feature(specialization)] -#![feature(step_by)] #![feature(step_trait)] #![feature(test)] #![feature(trusted_len)] diff --git a/src/librand/lib.rs b/src/librand/lib.rs index ca05db15ffe..5e56b0d8ab1 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -31,7 +31,7 @@ issue = "27703")] #![feature(core_intrinsics)] #![feature(staged_api)] -#![feature(step_by)] +#![feature(iterator_step_by)] #![feature(custom_attribute)] #![feature(specialization)] #![allow(unused_attributes)] diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 5e36bd8ec27..035640b9710 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -1946,6 +1946,44 @@ Maybe you just misspelled the lint name or the lint doesn't exist anymore. Either way, try to update/remove it in order to fix the error. "##, +E0621: r##" +This error code indicates a mismatch between the function signature (i.e., +the parameter types and the return type) and the function body. Most of +the time, this indicates that the function signature needs to be changed to +match the body, but it may be that the body needs to be changed to match +the signature. + +Specifically, one or more of the parameters contain borrowed data that +needs to have a named lifetime in order for the body to type-check. Most of +the time, this is because the borrowed data is being returned from the +function, as in this example: + +```compile_fail,E0621 +fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { // explicit lifetime required + // in the type of `y` + if x > y { x } else { y } +} +``` + +Here, the function is returning data borrowed from either x or y, but the +'a annotation indicates that it is returning data only from x. We can make +the signature match the body by changing the type of y to &'a i32, like so: + +``` +fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { + if x > y { x } else { y } +} +``` + +Alternatively, you could change the body not to return data from y: + +``` +fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { + x +} +``` +"##, + } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 62bedcdfcbe..873d39ec9e9 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -2170,12 +2170,12 @@ impl<'a> LoweringContext<'a> { // let result = match ::std::iter::IntoIterator::into_iter() { // mut iter => { // [opt_ident]: loop { - // let mut _next; + // let mut __next; // match ::std::iter::Iterator::next(&mut iter) { - // ::std::option::Option::Some(val) => _next = val, + // ::std::option::Option::Some(val) => __next = val, // ::std::option::Option::None => break // }; - // let = _next; + // let = __next; // StmtExpr(); // } // } @@ -2188,7 +2188,7 @@ impl<'a> LoweringContext<'a> { let iter = self.str_to_ident("iter"); - let next_ident = self.str_to_ident("_next"); + let next_ident = self.str_to_ident("__next"); let next_pat = self.pat_ident_binding_mode(e.span, next_ident, hir::BindByValue(hir::MutMutable)); @@ -2237,13 +2237,13 @@ impl<'a> LoweringContext<'a> { let next_expr = P(self.expr_ident(e.span, next_ident, next_pat.id)); - // `let mut _next` + // `let mut __next` let next_let = self.stmt_let_pat(e.span, None, next_pat, hir::LocalSource::ForLoopDesugar); - // `let = _next` + // `let = __next` let pat = self.lower_pat(pat); let pat_let = self.stmt_let_pat(e.span, Some(next_expr), diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index a1875cd46a0..02a36a372d9 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -594,8 +594,12 @@ impl<'hir> Map<'hir> { /// last good node id we found. Note that reaching the crate root (id == 0), /// is not an error, since items in the crate module have the crate root as /// parent. - fn walk_parent_nodes(&self, start_id: NodeId, found: F) -> Result - where F: Fn(&Node<'hir>) -> bool + fn walk_parent_nodes(&self, + start_id: NodeId, + found: F, + bail_early: F2) + -> Result + where F: Fn(&Node<'hir>) -> bool, F2: Fn(&Node<'hir>) -> bool { let mut id = start_id; loop { @@ -616,6 +620,8 @@ impl<'hir> Map<'hir> { Some(ref node) => { if found(node) { return Ok(parent_node); + } else if bail_early(node) { + return Err(parent_node); } } None => { @@ -626,6 +632,56 @@ impl<'hir> Map<'hir> { } } + /// Retrieve the NodeId for `id`'s enclosing method, unless there's a + /// `while` or `loop` before reacing it, as block tail returns are not + /// available in them. + /// + /// ``` + /// fn foo(x: usize) -> bool { + /// if x == 1 { + /// true // `get_return_block` gets passed the `id` corresponding + /// } else { // to this, it will return `foo`'s `NodeId`. + /// false + /// } + /// } + /// ``` + /// + /// ``` + /// fn foo(x: usize) -> bool { + /// loop { + /// true // `get_return_block` gets passed the `id` corresponding + /// } // to this, it will return `None`. + /// false + /// } + /// ``` + pub fn get_return_block(&self, id: NodeId) -> Option { + let match_fn = |node: &Node| { + match *node { + NodeItem(_) | + NodeForeignItem(_) | + NodeTraitItem(_) | + NodeImplItem(_) => true, + _ => false, + } + }; + let match_non_returning_block = |node: &Node| { + match *node { + NodeExpr(ref expr) => { + match expr.node { + ExprWhile(..) | ExprLoop(..) => true, + _ => false, + } + } + _ => false, + } + }; + + match self.walk_parent_nodes(id, match_fn, match_non_returning_block) { + Ok(id) => Some(id), + Err(_) => None, + } + } + /// Retrieve the NodeId for `id`'s parent item, or `id` itself if no /// parent item is in this map. The "parent item" is the closest parent node /// in the AST which is recorded by the map and is an item, either an item @@ -637,7 +693,7 @@ impl<'hir> Map<'hir> { NodeTraitItem(_) | NodeImplItem(_) => true, _ => false, - }) { + }, |_| false) { Ok(id) => id, Err(id) => id, } @@ -649,7 +705,7 @@ impl<'hir> Map<'hir> { let id = match self.walk_parent_nodes(id, |node| match *node { NodeItem(&Item { node: Item_::ItemMod(_), .. }) => true, _ => false, - }) { + }, |_| false) { Ok(id) => id, Err(id) => id, }; @@ -668,7 +724,7 @@ impl<'hir> Map<'hir> { NodeImplItem(_) | NodeBlock(_) => true, _ => false, - }) { + }, |_| false) { Ok(id) => Some(id), Err(_) => None, } diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index a78d5ce1c16..c6f4cd585d7 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -1527,7 +1527,8 @@ impl<'a> State<'a> { if i > 0 { word(&mut self.s, "::")? } - if segment.name != keywords::CrateRoot.name() && segment.name != "$crate" { + 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)?; } @@ -1554,7 +1555,8 @@ impl<'a> State<'a> { if i > 0 { word(&mut self.s, "::")? } - if segment.name != keywords::CrateRoot.name() && segment.name != "$crate" { + 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)?; } diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 4e78d79ef87..4f365a97f4c 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -524,10 +524,9 @@ for ty::TypeVariants<'tcx> region.hash_stable(hcx, hasher); pointee_ty.hash_stable(hcx, hasher); } - TyFnDef(def_id, substs, ref sig) => { + TyFnDef(def_id, substs) => { def_id.hash_stable(hcx, hasher); substs.hash_stable(hcx, hasher); - sig.hash_stable(hcx, hasher); } TyFnPtr(ref sig) => { sig.hash_stable(hcx, hasher); diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 11bac21bc42..82bbb4a1bf5 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -72,9 +72,11 @@ use ty::error::TypeError; use syntax::ast::DUMMY_NODE_ID; use syntax_pos::{Pos, Span}; use errors::{DiagnosticBuilder, DiagnosticStyledString}; - mod note; + mod need_type_info; +mod named_anon_conflict; + impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn note_and_explain_region(self, @@ -255,34 +257,48 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { - pub fn report_region_errors(&self, - errors: &Vec>) { + + pub fn report_region_errors(&self, errors: &Vec>) { debug!("report_region_errors(): {} errors to start", errors.len()); // try to pre-process the errors, which will group some of them // together into a `ProcessedErrors` group: let errors = self.process_errors(errors); - debug!("report_region_errors: {} errors after preprocessing", errors.len()); + debug!("report_region_errors: {} errors after preprocessing", + errors.len()); for error in errors { + debug!("report_region_errors: error = {:?}", error); - match error.clone() { - ConcreteFailure(origin, sub, sup) => { - self.report_concrete_failure(origin, sub, sup).emit(); - } - GenericBoundFailure(kind, param_ty, sub) => { - self.report_generic_bound_failure(kind, param_ty, sub); - } + if !self.try_report_named_anon_conflict(&error){ - SubSupConflict(var_origin, + match error.clone() { + // These errors could indicate all manner of different + // problems with many different solutions. Rather + // than generate a "one size fits all" error, what we + // attempt to do is go through a number of specific + // scenarios and try to find the best way to present + // the error. If all of these fails, we fall back to a rather + // general bit of code that displays the error information + ConcreteFailure(origin, sub, sup) => { + + self.report_concrete_failure(origin, sub, sup).emit(); + } + + GenericBoundFailure(kind, param_ty, sub) => { + self.report_generic_bound_failure(kind, param_ty, sub); + } + + SubSupConflict(var_origin, sub_origin, sub_r, sup_origin, sup_r) => { - self.report_sub_sup_conflict(var_origin, + self.report_sub_sup_conflict(var_origin, sub_origin, sub_r, sup_origin, sup_r); - } + } + } } } } diff --git a/src/librustc/infer/error_reporting/named_anon_conflict.rs b/src/librustc/infer/error_reporting/named_anon_conflict.rs new file mode 100644 index 00000000000..ccbc5cdb862 --- /dev/null +++ b/src/librustc/infer/error_reporting/named_anon_conflict.rs @@ -0,0 +1,199 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Error Reporting for Anonymous Region Lifetime Errors. +use hir; +use infer::InferCtxt; +use ty::{self, Region}; +use infer::region_inference::RegionResolutionError::*; +use infer::region_inference::RegionResolutionError; +use hir::map as hir_map; +use hir::def_id::DefId; + +impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { + // This method walks the Type of the function body arguments using + // `fold_regions()` function and returns the + // &hir::Arg of the function argument corresponding to the anonymous + // region and the Ty corresponding to the named region. + // Currently only the case where the function declaration consists of + // one named region and one anonymous region is handled. + // Consider the example `fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32` + // Here, we would return the hir::Arg for y, we return the type &'a + // i32, which is the type of y but with the anonymous region replaced + // with 'a, the corresponding bound region and is_first which is true if + // the hir::Arg is the first argument in the function declaration. + fn find_arg_with_anonymous_region + (&self, + anon_region: Region<'tcx>, + named_region: Region<'tcx>) + -> Option<(&hir::Arg, ty::Ty<'tcx>, ty::BoundRegion, bool)> { + + match *anon_region { + ty::ReFree(ref free_region) => { + + let id = free_region.scope; + let node_id = self.tcx.hir.as_local_node_id(id).unwrap(); + let body_id = self.tcx.hir.maybe_body_owned_by(node_id).unwrap(); + let body = self.tcx.hir.body(body_id); + if let Some(tables) = self.in_progress_tables { + body.arguments + .iter() + .enumerate() + .filter_map(|(index, arg)| { + let ty = tables.borrow().node_id_to_type(arg.id); + let mut found_anon_region = false; + let new_arg_ty = self.tcx + .fold_regions(&ty, &mut false, |r, _| if *r == *anon_region { + found_anon_region = true; + named_region + } else { + r + }); + if found_anon_region { + let is_first = index == 0; + Some((arg, new_arg_ty, free_region.bound_region, is_first)) + } else { + None + } + }) + .next() + } else { + None + } + } + _ => None, + + } + } + + // This method generates the error message for the case when + // the function arguments consist of a named region and an anonymous + // region and corresponds to `ConcreteFailure(..)` + pub fn try_report_named_anon_conflict(&self, error: &RegionResolutionError<'tcx>) -> bool { + + let (span, sub, sup) = match *error { + ConcreteFailure(ref origin, sub, sup) => (origin.span(), sub, sup), + _ => return false, // inapplicable + }; + + // Determine whether the sub and sup consist of one named region ('a) + // and one anonymous (elided) region. If so, find the parameter arg + // where the anonymous region appears (there must always be one; we + // 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. + let (named, (arg, new_ty, br, is_first), scope_def_id) = + if sub.is_named_region() && self.is_suitable_anonymous_region(sup).is_some() { + (sub, + self.find_arg_with_anonymous_region(sup, sub).unwrap(), + self.is_suitable_anonymous_region(sup).unwrap()) + } else if sup.is_named_region() && self.is_suitable_anonymous_region(sub).is_some() { + (sup, + self.find_arg_with_anonymous_region(sub, sup).unwrap(), + self.is_suitable_anonymous_region(sub).unwrap()) + } else { + return false; // inapplicable + }; + + // Here, we check for the case where the anonymous region + // is in the return type. + // FIXME(#42703) - Need to handle certain cases here. + let ret_ty = self.tcx.type_of(scope_def_id); + match ret_ty.sty { + ty::TyFnDef(_, _) => { + let sig = ret_ty.fn_sig(self.tcx); + let late_bound_regions = self.tcx + .collect_referenced_late_bound_regions(&sig.output()); + if late_bound_regions.iter().any(|r| *r == br) { + return false; + } else { + } + } + _ => {} + } + + // Here we check for the case where anonymous region + // corresponds to self and if yes, we display E0312. + // FIXME(#42700) - Need to format self properly to + // enable E0621 for it. + if is_first && + self.tcx + .opt_associated_item(scope_def_id) + .map(|i| i.method_has_self_argument) + .unwrap_or(false) { + 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 { + (format!("parameter type"), format!("type")) + }; + + + 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; + + } + + // This method returns whether the given Region is Anonymous + // and returns the DefId corresponding to the region. + pub fn is_suitable_anonymous_region(&self, region: Region<'tcx>) -> Option { + + match *region { + ty::ReFree(ref free_region) => { + match free_region.bound_region { + ty::BrAnon(..) => { + let anonymous_region_binding_scope = free_region.scope; + let node_id = self.tcx + .hir + .as_local_node_id(anonymous_region_binding_scope) + .unwrap(); + match self.tcx.hir.find(node_id) { + Some(hir_map::NodeItem(..)) | + Some(hir_map::NodeTraitItem(..)) => { + // proceed ahead // + } + Some(hir_map::NodeImplItem(..)) => { + let container_id = self.tcx + .associated_item(anonymous_region_binding_scope) + .container + .id(); + if self.tcx.impl_trait_ref(container_id).is_some() { + // For now, we do not try to target impls of traits. This is + // because this message is going to suggest that the user + // change the fn signature, but they may not be free to do so, + // since the signature must match the trait. + // + // FIXME(#42706) -- in some cases, we could do better here. + return None; + } + } + _ => return None, // inapplicable + // we target only top-level functions + } + return Some(anonymous_region_binding_scope); + } + _ => None, + } + } + _ => None, + } + } +} diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs index 7361d66428f..a684881c091 100644 --- a/src/librustc/infer/error_reporting/need_type_info.rs +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use hir::{self, map, Local, Pat, Body}; +use hir::{self, Local, Pat, Body}; use hir::intravisit::{self, Visitor, NestedVisitorMap}; use infer::InferCtxt; use infer::type_variable::TypeVariableOrigin; @@ -88,7 +88,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } - pub fn need_type_info(&self, body_id: hir::BodyId, span: Span, ty: Ty<'tcx>) { + pub fn need_type_info(&self, body_id: Option, span: Span, ty: Ty<'tcx>) { let ty = self.resolve_type_vars_if_possible(&ty); let name = self.extract_type_name(&ty); @@ -103,11 +103,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { found_arg_pattern: None, }; - // #40294: cause.body_id can also be a fn declaration. - // Currently, if it's anything other than NodeExpr, we just ignore it - match self.tcx.hir.find(body_id.node_id) { - Some(map::NodeExpr(expr)) => local_visitor.visit_expr(expr), - _ => () + if let Some(body_id) = body_id { + let expr = self.tcx.hir.expect_expr(body_id.node_id); + local_visitor.visit_expr(expr); } if let Some(pattern) = local_visitor.found_arg_pattern { diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index f96e8c389d6..5cb1606da67 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -38,7 +38,6 @@ use errors::DiagnosticBuilder; use syntax_pos::{self, Span, DUMMY_SP}; use util::nodemap::FxHashMap; use arena::DroplessArena; - use self::combine::CombineFields; use self::higher_ranked::HrMatchResult; use self::region_inference::{RegionVarBindings, RegionSnapshot}; @@ -1077,6 +1076,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { region_map, free_regions); let errors = self.region_vars.resolve_regions(®ion_rels); + if !self.is_tainted_by_errors() { // As a heuristic, just skip reporting region errors // altogether if other errors have been reported while @@ -1191,28 +1191,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // types using one of these methods, and should not call span_err directly for such // errors. - pub fn type_error_message(&self, - sp: Span, - mk_msg: M, - actual_ty: Ty<'tcx>) - where M: FnOnce(String) -> String, - { - self.type_error_struct(sp, mk_msg, actual_ty).emit(); - } - - // FIXME: this results in errors without an error code. Deprecate? - pub fn type_error_struct(&self, - sp: Span, - mk_msg: M, - actual_ty: Ty<'tcx>) - -> DiagnosticBuilder<'tcx> - where M: FnOnce(String) -> String, - { - self.type_error_struct_with_diag(sp, |actual_ty| { - self.tcx.sess.struct_span_err(sp, &mk_msg(actual_ty)) - }, actual_ty) - } - pub fn type_error_struct_with_diag(&self, sp: Span, mk_diag: M, @@ -1369,7 +1347,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { Some(self.tcx.closure_kind(def_id)) } - pub fn closure_type(&self, def_id: DefId) -> ty::PolyFnSig<'tcx> { + /// Obtain the signature of a function or closure. + /// For closures, unlike `tcx.fn_sig(def_id)`, this method will + /// work during the type-checking of the enclosing function and + /// return the closure signature in its partially inferred state. + pub fn fn_sig(&self, def_id: DefId) -> ty::PolyFnSig<'tcx> { if let Some(tables) = self.in_progress_tables { if let Some(id) = self.tcx.hir.as_local_node_id(def_id) { if let Some(&ty) = tables.borrow().closure_tys.get(&id) { @@ -1378,7 +1360,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } - self.tcx.closure_type(def_id) + self.tcx.fn_sig(def_id) } } diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index b81c56e5ee8..e4cf893375c 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -39,7 +39,6 @@ #![feature(specialization)] #![feature(unboxed_closures)] #![feature(discriminant_value)] -#![feature(sort_unstable)] #![feature(trace_macros)] #![feature(test)] diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index a9e0ef51102..8202c6106d1 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -291,16 +291,13 @@ impl LintStore { self.by_name.insert(name.into(), Removed(reason.into())); } - #[allow(unused_variables)] - fn find_lint(&self, lint_name: &str, sess: &Session, span: Option) - -> Result - { + fn find_lint(&self, lint_name: &str) -> Result { match self.by_name.get(lint_name) { Some(&Id(lint_id)) => Ok(lint_id), Some(&Renamed(_, lint_id)) => { Ok(lint_id) }, - Some(&Removed(ref reason)) => { + Some(&Removed(_)) => { Err(FindLintError::Removed) }, None => Err(FindLintError::NotFound) @@ -313,7 +310,7 @@ impl LintStore { &lint_name[..], level); let lint_flag_val = Symbol::intern(&lint_name); - match self.find_lint(&lint_name[..], sess, None) { + match self.find_lint(&lint_name[..]) { Ok(lint_id) => self.levels.set(lint_id, (level, CommandLine(lint_flag_val))), Err(FindLintError::Removed) => { } Err(_) => { @@ -513,7 +510,6 @@ pub fn raw_struct_lint<'a, S>(sess: &'a Session, } let name = lint.name_lower(); - let mut def = None; // Except for possible note details, forbid behaves like deny. let effective_level = if level == Forbid { Deny } else { level }; @@ -528,7 +524,8 @@ pub fn raw_struct_lint<'a, S>(sess: &'a Session, match source { Default => { - err.note(&format!("#[{}({})] on by default", level.as_str(), name)); + sess.diag_note_once(&mut err, lint, + &format!("#[{}({})] on by default", level.as_str(), name)); }, CommandLine(lint_flag_val) => { let flag = match level { @@ -537,20 +534,24 @@ pub fn raw_struct_lint<'a, S>(sess: &'a Session, }; let hyphen_case_lint_name = name.replace("_", "-"); if lint_flag_val.as_str() == name { - err.note(&format!("requested on the command line with `{} {}`", - flag, hyphen_case_lint_name)); + sess.diag_note_once(&mut err, lint, + &format!("requested on the command line with `{} {}`", + flag, hyphen_case_lint_name)); } else { let hyphen_case_flag_val = lint_flag_val.as_str().replace("_", "-"); - err.note(&format!("`{} {}` implied by `{} {}`", - flag, hyphen_case_lint_name, flag, hyphen_case_flag_val)); + sess.diag_note_once(&mut err, lint, + &format!("`{} {}` implied by `{} {}`", + flag, hyphen_case_lint_name, flag, + hyphen_case_flag_val)); } }, Node(lint_attr_name, src) => { - def = Some(src); + sess.diag_span_note_once(&mut err, lint, src, "lint level defined here"); if lint_attr_name.as_str() != name { let level_str = level.as_str(); - err.note(&format!("#[{}({})] implied by #[{}({})]", - level_str, name, level_str, lint_attr_name)); + sess.diag_note_once(&mut err, lint, + &format!("#[{}({})] implied by #[{}({})]", + level_str, name, level_str, lint_attr_name)); } } } @@ -566,10 +567,6 @@ pub fn raw_struct_lint<'a, S>(sess: &'a Session, err.note(&citation); } - if let Some(span) = def { - sess.diag_span_note_once(&mut err, lint, span, "lint level defined here"); - } - err } @@ -724,21 +721,22 @@ pub trait LintContext<'tcx>: Sized { let mut pushed = 0; for result in gather_attrs(attrs) { - let v = match result { + let (is_group, lint_level_spans) = match result { Err(span) => { span_err!(self.sess(), span, E0452, "malformed lint attribute"); continue; } Ok((lint_name, level, span)) => { - match self.lints().find_lint(&lint_name.as_str(), &self.sess(), Some(span)) { - Ok(lint_id) => vec![(lint_id, level, span)], + match self.lints().find_lint(&lint_name.as_str()) { + Ok(lint_id) => (false, vec![(lint_id, level, span)]), Err(FindLintError::NotFound) => { match self.lints().lint_groups.get(&*lint_name.as_str()) { - Some(&(ref v, _)) => v.iter() + Some(&(ref v, _)) => (true, + v.iter() .map(|lint_id: &LintId| (*lint_id, level, span)) - .collect(), + .collect()), None => { // The lint or lint group doesn't exist. // This is an error, but it was handled @@ -754,14 +752,18 @@ pub trait LintContext<'tcx>: Sized { let lint_attr_name = result.expect("lint attribute should be well-formed").0; - for (lint_id, level, span) in v { + for (lint_id, level, span) in lint_level_spans { let (now, now_source) = self.lint_sess().get_source(lint_id); if now == Forbid && level != Forbid { - let lint_name = lint_id.to_string(); + let forbidden_lint_name = match now_source { + LintSource::Default => lint_id.to_string(), + LintSource::Node(name, _) => name.to_string(), + LintSource::CommandLine(name) => name.to_string(), + }; let mut diag_builder = struct_span_err!(self.sess(), span, E0453, "{}({}) overruled by outer forbid({})", - level.as_str(), lint_name, - lint_name); + level.as_str(), lint_attr_name, + forbidden_lint_name); diag_builder.span_label(span, "overruled by previous forbid"); match now_source { LintSource::Default => &mut diag_builder, @@ -772,7 +774,10 @@ pub trait LintContext<'tcx>: Sized { LintSource::CommandLine(_) => { diag_builder.note("`forbid` lint level was set on command line") } - }.emit() + }.emit(); + if is_group { // don't set a separate error for every lint in the group + break; + } } else if now != level { let cx = self.lint_sess_mut(); cx.stack.push((lint_id, (now, now_source))); @@ -1420,7 +1425,7 @@ impl Decodable for LintId { fn decode(d: &mut D) -> Result { let s = d.read_str()?; ty::tls::with(|tcx| { - match tcx.sess.lint_store.borrow().find_lint(&s, tcx.sess, None) { + match tcx.sess.lint_store.borrow().find_lint(&s) { Ok(id) => Ok(id), Err(_) => panic!("invalid lint-id `{}`", s), } diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index 74e1225f394..eab5a8f9103 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -12,7 +12,7 @@ //! `unsafe`. use self::RootUnsafeContext::*; -use ty::{self, Ty, TyCtxt}; +use ty::{self, TyCtxt}; use lint; use syntax::ast; @@ -40,14 +40,6 @@ enum RootUnsafeContext { UnsafeBlock(ast::NodeId), } -fn type_is_unsafe_function(ty: Ty) -> bool { - match ty.sty { - ty::TyFnDef(.., f) | - ty::TyFnPtr(f) => f.unsafety() == hir::Unsafety::Unsafe, - _ => false, - } -} - struct EffectCheckVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, tables: &'a ty::TypeckTables<'tcx>, @@ -174,10 +166,11 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { match expr.node { hir::ExprMethodCall(..) => { let def_id = self.tables.type_dependent_defs[&expr.id].def_id(); - let base_type = self.tcx.type_of(def_id); - debug!("effect: method call case, base type is {:?}", - base_type); - if type_is_unsafe_function(base_type) { + 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") } @@ -186,8 +179,13 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { let base_type = self.tables.expr_ty_adjusted(base); debug!("effect: call case, base type is {:?}", base_type); - if type_is_unsafe_function(base_type) { - self.require_unsafe(expr.span, "call to unsafe function") + 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) => { diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 58e77f40d98..259bd4f0999 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -816,7 +816,6 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { fn walk_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat, match_mode: MatchMode) { debug!("walk_pat cmt_discr={:?} pat={:?}", cmt_discr, pat); - let tcx = self.tcx(); let ExprUseVisitor { ref mc, ref mut delegate, param_env } = *self; return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |cmt_pat, pat| { if let PatKind::Binding(bmode, def_id, ..) = pat.node { @@ -864,13 +863,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { match def { Def::Variant(variant_did) | Def::VariantCtor(variant_did, ..) => { - let enum_did = tcx.parent_def_id(variant_did).unwrap(); - let downcast_cmt = if tcx.adt_def(enum_did).is_univariant() { - cmt_pat - } else { - let cmt_pat_ty = cmt_pat.ty; - mc.cat_downcast(pat, cmt_pat, cmt_pat_ty, variant_did) - }; + let downcast_cmt = mc.cat_downcast_if_needed(pat, cmt_pat, variant_did); debug!("variant downcast_cmt={:?} pat={:?}", downcast_cmt, pat); delegate.matched_pat(pat, downcast_cmt, match_mode); diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index f180ae53b8a..fde207e4b2f 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -66,11 +66,8 @@ fn unpack_option_like<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl<'a, 'tcx> ExprVisitor<'a, 'tcx> { fn def_id_is_transmute(&self, def_id: DefId) -> bool { - let intrinsic = match self.tcx.type_of(def_id).sty { - ty::TyFnDef(.., bfty) => bfty.abi() == RustIntrinsic, - _ => return false - }; - intrinsic && self.tcx.item_name(def_id) == "transmute" + self.tcx.fn_sig(def_id).abi() == RustIntrinsic && + self.tcx.item_name(def_id) == "transmute" } fn check_transmute(&self, span: Span, from: Ty<'tcx>, to: Ty<'tcx>) { @@ -153,22 +150,14 @@ impl<'a, 'tcx> Visitor<'tcx> for ExprVisitor<'a, 'tcx> { } else { Def::Err }; - match def { - Def::Fn(did) if self.def_id_is_transmute(did) => { + if let Def::Fn(did) = def { + if self.def_id_is_transmute(did) { let typ = self.tables.node_id_to_type(expr.id); - let typ = self.tcx.lift_to_global(&typ).unwrap(); - match typ.sty { - ty::TyFnDef(.., sig) if sig.abi() == RustIntrinsic => { - let from = sig.inputs().skip_binder()[0]; - let to = *sig.output().skip_binder(); - self.check_transmute(expr.span, from, to); - } - _ => { - span_bug!(expr.span, "transmute wasn't a bare fn?!"); - } - } + let sig = typ.fn_sig(self.tcx); + let from = sig.inputs().skip_binder()[0]; + let to = *sig.output().skip_binder(); + self.check_transmute(expr.span, from, to); } - _ => {} } intravisit::walk_expr(self, expr); diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 259079cf160..5c741eccf83 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -1032,22 +1032,29 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { ret } - pub fn cat_downcast(&self, - node: &N, - base_cmt: cmt<'tcx>, - downcast_ty: Ty<'tcx>, - variant_did: DefId) - -> cmt<'tcx> { - let ret = Rc::new(cmt_ { - id: node.id(), - span: node.span(), - mutbl: base_cmt.mutbl.inherit(), - cat: Categorization::Downcast(base_cmt, variant_did), - ty: downcast_ty, - note: NoteNone - }); - debug!("cat_downcast ret={:?}", ret); - ret + pub fn cat_downcast_if_needed(&self, + node: &N, + base_cmt: cmt<'tcx>, + variant_did: DefId) + -> cmt<'tcx> { + // univariant enums do not need downcasts + let base_did = self.tcx.parent_def_id(variant_did).unwrap(); + if !self.tcx.adt_def(base_did).is_univariant() { + let base_ty = base_cmt.ty; + let ret = Rc::new(cmt_ { + id: node.id(), + span: node.span(), + mutbl: base_cmt.mutbl.inherit(), + cat: Categorization::Downcast(base_cmt, variant_did), + ty: base_ty, + note: NoteNone + }); + debug!("cat_downcast ret={:?}", ret); + ret + } else { + debug!("cat_downcast univariant={:?}", base_cmt); + base_cmt + } } pub fn cat_pattern(&self, cmt: cmt<'tcx>, pat: &hir::Pat, mut op: F) -> McResult<()> @@ -1109,45 +1116,23 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { op(cmt.clone(), pat); - // Note: This goes up here (rather than within the PatKind::TupleStruct arm - // alone) because PatKind::Struct can also refer to variants. - let cmt = match pat.node { - PatKind::Path(hir::QPath::Resolved(_, ref path)) | - PatKind::TupleStruct(hir::QPath::Resolved(_, ref path), ..) | - PatKind::Struct(hir::QPath::Resolved(_, ref path), ..) => { - match path.def { - Def::Err => { - debug!("access to unresolvable pattern {:?}", pat); - return Err(()) - } - Def::Variant(variant_did) | - Def::VariantCtor(variant_did, ..) => { - // univariant enums do not need downcasts - let enum_did = self.tcx.parent_def_id(variant_did).unwrap(); - if !self.tcx.adt_def(enum_did).is_univariant() { - self.cat_downcast(pat, cmt.clone(), cmt.ty, variant_did) - } else { - cmt - } - } - _ => cmt - } - } - _ => cmt - }; - match pat.node { PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => { let def = self.tables.qpath_def(qpath, pat.id); - let expected_len = match def { + let (cmt, expected_len) = match def { + Def::Err => { + debug!("access to unresolvable pattern {:?}", pat); + return Err(()) + } Def::VariantCtor(def_id, CtorKind::Fn) => { let enum_def = self.tcx.parent_def_id(def_id).unwrap(); - self.tcx.adt_def(enum_def).variant_with_id(def_id).fields.len() + (self.cat_downcast_if_needed(pat, cmt, def_id), + self.tcx.adt_def(enum_def).variant_with_id(def_id).fields.len()) } Def::StructCtor(_, CtorKind::Fn) => { match self.pat_ty(&pat)?.sty { ty::TyAdt(adt_def, _) => { - adt_def.struct_variant().fields.len() + (cmt, adt_def.struct_variant().fields.len()) } ref ty => { span_bug!(pat.span, "tuple struct pattern unexpected type {:?}", ty); @@ -1168,8 +1153,21 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } } - PatKind::Struct(_, ref field_pats, _) => { + PatKind::Struct(ref qpath, ref field_pats, _) => { // {f1: p1, ..., fN: pN} + let def = self.tables.qpath_def(qpath, pat.id); + let cmt = match def { + Def::Err => { + debug!("access to unresolvable pattern {:?}", pat); + return Err(()) + }, + Def::Variant(variant_did) | + Def::VariantCtor(variant_did, ..) => { + self.cat_downcast_if_needed(pat, cmt, variant_did) + }, + _ => cmt + }; + for fp in field_pats { let field_ty = self.pat_ty(&fp.node.pat)?; // see (*2) let cmt_field = self.cat_field(pat, cmt.clone(), fp.node.name, field_ty); diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index ce5d58f5800..b347a931851 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -28,6 +28,7 @@ use syntax::attr; use syntax::ptr::P; use syntax_pos::Span; use errors::DiagnosticBuilder; +use util::common::ErrorReported; use util::nodemap::{NodeMap, NodeSet, FxHashSet, FxHashMap, DefIdMap}; use rustc_back::slice; @@ -255,7 +256,7 @@ const ROOT_SCOPE: ScopeRef<'static> = &Scope::Root; pub fn krate(sess: &Session, hir_map: &Map) - -> Result { + -> Result { let krate = hir_map.krate(); let mut map = NamedRegionMap { defs: NodeMap(), diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 70c07982f83..8bafdda234a 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -21,7 +21,7 @@ use session::search_paths::PathKind; use session::config::DebugInfoLevel; use ty::tls; use util::nodemap::{FxHashMap, FxHashSet}; -use util::common::duration_to_secs_str; +use util::common::{duration_to_secs_str, ErrorReported}; use syntax::ast::NodeId; use errors::{self, DiagnosticBuilder}; @@ -79,10 +79,10 @@ pub struct Session { pub working_dir: (String, bool), pub lint_store: RefCell, pub lints: RefCell, - /// Set of (LintId, span, message) tuples tracking lint (sub)diagnostics - /// that have been set once, but should not be set again, in order to avoid - /// redundantly verbose output (Issue #24690). - pub one_time_diagnostics: RefCell>, + /// Set of (LintId, Option, message) tuples tracking lint + /// (sub)diagnostics that have been set once, but should not be set again, + /// in order to avoid redundantly verbose output (Issue #24690). + pub one_time_diagnostics: RefCell, String)>>, pub plugin_llvm_passes: RefCell>, pub plugin_attributes: RefCell>, pub crate_types: RefCell>, @@ -157,6 +157,13 @@ pub struct PerfStats { pub decode_def_path_tables_time: Cell, } +/// Enum to support dispatch of one-time diagnostics (in Session.diag_once) +enum DiagnosticBuilderMethod { + Note, + SpanNote, + // add more variants as needed to support one-time diagnostics +} + impl Session { pub fn local_crate_disambiguator(&self) -> Symbol { *self.crate_disambiguator.borrow() @@ -248,7 +255,10 @@ impl Session { pub fn abort_if_errors(&self) { self.diagnostic().abort_if_errors(); } - pub fn track_errors(&self, f: F) -> Result + pub fn compile_status(&self) -> Result<(), CompileIncomplete> { + compile_result_from_err_count(self.err_count()) + } + pub fn track_errors(&self, f: F) -> Result where F: FnOnce() -> T { let old_count = self.err_count(); @@ -257,7 +267,7 @@ impl Session { if errors == 0 { Ok(result) } else { - Err(errors) + Err(ErrorReported) } } pub fn span_warn>(&self, sp: S, msg: &str) { @@ -329,34 +339,53 @@ impl Session { &self.parse_sess.span_diagnostic } - /// Analogous to calling `.span_note` on the given DiagnosticBuilder, but - /// deduplicates on lint ID, span, and message for this `Session` if we're - /// not outputting in JSON mode. - // - // FIXME: if the need arises for one-time diagnostics other than - // `span_note`, we almost certainly want to generalize this - // "check/insert-into the one-time diagnostics map, then set message if - // it's not already there" code to accomodate all of them - pub fn diag_span_note_once<'a, 'b>(&'a self, - diag_builder: &'b mut DiagnosticBuilder<'a>, - lint: &'static lint::Lint, span: Span, message: &str) { + /// Analogous to calling methods on the given `DiagnosticBuilder`, but + /// deduplicates on lint ID, span (if any), and message for this `Session` + /// if we're not outputting in JSON mode. + fn diag_once<'a, 'b>(&'a self, + diag_builder: &'b mut DiagnosticBuilder<'a>, + method: DiagnosticBuilderMethod, + lint: &'static lint::Lint, message: &str, span: Option) { + let mut do_method = || { + match method { + DiagnosticBuilderMethod::Note => { + diag_builder.note(message); + }, + DiagnosticBuilderMethod::SpanNote => { + diag_builder.span_note(span.expect("span_note expects a span"), message); + } + } + }; + match self.opts.error_format { // when outputting JSON for tool consumption, the tool might want // the duplicates config::ErrorOutputType::Json => { - diag_builder.span_note(span, &message); + do_method() }, _ => { let lint_id = lint::LintId::of(lint); let id_span_message = (lint_id, span, message.to_owned()); let fresh = self.one_time_diagnostics.borrow_mut().insert(id_span_message); if fresh { - diag_builder.span_note(span, &message); + do_method() } } } } + pub fn diag_span_note_once<'a, 'b>(&'a self, + diag_builder: &'b mut DiagnosticBuilder<'a>, + lint: &'static lint::Lint, span: Span, message: &str) { + self.diag_once(diag_builder, DiagnosticBuilderMethod::SpanNote, lint, message, Some(span)); + } + + pub fn diag_note_once<'a, 'b>(&'a self, + diag_builder: &'b mut DiagnosticBuilder<'a>, + lint: &'static lint::Lint, message: &str) { + self.diag_once(diag_builder, DiagnosticBuilderMethod::Note, lint, message, None); + } + pub fn codemap<'a>(&'a self) -> &'a codemap::CodeMap { self.parse_sess.codemap() } @@ -776,15 +805,23 @@ pub fn early_warn(output: config::ErrorOutputType, msg: &str) { handler.emit(&MultiSpan::new(), msg, errors::Level::Warning); } -// Err(0) means compilation was stopped, but no errors were found. -// This would be better as a dedicated enum, but using try! is so convenient. -pub type CompileResult = Result<(), usize>; +#[derive(Copy, Clone, Debug)] +pub enum CompileIncomplete { + Stopped, + Errored(ErrorReported) +} +impl From for CompileIncomplete { + fn from(err: ErrorReported) -> CompileIncomplete { + CompileIncomplete::Errored(err) + } +} +pub type CompileResult = Result<(), CompileIncomplete>; pub fn compile_result_from_err_count(err_count: usize) -> CompileResult { if err_count == 0 { Ok(()) } else { - Err(err_count) + Err(CompileIncomplete::Errored(ErrorReported)) } } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 247fb079fe7..0bf0e21baaf 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -45,7 +45,8 @@ use syntax_pos::{DUMMY_SP, Span}; impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { pub fn report_fulfillment_errors(&self, - errors: &Vec>) { + errors: &Vec>, + body_id: Option) { #[derive(Debug)] struct ErrorDescriptor<'tcx> { predicate: ty::Predicate<'tcx>, @@ -105,7 +106,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { for (error, suppressed) in errors.iter().zip(is_suppressed) { if !suppressed { - self.report_fulfillment_error(error); + self.report_fulfillment_error(error, body_id); } } } @@ -148,7 +149,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { false } - fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) { + fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>, + body_id: Option) { debug!("report_fulfillment_errors({:?})", error); match error.code { FulfillmentErrorCode::CodeSelectionError(ref e) => { @@ -158,7 +160,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.report_projection_error(&error.obligation, e); } FulfillmentErrorCode::CodeAmbiguity => { - self.maybe_report_ambiguity(&error.obligation); + self.maybe_report_ambiguity(&error.obligation, body_id); } FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => { self.report_mismatched_types(&error.obligation.cause, @@ -869,14 +871,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { - fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) { + fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>, + body_id: Option) { // Unable to successfully determine, probably means // insufficient type information, but could mean // ambiguous impls. The latter *ought* to be a // coherence violation, so we don't report it here. let predicate = self.resolve_type_vars_if_possible(&obligation.predicate); - let body_id = hir::BodyId { node_id: obligation.cause.body_id }; let span = obligation.cause.span; debug!("maybe_report_ambiguity(predicate={:?}, obligation={:?})", @@ -953,7 +955,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder(); // both must be type variables, or the other would've been instantiated assert!(a.is_ty_var() && b.is_ty_var()); - self.need_type_info(hir::BodyId { node_id: obligation.cause.body_id }, + self.need_type_info(body_id, obligation.cause.span, a); } @@ -1058,7 +1060,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { err.note("slice and array elements must have `Sized` type"); } ObligationCauseCode::TupleElem => { - err.note("tuple elements must have `Sized` type"); + err.note("only the last element of a tuple may have a dynamically sized type"); } ObligationCauseCode::ProjectionWf(data) => { err.note(&format!("required so that the projection `{}` is well-formed", @@ -1088,13 +1090,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ObligationCauseCode::VariableType(_) => { err.note("all local variables must have a statically known size"); } - ObligationCauseCode::ReturnType => { + ObligationCauseCode::SizedReturnType => { err.note("the return type of a function must have a \ statically known size"); } ObligationCauseCode::AssignmentLhsSized => { err.note("the left-hand-side of an assignment must have a statically known size"); } + ObligationCauseCode::TupleInitializerSized => { + err.note("tuples must have a statically known size to be initialized"); + } ObligationCauseCode::StructInitializerSized => { err.note("structs must have a statically known size to be initialized"); } @@ -1133,6 +1138,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { but not on the corresponding trait method", predicate)); } + ObligationCauseCode::ReturnType(_) | + ObligationCauseCode::BlockTailExpression(_) => (), } } diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index e9196cd1243..16c41c816b4 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -118,27 +118,34 @@ pub enum ObligationCauseCode<'tcx> { /// Obligation incurred due to an object cast. ObjectCastObligation(/* Object type */ Ty<'tcx>), - /// Various cases where expressions must be sized/copy/etc: - AssignmentLhsSized, // L = X implies that L is Sized - StructInitializerSized, // S { ... } must be Sized - VariableType(ast::NodeId), // Type of each variable must be Sized - ReturnType, // Return type must be Sized - RepeatVec, // [T,..n] --> T must be Copy + // Various cases where expressions must be sized/copy/etc: + /// L = X implies that L is Sized + AssignmentLhsSized, + /// (x1, .., xn) must be Sized + TupleInitializerSized, + /// S { ... } must be Sized + StructInitializerSized, + /// Type of each variable must be Sized + VariableType(ast::NodeId), + /// Return type must be Sized + SizedReturnType, + /// [T,..n] --> T must be Copy + RepeatVec, - // Types of fields (other than the last) in a struct must be sized. + /// Types of fields (other than the last) in a struct must be sized. FieldSized, - // Constant expressions must be sized. + /// Constant expressions must be sized. ConstSized, - // static items must have `Sync` type + /// static items must have `Sync` type SharedStatic, BuiltinDerivedObligation(DerivedObligationCause<'tcx>), ImplDerivedObligation(DerivedObligationCause<'tcx>), - // error derived when matching traits/impls; see ObligationCause for more details + /// error derived when matching traits/impls; see ObligationCause for more details CompareImplMethodObligation { item_name: ast::Name, impl_item_def_id: DefId, @@ -146,37 +153,43 @@ pub enum ObligationCauseCode<'tcx> { lint_id: Option, }, - // Checking that this expression can be assigned where it needs to be + /// Checking that this expression can be assigned where it needs to be // FIXME(eddyb) #11161 is the original Expr required? ExprAssignable, - // Computing common supertype in the arms of a match expression + /// Computing common supertype in the arms of a match expression MatchExpressionArm { arm_span: Span, source: hir::MatchSource }, - // Computing common supertype in an if expression + /// Computing common supertype in an if expression IfExpression, - // Computing common supertype of an if expression with no else counter-part + /// Computing common supertype of an if expression with no else counter-part IfExpressionWithNoElse, - // `where a == b` + /// `where a == b` EquatePredicate, - // `main` has wrong type + /// `main` has wrong type MainFunctionType, - // `start` has wrong type + /// `start` has wrong type StartFunctionType, - // intrinsic has wrong type + /// intrinsic has wrong type IntrinsicType, - // method receiver + /// method receiver MethodReceiver, - // `return` with no expression + /// `return` with no expression ReturnNoExpression, + + /// `return` with an expression + ReturnType(ast::NodeId), + + /// Block implicit return + BlockTailExpression(ast::NodeId), } #[derive(Clone, Debug, PartialEq, Eq)] @@ -498,7 +511,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ) { Ok(predicates) => predicates, Err(errors) => { - infcx.report_fulfillment_errors(&errors); + infcx.report_fulfillment_errors(&errors, None); // An unnormalized env is better than nothing. return elaborated_env; } @@ -597,7 +610,7 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, debug!("normalize_and_test_predicates(predicates={:?})", predicates); - tcx.infer_ctxt().enter(|infcx| { + let result = tcx.infer_ctxt().enter(|infcx| { let param_env = ty::ParamEnv::empty(Reveal::All); let mut selcx = SelectionContext::new(&infcx); let mut fulfill_cx = FulfillmentContext::new(); @@ -613,7 +626,10 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } fulfill_cx.select_all_or_error(&infcx).is_ok() - }) + }); + debug!("normalize_and_test_predicates(predicates={:?}) = {:?}", + predicates, result); + result } /// Given a trait `trait_ref`, iterates the vtable entries diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 0e3a53129d1..c6c052fa4b1 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -260,7 +260,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // The `Self` type is erased, so it should not appear in list of // arguments or return type apart from the receiver. - let ref sig = self.type_of(method.def_id).fn_sig(); + let ref sig = self.fn_sig(method.def_id); for input_ty in &sig.skip_binder().inputs()[1..] { if self.contains_illegal_self_type_reference(trait_def_id, input_ty) { return Some(MethodViolationCode::ReferencesSelf); diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 787452121d3..c356e53234d 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -1137,9 +1137,19 @@ fn confirm_fn_pointer_candidate<'cx, 'gcx, 'tcx>( -> Progress<'tcx> { let fn_type = selcx.infcx().shallow_resolve(fn_pointer_vtable.fn_ty); - let sig = fn_type.fn_sig(); + let sig = fn_type.fn_sig(selcx.tcx()); + let Normalized { + value: sig, + obligations + } = normalize_with_depth(selcx, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth+1, + &sig); + confirm_callable_candidate(selcx, obligation, sig, util::TupleArgumentsFlag::Yes) .with_addl_obligations(fn_pointer_vtable.nested) + .with_addl_obligations(obligations) } fn confirm_closure_candidate<'cx, 'gcx, 'tcx>( @@ -1149,7 +1159,7 @@ fn confirm_closure_candidate<'cx, 'gcx, 'tcx>( -> Progress<'tcx> { let closure_typer = selcx.closure_typer(); - let closure_type = closure_typer.closure_type(vtable.closure_def_id) + let closure_type = closure_typer.fn_sig(vtable.closure_def_id) .subst(selcx.tcx(), vtable.substs.substs); let Normalized { value: closure_type, diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 10710d963a0..856fea7c2c4 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1404,19 +1404,15 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } // provide an impl, but only for suitable `fn` pointers - ty::TyFnDef(.., ty::Binder(ty::FnSig { - unsafety: hir::Unsafety::Normal, - abi: Abi::Rust, - variadic: false, - .. - })) | - ty::TyFnPtr(ty::Binder(ty::FnSig { - unsafety: hir::Unsafety::Normal, - abi: Abi::Rust, - variadic: false, - .. - })) => { - candidates.vec.push(FnPointerCandidate); + ty::TyFnDef(..) | ty::TyFnPtr(_) => { + if let ty::Binder(ty::FnSig { + unsafety: hir::Unsafety::Normal, + abi: Abi::Rust, + variadic: false, + .. + }) = self_ty.fn_sig(self.tcx()) { + candidates.vec.push(FnPointerCandidate); + } } _ => { } @@ -1655,6 +1651,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { def_id_a == def_id_b } + // (.., T) -> (.., U). + (&ty::TyTuple(tys_a, _), &ty::TyTuple(tys_b, _)) => { + tys_a.len() == tys_b.len() + } + _ => false }; @@ -2348,7 +2349,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // ok to skip binder; it is reintroduced below let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder()); - let sig = self_ty.fn_sig(); + let sig = self_ty.fn_sig(self.tcx()); let trait_ref = self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(), self_ty, @@ -2356,11 +2357,18 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { util::TupleArgumentsFlag::Yes) .map_bound(|(trait_ref, _)| trait_ref); + let Normalized { value: trait_ref, obligations } = + project::normalize_with_depth(self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &trait_ref); + self.confirm_poly_trait_refs(obligation.cause.clone(), obligation.param_env, obligation.predicate.to_poly_trait_ref(), trait_ref)?; - Ok(VtableFnPointerData { fn_ty: self_ty, nested: vec![] }) + Ok(VtableFnPointerData { fn_ty: self_ty, nested: obligations }) } fn confirm_closure_candidate(&mut self, @@ -2588,8 +2596,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let inner_source = field.subst(tcx, substs_a); let inner_target = field.subst(tcx, substs_b); - // Check that the source structure with the target's - // type parameters is a subtype of the target. + // Check that the source struct with the target's + // unsized parameters is equal to the target. let params = substs_a.iter().enumerate().map(|(i, &k)| { if ty_params.contains(i) { Kind::from(substs_b.type_at(i)) @@ -2614,6 +2622,37 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { &[inner_target])); } + // (.., T) -> (.., U). + (&ty::TyTuple(tys_a, _), &ty::TyTuple(tys_b, _)) => { + assert_eq!(tys_a.len(), tys_b.len()); + + // The last field of the tuple has to exist. + let (a_last, a_mid) = if let Some(x) = tys_a.split_last() { + x + } else { + return Err(Unimplemented); + }; + let b_last = tys_b.last().unwrap(); + + // Check that the source tuple with the target's + // last element is equal to the target. + let new_tuple = tcx.mk_tup(a_mid.iter().chain(Some(b_last)), false); + let InferOk { obligations, .. } = + self.infcx.at(&obligation.cause, obligation.param_env) + .eq(target, new_tuple) + .map_err(|_| Unimplemented)?; + self.inferred_obligations.extend(obligations); + + // Construct the nested T: Unsize predicate. + nested.push(tcx.predicate_for_trait_def( + obligation.param_env, + obligation.cause.clone(), + obligation.predicate.def_id(), + obligation.recursion_depth + 1, + a_last, + &[b_last])); + } + _ => bug!() }; @@ -2799,7 +2838,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { substs: ty::ClosureSubsts<'tcx>) -> ty::PolyTraitRef<'tcx> { - let closure_type = self.infcx.closure_type(closure_def_id) + let closure_type = self.infcx.fn_sig(closure_def_id) .subst(self.tcx(), substs.substs); let ty::Binder((trait_ref, _)) = self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(), diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 4abb0cb549d..c4479e69032 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -189,9 +189,11 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { tcx.lift(&ty).map(super::ObjectCastObligation) } super::AssignmentLhsSized => Some(super::AssignmentLhsSized), + super::TupleInitializerSized => Some(super::TupleInitializerSized), super::StructInitializerSized => Some(super::StructInitializerSized), super::VariableType(id) => Some(super::VariableType(id)), - super::ReturnType => Some(super::ReturnType), + super::ReturnType(id) => Some(super::ReturnType(id)), + super::SizedReturnType => Some(super::SizedReturnType), super::RepeatVec => Some(super::RepeatVec), super::FieldSized => Some(super::FieldSized), super::ConstSized => Some(super::ConstSized), @@ -213,34 +215,19 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { lint_id: lint_id, }) } - super::ExprAssignable => { - Some(super::ExprAssignable) - } + super::ExprAssignable => Some(super::ExprAssignable), super::MatchExpressionArm { arm_span, source } => { Some(super::MatchExpressionArm { arm_span: arm_span, source: source }) } - super::IfExpression => { - Some(super::IfExpression) - } - super::IfExpressionWithNoElse => { - Some(super::IfExpressionWithNoElse) - } - super::EquatePredicate => { - Some(super::EquatePredicate) - } - super::MainFunctionType => { - Some(super::MainFunctionType) - } - super::StartFunctionType => { - Some(super::StartFunctionType) - } - super::IntrinsicType => { - Some(super::IntrinsicType) - } - super::MethodReceiver => { - Some(super::MethodReceiver) - } + super::IfExpression => Some(super::IfExpression), + super::IfExpressionWithNoElse => Some(super::IfExpressionWithNoElse), + super::EquatePredicate => Some(super::EquatePredicate), + super::MainFunctionType => Some(super::MainFunctionType), + super::StartFunctionType => Some(super::StartFunctionType), + super::IntrinsicType => Some(super::IntrinsicType), + super::MethodReceiver => Some(super::MethodReceiver), + super::BlockTailExpression(id) => Some(super::BlockTailExpression(id)), } } } @@ -490,14 +477,17 @@ impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCauseCode<'tcx> { super::TupleElem | super::ItemObligation(_) | super::AssignmentLhsSized | + super::TupleInitializerSized | super::StructInitializerSized | super::VariableType(_) | - super::ReturnType | + super::ReturnType(_) | + super::SizedReturnType | super::ReturnNoExpression | super::RepeatVec | super::FieldSized | super::ConstSized | super::SharedStatic | + super::BlockTailExpression(_) | super::CompareImplMethodObligation { .. } => self.clone(), super::ProjectionWf(proj) => super::ProjectionWf(proj.fold_with(folder)), @@ -535,14 +525,17 @@ impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCauseCode<'tcx> { super::TupleElem | super::ItemObligation(_) | super::AssignmentLhsSized | + super::TupleInitializerSized | super::StructInitializerSized | super::VariableType(_) | - super::ReturnType | + super::ReturnType(_) | + super::SizedReturnType | super::ReturnNoExpression | super::RepeatVec | super::FieldSized | super::ConstSized | super::SharedStatic | + super::BlockTailExpression(_) | super::CompareImplMethodObligation { .. } => false, super::ProjectionWf(proj) => proj.visit_with(visitor), diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 2d81606329e..5f869fc5567 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1378,9 +1378,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn mk_fn_def(self, def_id: DefId, - substs: &'tcx Substs<'tcx>, - fty: PolyFnSig<'tcx>) -> Ty<'tcx> { - self.mk_ty(TyFnDef(def_id, substs, fty)) + substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { + self.mk_ty(TyFnDef(def_id, substs)) } pub fn mk_fn_ptr(self, fty: PolyFnSig<'tcx>) -> Ty<'tcx> { diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs index 3d2cc4c598a..68f85ba7d33 100644 --- a/src/librustc/ty/fast_reject.rs +++ b/src/librustc/ty/fast_reject.rs @@ -68,6 +68,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, // view of possibly unifying simplify_type(tcx, mt.ty, can_simplify_params) } + ty::TyFnDef(def_id, _) | ty::TyClosure(def_id, _) => { Some(ClosureSimplifiedType(def_id)) } @@ -75,7 +76,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, ty::TyTuple(ref tys, _) => { Some(TupleSimplifiedType(tys.len())) } - ty::TyFnDef(.., ref f) | ty::TyFnPtr(ref f) => { + ty::TyFnPtr(ref f) => { Some(FunctionSimplifiedType(f.skip_binder().inputs().len())) } ty::TyProjection(_) | ty::TyParam(_) => { diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 46afa6ee7d0..d5aa9f55ff0 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -155,9 +155,8 @@ impl FlagComputation { self.add_tys(&ts[..]); } - &ty::TyFnDef(_, substs, f) => { + &ty::TyFnDef(_, substs) => { self.add_substs(substs); - self.add_fn_sig(f); } &ty::TyFnPtr(f) => { diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 09a3bcd0613..b9896e0cecf 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -348,7 +348,7 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option { .filter_map(|ty| characteristic_def_id_of_type(ty)) .next(), - ty::TyFnDef(def_id, ..) | + ty::TyFnDef(def_id, _) | ty::TyClosure(def_id, _) => Some(def_id), ty::TyBool | diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 12af56d5c3d..e1aa89078a3 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1220,12 +1220,16 @@ impl<'a, 'tcx> Layout { } ty::TyTuple(tys, _) => { - // FIXME(camlorn): if we ever allow unsized tuples, this needs to be checked. - // See the univariant case below to learn how. + let kind = if tys.len() == 0 { + StructKind::AlwaysSizedUnivariant + } else { + StructKind::MaybeUnsizedUnivariant + }; + let st = Struct::new(dl, &tys.iter().map(|ty| ty.layout(tcx, param_env)) .collect::, _>>()?, - &ReprOptions::default(), StructKind::AlwaysSizedUnivariant, ty)?; + &ReprOptions::default(), kind, ty)?; Univariant { variant: st, non_zero: false } } diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index 524cf57472b..a6c59d4c223 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -875,13 +875,12 @@ define_maps! { <'tcx> /// for trans. This is also the only query that can fetch non-local MIR, at present. [] optimized_mir: Mir(DefId) -> &'tcx mir::Mir<'tcx>, - /// Records the type of each closure. The def ID is the ID of the + /// Type of each closure. The def ID is the ID of the /// expression defining the closure. [] closure_kind: ItemSignature(DefId) -> ty::ClosureKind, - /// Records the type of each closure. The def ID is the ID of the - /// expression defining the closure. - [] closure_type: ItemSignature(DefId) -> ty::PolyFnSig<'tcx>, + /// The signature of functions and closures. + [] fn_sig: ItemSignature(DefId) -> ty::PolyFnSig<'tcx>, /// Caches CoerceUnsized kinds for impls on custom types. [] coerce_unsized_info: ItemSignature(DefId) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 13e46a265c6..548ee7bcbe5 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -206,7 +206,7 @@ impl AssociatedItem { // late-bound regions, and we don't want method signatures to show up // `as for<'r> fn(&'r MyType)`. Pretty-printing handles late-bound // regions just fine, showing `fn(&MyType)`. - format!("{}", tcx.type_of(self.def_id).fn_sig().skip_binder()) + format!("{}", tcx.fn_sig(self.def_id).skip_binder()) } ty::AssociatedKind::Type => format!("type {};", self.name.to_string()), ty::AssociatedKind::Const => { @@ -481,6 +481,18 @@ impl<'tcx> TyS<'tcx> { _ => false, } } + + pub fn is_suggestable(&self) -> bool { + match self.sty { + TypeVariants::TyAnon(..) | + TypeVariants::TyFnDef(..) | + TypeVariants::TyFnPtr(..) | + TypeVariants::TyDynamic(..) | + TypeVariants::TyClosure(..) | + TypeVariants::TyProjection(..) => false, + _ => true, + } + } } impl<'a, 'gcx, 'tcx> HashStable> for ty::TyS<'tcx> { diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index d4f06a902ee..2e9780572c9 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -291,7 +291,7 @@ impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> { if a.def_id != b.def_id { Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id))) } else { - let substs = relation.relate_item_substs(a.def_id, a.substs, b.substs)?; + let substs = relate_substs(relation, None, a.substs, b.substs)?; Ok(ty::TraitRef { def_id: a.def_id, substs: substs }) } } @@ -308,7 +308,7 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> { if a.def_id != b.def_id { Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id))) } else { - let substs = relation.relate_item_substs(a.def_id, a.substs, b.substs)?; + let substs = relate_substs(relation, None, a.substs, b.substs)?; Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs: substs }) } } @@ -440,13 +440,11 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, } } - (&ty::TyFnDef(a_def_id, a_substs, a_fty), - &ty::TyFnDef(b_def_id, b_substs, b_fty)) + (&ty::TyFnDef(a_def_id, a_substs), &ty::TyFnDef(b_def_id, b_substs)) if a_def_id == b_def_id => { - let substs = relate_substs(relation, None, a_substs, b_substs)?; - let fty = relation.relate(&a_fty, &b_fty)?; - Ok(tcx.mk_fn_def(a_def_id, substs, fty)) + let substs = relation.relate_item_substs(a_def_id, a_substs, b_substs)?; + Ok(tcx.mk_fn_def(a_def_id, substs)) } (&ty::TyFnPtr(a_fty), &ty::TyFnPtr(b_fty)) => diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 1e268924390..d05262965d7 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -531,10 +531,8 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { ty::TyDynamic(ref trait_ty, ref region) => ty::TyDynamic(trait_ty.fold_with(folder), region.fold_with(folder)), ty::TyTuple(ts, defaulted) => ty::TyTuple(ts.fold_with(folder), defaulted), - ty::TyFnDef(def_id, substs, f) => { - ty::TyFnDef(def_id, - substs.fold_with(folder), - f.fold_with(folder)) + ty::TyFnDef(def_id, substs) => { + ty::TyFnDef(def_id, substs.fold_with(folder)) } ty::TyFnPtr(f) => ty::TyFnPtr(f.fold_with(folder)), ty::TyRef(ref r, tm) => { @@ -568,9 +566,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { ty::TyDynamic(ref trait_ty, ref reg) => trait_ty.visit_with(visitor) || reg.visit_with(visitor), ty::TyTuple(ts, _) => ts.visit_with(visitor), - ty::TyFnDef(_, substs, ref f) => { - substs.visit_with(visitor) || f.visit_with(visitor) - } + ty::TyFnDef(_, substs) => substs.visit_with(visitor), ty::TyFnPtr(ref f) => f.visit_with(visitor), ty::TyRef(r, ref tm) => r.visit_with(visitor) || tm.visit_with(visitor), ty::TyClosure(_did, ref substs) => substs.visit_with(visitor), diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 6923a6d21d6..452775e9e13 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -14,7 +14,7 @@ use hir::def_id::DefId; use hir::map::DefPathHash; use middle::region; -use ty::subst::Substs; +use ty::subst::{Substs, Subst}; use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable}; use ty::{Slice, TyS}; use ty::subst::Kind; @@ -138,7 +138,7 @@ pub enum TypeVariants<'tcx> { /// The anonymous type of a function declaration/definition. Each /// function has a unique type. - TyFnDef(DefId, &'tcx Substs<'tcx>, PolyFnSig<'tcx>), + TyFnDef(DefId, &'tcx Substs<'tcx>), /// A pointer to a function. Written as `fn() -> i32`. TyFnPtr(PolyFnSig<'tcx>), @@ -990,6 +990,20 @@ impl RegionKind { flags } + + // This method returns whether the given Region is Named + pub fn is_named_region(&self) -> bool { + + match *self { + ty::ReFree(ref free_region) => { + match free_region.bound_region { + ty::BrNamed(..) => true, + _ => false, + } + } + _ => false, + } + } } /// Type utilities @@ -1329,9 +1343,12 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } - pub fn fn_sig(&self) -> PolyFnSig<'tcx> { + pub fn fn_sig(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> PolyFnSig<'tcx> { match self.sty { - TyFnDef(.., f) | TyFnPtr(f) => f, + TyFnDef(def_id, substs) => { + tcx.fn_sig(def_id).subst(tcx, substs) + } + TyFnPtr(f) => f, _ => bug!("Ty::fn_sig() called on non-fn type: {:?}", self) } } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 1bbc7673485..df4bbad3859 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -317,15 +317,26 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { target: Ty<'tcx>) -> (Ty<'tcx>, Ty<'tcx>) { let (mut a, mut b) = (source, target); - while let (&TyAdt(a_def, a_substs), &TyAdt(b_def, b_substs)) = (&a.sty, &b.sty) { - if a_def != b_def || !a_def.is_struct() { - break; - } - match a_def.struct_variant().fields.last() { - Some(f) => { - a = f.ty(self, a_substs); - b = f.ty(self, b_substs); - } + loop { + match (&a.sty, &b.sty) { + (&TyAdt(a_def, a_substs), &TyAdt(b_def, b_substs)) + if a_def == b_def && a_def.is_struct() => { + if let Some(f) = a_def.struct_variant().fields.last() { + a = f.ty(self, a_substs); + b = f.ty(self, b_substs); + } else { + break; + } + }, + (&TyTuple(a_tys, _), &TyTuple(b_tys, _)) + if a_tys.len() == b_tys.len() => { + if let Some(a_last) = a_tys.last() { + a = a_last; + b = b_tys.last().unwrap(); + } else { + break; + } + }, _ => break, } } @@ -679,7 +690,7 @@ impl<'a, 'gcx, 'tcx, W> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx, W> TyRef(_, m) => self.hash(m.mutbl), TyClosure(def_id, _) | TyAnon(def_id, _) | - TyFnDef(def_id, ..) => self.def_id(def_id), + TyFnDef(def_id, _) => self.def_id(def_id), TyAdt(d, _) => self.def_id(d.did), TyFnPtr(f) => { self.hash(f.unsafety()); diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index d7954953aba..71844abfe53 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -115,9 +115,8 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) { ty::TyTuple(ts, _) => { stack.extend(ts.iter().cloned().rev()); } - ty::TyFnDef(_, substs, ft) => { + ty::TyFnDef(_, substs) => { stack.extend(substs.types().rev()); - push_sig_subtypes(stack, ft); } ty::TyFnPtr(ft) => { push_sig_subtypes(stack, ft); diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 1fa63577196..eb6bffc29c5 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -753,8 +753,14 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { } write!(f, ")") } - TyFnDef(def_id, substs, ref bare_fn) => { - write!(f, "{} {{", bare_fn.0)?; + TyFnDef(def_id, substs) => { + ty::tls::with(|tcx| { + let mut sig = tcx.fn_sig(def_id); + if let Some(substs) = tcx.lift(&substs) { + sig = sig.subst(tcx, substs); + } + write!(f, "{} {{", sig.0) + })?; parameterized(f, substs, def_id, &[])?; write!(f, "}}") } diff --git a/src/librustc_asan/build.rs b/src/librustc_asan/build.rs index 3a80baa0485..cb7721affe7 100644 --- a/src/librustc_asan/build.rs +++ b/src/librustc_asan/build.rs @@ -32,4 +32,5 @@ fn main() { .build_target("asan") .build(); } + println!("cargo:rerun-if-env-changed=LLVM_CONFIG"); } diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index c72bdd04011..3be7c43cab9 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -18,8 +18,6 @@ pub use self::bckerr_code::*; pub use self::AliasableViolationKind::*; pub use self::MovedValueUseKind::*; -pub use self::mir::elaborate_drops::ElaborateDrops; - use self::InteriorKind::*; use rustc::hir::map as hir_map; @@ -55,8 +53,6 @@ pub mod gather_loans; pub mod move_data; -mod mir; - #[derive(Clone, Copy)] pub struct LoanDataFlowOperator; @@ -100,26 +96,21 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) { } let body_id = tcx.hir.body_owned_by(owner_id); - let attributes = tcx.get_attrs(owner_def_id); let tables = tcx.typeck_tables_of(owner_def_id); let region_maps = tcx.region_maps(owner_def_id); let mut bccx = &mut BorrowckCtxt { tcx, tables, region_maps, owner_def_id }; let body = bccx.tcx.hir.body(body_id); - if bccx.tcx.has_attr(owner_def_id, "rustc_mir_borrowck") { - mir::borrowck_mir(bccx, owner_id, &attributes); - } else { - // Eventually, borrowck will always read the MIR, but at the - // moment we do not. So, for now, we always force MIR to be - // constructed for a given fn, since this may result in errors - // being reported and we want that to happen. - // - // Note that `mir_validated` is a "stealable" result; the - // thief, `optimized_mir()`, forces borrowck, so we know that - // is not yet stolen. - tcx.mir_validated(owner_def_id).borrow(); - } + // Eventually, borrowck will always read the MIR, but at the + // moment we do not. So, for now, we always force MIR to be + // constructed for a given fn, since this may result in errors + // being reported and we want that to happen. + // + // Note that `mir_validated` is a "stealable" result; the + // thief, `optimized_mir()`, forces borrowck, so we know that + // is not yet stolen. + tcx.mir_validated(owner_def_id).borrow(); let cfg = cfg::CFG::new(bccx.tcx, &body); let AnalysisData { all_loans, diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs index 9c980ddf08a..a2b1e3c2663 100644 --- a/src/librustc_borrowck/lib.rs +++ b/src/librustc_borrowck/lib.rs @@ -21,7 +21,6 @@ #![feature(quote)] #![feature(rustc_diagnostic_macros)] #![feature(associated_consts)] -#![feature(nonzero)] #[macro_use] extern crate log; #[macro_use] extern crate syntax; @@ -39,7 +38,7 @@ extern crate core; // for NonZero pub use borrowck::check_crate; pub use borrowck::build_borrowck_dataflow_data_for_fn; -pub use borrowck::{AnalysisData, BorrowckCtxt, ElaborateDrops}; +pub use borrowck::{AnalysisData, BorrowckCtxt}; // NB: This module needs to be declared first so diagnostics are // registered before they are used. diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs index d175920e8a6..0a966b0c170 100644 --- a/src/librustc_const_eval/pattern.rs +++ b/src/librustc_const_eval/pattern.rs @@ -12,7 +12,7 @@ use eval; use rustc::middle::const_val::{ConstEvalErr, ConstVal}; use rustc::mir::{Field, BorrowKind, Mutability}; -use rustc::ty::{self, TyCtxt, AdtDef, Ty, TypeVariants, Region}; +use rustc::ty::{self, TyCtxt, AdtDef, Ty, Region}; use rustc::ty::subst::{Substs, Kind}; use rustc::hir::{self, PatKind, RangeEnd}; use rustc::hir::def::{Def, CtorKind}; @@ -549,8 +549,8 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { let adt_def = self.tcx.adt_def(enum_id); if adt_def.variants.len() > 1 { let substs = match ty.sty { - TypeVariants::TyAdt(_, substs) => substs, - TypeVariants::TyFnDef(_, substs, _) => substs, + ty::TyAdt(_, substs) | + ty::TyFnDef(_, substs) => substs, _ => bug!("inappropriate type for def: {:?}", ty.sty), }; PatternKind::Variant { diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 159fee6aa4c..a3e1cf7c1a8 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -13,7 +13,8 @@ use rustc::hir::lowering::lower_crate; use rustc::ich::Fingerprint; use rustc_data_structures::stable_hasher::StableHasher; use rustc_mir as mir; -use rustc::session::{Session, CompileResult, compile_result_from_err_count}; +use rustc::session::{Session, CompileResult}; +use rustc::session::CompileIncomplete; use rustc::session::config::{self, Input, OutputFilenames, OutputType, OutputTypes}; use rustc::session::search_paths::PathKind; @@ -23,7 +24,7 @@ use rustc::middle::privacy::AccessLevels; use rustc::mir::transform::{MIR_CONST, MIR_VALIDATED, MIR_OPTIMIZED, Passes}; use rustc::ty::{self, TyCtxt, Resolutions, GlobalArenas}; use rustc::traits; -use rustc::util::common::time; +use rustc::util::common::{ErrorReported, time}; use rustc::util::nodemap::NodeSet; use rustc::util::fs::rename_or_copy_remove; use rustc_borrowck as borrowck; @@ -78,7 +79,9 @@ pub fn compile_input(sess: &Session, } if control.$point.stop == Compilation::Stop { - return compile_result_from_err_count($tsess.err_count()); + // FIXME: shouldn't this return Err(CompileIncomplete::Stopped) + // if there are no errors? + return $tsess.compile_status(); } }} } @@ -91,7 +94,7 @@ pub fn compile_input(sess: &Session, Ok(krate) => krate, Err(mut parse_error) => { parse_error.emit(); - return Err(1); + return Err(CompileIncomplete::Errored(ErrorReported)); } }; @@ -194,7 +197,7 @@ pub fn compile_input(sess: &Session, (control.after_analysis.callback)(&mut state); if control.after_analysis.stop == Compilation::Stop { - return result.and_then(|_| Err(0usize)); + return result.and_then(|_| Err(CompileIncomplete::Stopped)); } } @@ -564,7 +567,7 @@ pub fn phase_2_configure_and_expand(sess: &Session, addl_plugins: Option>, make_glob_map: MakeGlobMap, after_expand: F) - -> Result + -> Result where F: FnOnce(&ast::Crate) -> CompileResult, { let time_passes = sess.time_passes(); @@ -636,7 +639,7 @@ pub fn phase_2_configure_and_expand(sess: &Session, // Lint plugins are registered; now we can process command line flags. if sess.opts.describe_lints { super::describe_lints(&sess.lint_store.borrow(), true); - return Err(0); + return Err(CompileIncomplete::Stopped); } sess.track_errors(|| sess.lint_store.borrow_mut().process_command_line(sess))?; @@ -839,7 +842,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, arenas: &'tcx GlobalArenas<'tcx>, name: &str, f: F) - -> Result + -> Result where F: for<'a> FnOnce(TyCtxt<'a, 'tcx, 'tcx>, ty::CrateAnalysis, IncrementalHashesMap, @@ -920,6 +923,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, // What we need to do constant evaluation. passes.push_pass(MIR_CONST, mir::transform::simplify::SimplifyCfg::new("initial")); passes.push_pass(MIR_CONST, mir::transform::type_check::TypeckMir); + passes.push_pass(MIR_CONST, mir::transform::rustc_peek::SanityCheck); // What we need to run borrowck etc. passes.push_pass(MIR_VALIDATED, mir::transform::qualify_consts::QualifyAndPromoteConstants); @@ -934,7 +938,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, // From here on out, regions are gone. passes.push_pass(MIR_OPTIMIZED, mir::transform::erase_regions::EraseRegions); passes.push_pass(MIR_OPTIMIZED, mir::transform::add_call_guards::AddCallGuards); - passes.push_pass(MIR_OPTIMIZED, borrowck::ElaborateDrops); + passes.push_pass(MIR_OPTIMIZED, mir::transform::elaborate_drops::ElaborateDrops); passes.push_pass(MIR_OPTIMIZED, mir::transform::no_landing_pads::NoLandingPads); passes.push_pass(MIR_OPTIMIZED, mir::transform::simplify::SimplifyCfg::new("elaborate-drops")); @@ -1018,7 +1022,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, Err(sess.err_count()))); + return Ok(f(tcx, analysis, incremental_hashes_map, sess.compile_status())); } analysis.reachable = @@ -1034,12 +1038,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, time(time_passes, "lint checking", || lint::check_crate(tcx)); - // The above three passes generate errors w/o aborting - if sess.err_count() > 0 { - return Ok(f(tcx, analysis, incremental_hashes_map, Err(sess.err_count()))); - } - - Ok(f(tcx, analysis, incremental_hashes_map, Ok(()))) + return Ok(f(tcx, analysis, incremental_hashes_map, tcx.sess.compile_status())); }) } @@ -1115,11 +1114,7 @@ pub fn phase_5_run_llvm_passes(sess: &Session, "serialize work products", move || rustc_incremental::save_work_products(sess)); - if sess.err_count() > 0 { - Err(sess.err_count()) - } else { - Ok(()) - } + sess.compile_status() } /// Run the linker on any artifacts that resulted from the LLVM run. diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 54e7c398fe6..802ed2a489b 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -67,6 +67,7 @@ use rustc_trans::back::link; use rustc_trans::back::write::{RELOC_MODEL_ARGS, CODE_GEN_MODEL_ARGS}; use rustc::dep_graph::DepGraph; use rustc::session::{self, config, Session, build_session, CompileResult}; +use rustc::session::CompileIncomplete; use rustc::session::config::{Input, PrintRequest, OutputType, ErrorOutputType}; use rustc::session::config::nightly_options; use rustc::session::{early_error, early_warn}; @@ -74,7 +75,7 @@ use rustc::lint::Lint; use rustc::lint; use rustc_metadata::locator; use rustc_metadata::cstore::CStore; -use rustc::util::common::time; +use rustc::util::common::{time, ErrorReported}; use serialize::json::ToJson; @@ -83,10 +84,11 @@ use std::cmp::max; use std::cmp::Ordering::Equal; use std::default::Default; use std::env; +use std::ffi::OsString; use std::io::{self, Read, Write}; use std::iter::repeat; use std::path::PathBuf; -use std::process; +use std::process::{self, Command, Stdio}; use std::rc::Rc; use std::str; use std::sync::{Arc, Mutex}; @@ -109,18 +111,14 @@ mod derive_registrar; const BUG_REPORT_URL: &'static str = "https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.\ md#bug-reports"; -#[inline] -fn abort_msg(err_count: usize) -> String { - match err_count { - 0 => "aborting with no errors (maybe a bug?)".to_owned(), - _ => "aborting due to previous error(s)".to_owned(), - } -} - -pub fn abort_on_err(result: Result, sess: &Session) -> T { +pub fn abort_on_err(result: Result, sess: &Session) -> T { match result { - Err(err_count) => { - sess.fatal(&abort_msg(err_count)); + Err(CompileIncomplete::Errored(ErrorReported)) => { + sess.abort_if_errors(); + panic!("error reported but abort_if_errors didn't abort???"); + } + Err(CompileIncomplete::Stopped) => { + sess.fatal("compilation terminated"); } Ok(x) => x, } @@ -131,19 +129,20 @@ pub fn run(run_compiler: F) -> isize { monitor(move || { let (result, session) = run_compiler(); - if let Err(err_count) = result { - if err_count > 0 { - match session { - Some(sess) => sess.fatal(&abort_msg(err_count)), - None => { - let emitter = - errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto, None); - let handler = errors::Handler::with_emitter(true, false, Box::new(emitter)); - handler.emit(&MultiSpan::new(), - &abort_msg(err_count), - errors::Level::Fatal); - exit_on_err(); - } + if let Err(CompileIncomplete::Errored(_)) = result { + match session { + Some(sess) => { + sess.abort_if_errors(); + panic!("error reported but abort_if_errors didn't abort???"); + } + None => { + let emitter = + errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto, None); + let handler = errors::Handler::with_emitter(true, false, Box::new(emitter)); + handler.emit(&MultiSpan::new(), + "aborting due to previous error(s)", + errors::Level::Fatal); + exit_on_err(); } } } @@ -345,6 +344,31 @@ pub trait CompilerCalls<'a> { #[derive(Copy, Clone)] pub struct RustcDefaultCalls; +// FIXME remove these and use winapi 0.3 instead +// Duplicates: bootstrap/compile.rs, librustc_errors/emitter.rs +#[cfg(unix)] +fn stdout_isatty() -> bool { + unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 } +} + +#[cfg(windows)] +fn stdout_isatty() -> bool { + type DWORD = u32; + type BOOL = i32; + type HANDLE = *mut u8; + type LPDWORD = *mut u32; + const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD; + extern "system" { + fn GetStdHandle(which: DWORD) -> HANDLE; + fn GetConsoleMode(hConsoleHandle: HANDLE, lpMode: LPDWORD) -> BOOL; + } + unsafe { + let handle = GetStdHandle(STD_OUTPUT_HANDLE); + let mut out = 0; + GetConsoleMode(handle, &mut out) != 0 + } +} + fn handle_explain(code: &str, descriptions: &errors::registry::Registry, output: ErrorOutputType) { @@ -356,6 +380,8 @@ fn handle_explain(code: &str, match descriptions.find_description(&normalised) { Some(ref description) => { let mut is_in_code_block = false; + let mut text = String::new(); + // Slice off the leading newline and print. for line in description[1..].lines() { let indent_level = line.find(|c: char| !c.is_whitespace()) @@ -363,12 +389,19 @@ fn handle_explain(code: &str, let dedented_line = &line[indent_level..]; if dedented_line.starts_with("```") { is_in_code_block = !is_in_code_block; - println!("{}", &line[..(indent_level+3)]); + text.push_str(&line[..(indent_level+3)]); } else if is_in_code_block && dedented_line.starts_with("# ") { continue; } else { - println!("{}", line); + text.push_str(line); } + text.push('\n'); + } + + if stdout_isatty() { + show_content_with_pager(&text); + } else { + print!("{}", text); } } None => { @@ -377,6 +410,39 @@ fn handle_explain(code: &str, } } +fn show_content_with_pager(content: &String) { + let pager_name = env::var_os("PAGER").unwrap_or_else(|| if cfg!(windows) { + OsString::from("more.com") + } else { + OsString::from("less") + }); + + let mut fallback_to_println = false; + + match Command::new(pager_name).stdin(Stdio::piped()).spawn() { + Ok(mut pager) => { + if let Some(mut pipe) = pager.stdin.as_mut() { + if pipe.write_all(content.as_bytes()).is_err() { + fallback_to_println = true; + } + } + + if pager.wait().is_err() { + fallback_to_println = true; + } + } + Err(_) => { + fallback_to_println = true; + } + } + + // If pager fails for whatever reason, we should still print the content + // to standard output + if fallback_to_println { + print!("{}", content); + } +} + impl<'a> CompilerCalls<'a> for RustcDefaultCalls { fn early_callback(&mut self, matches: &getopts::Matches, diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 2d25d12d3a9..4b71aa6b85f 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -47,7 +47,12 @@ impl Emitter for EmitterWriter { // don't display multiline suggestions as labels sugg.substitution_parts[0].substitutions[0].find('\n').is_none() { let substitution = &sugg.substitution_parts[0].substitutions[0]; - let msg = format!("help: {} `{}`", sugg.msg, substitution); + let msg = if substitution.len() == 0 { + // This substitution is only removal, don't show it + format!("help: {}", sugg.msg) + } else { + format!("help: {} `{}`", sugg.msg, substitution) + }; primary_span.push_span_label(sugg.substitution_spans().next().unwrap(), msg); } else { // if there are multiple suggestions, print them all in full diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index ada1c632bc0..dd25f969414 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -506,7 +506,10 @@ impl Handler { return; } - _ => s = "aborting due to previous error(s)".to_string(), + 1 => s = "aborting due to previous error".to_string(), + _ => { + s = format!("aborting due to {} previous errors", self.err_count.get()); + } } panic!(self.fatal(&s)); diff --git a/src/librustc_incremental/lib.rs b/src/librustc_incremental/lib.rs index 5bd7a24bdaf..ac3149b90b8 100644 --- a/src/librustc_incremental/lib.rs +++ b/src/librustc_incremental/lib.rs @@ -20,7 +20,6 @@ #![feature(rand)] #![feature(conservative_impl_trait)] -#![feature(sort_unstable)] extern crate graphviz; #[macro_use] extern crate rustc; diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 9800012917c..2b331509025 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -684,13 +684,9 @@ fn fl_lit_check_expr(cx: &EarlyContext, expr: &ast::Expr) { // These may occur in patterns // and can maybe contain float literals ExprKind::Unary(_, ref f) => fl_lit_check_expr(cx, f), - // These may occur in patterns - // and can't contain float literals - ExprKind::Path(..) => (), - // If something unhandled is encountered, we need to expand the - // search or ignore more ExprKinds. - _ => span_bug!(expr.span, "Unhandled expression {:?} in float lit pattern lint", - expr.node), + // Other kinds of exprs can't occur in patterns so we don't have to check them + // (ast_validation will emit an error if they occur) + _ => (), } } @@ -1154,24 +1150,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes { if !def_id_is_transmute(cx, did) { return None; } - let typ = cx.tables.node_id_to_type(expr.id); - match typ.sty { - ty::TyFnDef(.., bare_fn) if bare_fn.abi() == RustIntrinsic => { - let from = bare_fn.inputs().skip_binder()[0]; - let to = *bare_fn.output().skip_binder(); - return Some((&from.sty, &to.sty)); - } - _ => (), - } + let sig = cx.tables.node_id_to_type(expr.id).fn_sig(cx.tcx); + let from = sig.inputs().skip_binder()[0]; + let to = *sig.output().skip_binder(); + return Some((&from.sty, &to.sty)); } None } fn def_id_is_transmute(cx: &LateContext, def_id: DefId) -> bool { - match cx.tcx.type_of(def_id).sty { - ty::TyFnDef(.., bfty) if bfty.abi() == RustIntrinsic => (), - _ => return false, - } + cx.tcx.fn_sig(def_id).abi() == RustIntrinsic && cx.tcx.item_name(def_id) == "transmute" } } diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 32bde42b526..ac3977bd216 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -659,7 +659,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { fn check_foreign_fn(&mut self, id: ast::NodeId, decl: &hir::FnDecl) { let def_id = self.cx.tcx.hir.local_def_id(id); - let sig = self.cx.tcx.type_of(def_id).fn_sig(); + let sig = self.cx.tcx.fn_sig(def_id); let sig = self.cx.tcx.erase_late_bound_regions(&sig); for (input_ty, input_hir) in sig.inputs().iter().zip(&decl.inputs) { diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index 01b37a55f4f..3f0f5369607 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -60,11 +60,7 @@ fn main() { }); println!("cargo:rerun-if-changed={}", llvm_config.display()); - - if let Some(cfg_toml) = env::var_os("CFG_LLVM_TOML") { - let cfg_path = PathBuf::from(cfg_toml); - println!("cargo:rerun-if-changed={}", cfg_path.display()); - } + println!("cargo:rerun-if-env-changed=LLVM_CONFIG"); // Test whether we're cross-compiling LLVM. This is a pretty rare case // currently where we're producing an LLVM for a different platform than diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs index 312b5a38d6e..770d16e5c02 100644 --- a/src/librustc_llvm/ffi.rs +++ b/src/librustc_llvm/ffi.rs @@ -1597,7 +1597,13 @@ extern "C" { Output: *const c_char, FileType: FileType) -> LLVMRustResult; - pub fn LLVMRustPrintModule(PM: PassManagerRef, M: ModuleRef, Output: *const c_char); + pub fn LLVMRustPrintModule(PM: PassManagerRef, + M: ModuleRef, + Output: *const c_char, + Demangle: extern fn(*const c_char, + size_t, + *mut c_char, + size_t) -> size_t); pub fn LLVMRustSetLLVMOptions(Argc: c_int, Argv: *const *const c_char); pub fn LLVMRustPrintPasses(); pub fn LLVMRustSetNormalizedTarget(M: ModuleRef, triple: *const c_char); diff --git a/src/librustc_lsan/build.rs b/src/librustc_lsan/build.rs index da53571a243..3d2ae480de6 100644 --- a/src/librustc_lsan/build.rs +++ b/src/librustc_lsan/build.rs @@ -32,4 +32,5 @@ fn main() { .build_target("lsan") .build(); } + println!("cargo:rerun-if-env-changed=LLVM_CONFIG"); } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index ff5febadeb7..54138e2e3b0 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -107,7 +107,7 @@ provide! { <'tcx> tcx, def_id, cdata, mir_const_qualif => { cdata.mir_const_qualif(def_id.index) } typeck_tables_of => { cdata.item_body_tables(def_id.index, tcx) } closure_kind => { cdata.closure_kind(def_id.index) } - closure_type => { cdata.closure_ty(def_id.index, tcx) } + fn_sig => { cdata.fn_sig(def_id.index, tcx) } inherent_impls => { Rc::new(cdata.get_inherent_implementations_for_type(def_id.index)) } is_const_fn => { cdata.is_const_fn(def_id.index) } is_foreign_item => { cdata.is_foreign_item(def_id.index) } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index b974541ef25..ad3a9dd9fef 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -1084,14 +1084,20 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn closure_ty(&self, - closure_id: DefIndex, - tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> ty::PolyFnSig<'tcx> { - match self.entry(closure_id).kind { - EntryKind::Closure(data) => data.decode(self).ty.decode((self, tcx)), + pub fn fn_sig(&self, + id: DefIndex, + tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> ty::PolyFnSig<'tcx> { + let sig = match self.entry(id).kind { + EntryKind::Fn(data) | + EntryKind::ForeignFn(data) => data.decode(self).sig, + EntryKind::Method(data) => data.decode(self).fn_data.sig, + EntryKind::Variant(data) | + EntryKind::Struct(data, _) => data.decode(self).ctor_sig.unwrap(), + EntryKind::Closure(data) => data.decode(self).sig, _ => bug!(), - } + }; + sig.decode((self, tcx)) } #[inline] diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 63a24c7db18..f74aac255a0 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -16,6 +16,7 @@ use schema::*; use rustc::middle::cstore::{LinkMeta, LinkagePreference, NativeLibrary, EncodedMetadata, EncodedMetadataHashes, EncodedMetadataHash}; +use rustc::hir::def::CtorKind; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LOCAL_CRATE}; use rustc::hir::map::definitions::{DefPathTable, GlobalMetaDataKind}; use rustc::ich::Fingerprint; @@ -499,6 +500,11 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { ctor_kind: variant.ctor_kind, discr: variant.discr, struct_ctor: None, + ctor_sig: if variant.ctor_kind == CtorKind::Fn { + Some(self.lazy(&tcx.fn_sig(def_id))) + } else { + None + } }; let enum_id = tcx.hir.as_local_node_id(enum_did).unwrap(); @@ -518,7 +524,11 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { ty: Some(self.encode_item_type(def_id)), inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), + variances: if variant.ctor_kind == CtorKind::Fn { + self.encode_variances_of(def_id) + } else { + LazySeq::empty() + }, generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), @@ -617,6 +627,11 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { ctor_kind: variant.ctor_kind, discr: variant.discr, struct_ctor: Some(def_id.index), + ctor_sig: if variant.ctor_kind == CtorKind::Fn { + Some(self.lazy(&tcx.fn_sig(def_id))) + } else { + None + } }; let struct_id = tcx.hir.as_local_node_id(adt_def_id).unwrap(); @@ -641,7 +656,11 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { ty: Some(self.encode_item_type(def_id)), inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), + variances: if variant.ctor_kind == CtorKind::Fn { + self.encode_variances_of(def_id) + } else { + LazySeq::empty() + }, generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), @@ -695,7 +714,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { }; FnData { constness: hir::Constness::NotConst, - arg_names: arg_names + arg_names: arg_names, + sig: self.lazy(&tcx.fn_sig(def_id)), } } else { bug!() @@ -732,7 +752,11 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } }, inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), + variances: if trait_item.kind == ty::AssociatedKind::Method { + self.encode_variances_of(def_id) + } else { + LazySeq::empty() + }, generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), @@ -747,6 +771,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> { debug!("IsolatedEncoder::encode_info_for_impl_item({:?})", def_id); + let tcx = self.tcx; + let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap(); let ast_item = self.tcx.hir.expect_impl_item(node_id); let impl_item = self.tcx.associated_item(def_id); @@ -768,6 +794,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { FnData { constness: sig.constness, arg_names: self.encode_fn_arg_names_for_body(body), + sig: self.lazy(&tcx.fn_sig(def_id)), } } else { bug!() @@ -806,7 +833,11 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { ty: Some(self.encode_item_type(def_id)), inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), + variances: if impl_item.kind == ty::AssociatedKind::Method { + self.encode_variances_of(def_id) + } else { + LazySeq::empty() + }, generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), @@ -881,6 +912,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { let data = FnData { constness: constness, arg_names: self.encode_fn_arg_names_for_body(body), + sig: self.lazy(&tcx.fn_sig(def_id)), }; EntryKind::Fn(self.lazy(&data)) @@ -910,6 +942,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { ctor_kind: variant.ctor_kind, discr: variant.discr, struct_ctor: struct_ctor, + ctor_sig: None, }), repr_options) } hir::ItemUnion(..) => { @@ -920,6 +953,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { ctor_kind: variant.ctor_kind, discr: variant.discr, struct_ctor: None, + ctor_sig: None, }), repr_options) } hir::ItemDefaultImpl(..) => { @@ -1037,7 +1071,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { hir::ItemEnum(..) | hir::ItemStruct(..) | hir::ItemUnion(..) | - hir::ItemTrait(..) => self.encode_variances_of(def_id), + hir::ItemFn(..) => self.encode_variances_of(def_id), _ => LazySeq::empty(), }, generics: match item.node { @@ -1176,7 +1210,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { let data = ClosureData { kind: tcx.closure_kind(def_id), - ty: self.lazy(&tcx.closure_type(def_id)), + sig: self.lazy(&tcx.fn_sig(def_id)), }; Entry { @@ -1364,6 +1398,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { let data = FnData { constness: hir::Constness::NotConst, arg_names: self.encode_fn_arg_names(names), + sig: self.lazy(&tcx.fn_sig(def_id)), }; EntryKind::ForeignFn(self.lazy(&data)) } @@ -1382,7 +1417,10 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { ty: Some(self.encode_item_type(def_id)), inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), + variances: match nitem.node { + hir::ForeignItemFn(..) => self.encode_variances_of(def_id), + _ => LazySeq::empty(), + }, generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index 12997f24c74..99b718ea07b 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -26,7 +26,6 @@ #![feature(specialization)] #![feature(discriminant_value)] #![feature(rustc_private)] -#![feature(sort_unstable)] #[macro_use] extern crate log; diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 1337f90efa7..9ef5b940830 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -343,18 +343,18 @@ pub enum EntryKind<'tcx> { Type, Enum(ReprOptions), Field, - Variant(Lazy), - Struct(Lazy, ReprOptions), - Union(Lazy, ReprOptions), - Fn(Lazy), - ForeignFn(Lazy), + Variant(Lazy>), + Struct(Lazy>, ReprOptions), + Union(Lazy>, ReprOptions), + Fn(Lazy>), + ForeignFn(Lazy>), Mod(Lazy), MacroDef(Lazy), Closure(Lazy>), Trait(Lazy>), Impl(Lazy>), DefaultImpl(Lazy>), - Method(Lazy), + Method(Lazy>), AssociatedType(AssociatedContainer), AssociatedConst(AssociatedContainer, u8), } @@ -439,27 +439,33 @@ pub struct MacroDef { impl_stable_hash_for!(struct MacroDef { body, legacy }); #[derive(RustcEncodable, RustcDecodable)] -pub struct FnData { +pub struct FnData<'tcx> { pub constness: hir::Constness, pub arg_names: LazySeq, + pub sig: Lazy>, } -impl_stable_hash_for!(struct FnData { constness, arg_names }); +impl_stable_hash_for!(struct FnData<'tcx> { constness, arg_names, sig }); #[derive(RustcEncodable, RustcDecodable)] -pub struct VariantData { +pub struct VariantData<'tcx> { pub ctor_kind: CtorKind, pub discr: ty::VariantDiscr, /// If this is a struct's only variant, this /// is the index of the "struct ctor" item. pub struct_ctor: Option, + + /// If this is a tuple struct or variant + /// ctor, this is its "function" signature. + pub ctor_sig: Option>>, } -impl_stable_hash_for!(struct VariantData { +impl_stable_hash_for!(struct VariantData<'tcx> { ctor_kind, discr, - struct_ctor + struct_ctor, + ctor_sig }); #[derive(RustcEncodable, RustcDecodable)] @@ -543,16 +549,16 @@ impl AssociatedContainer { } #[derive(RustcEncodable, RustcDecodable)] -pub struct MethodData { - pub fn_data: FnData, +pub struct MethodData<'tcx> { + pub fn_data: FnData<'tcx>, pub container: AssociatedContainer, pub has_self: bool, } -impl_stable_hash_for!(struct MethodData { fn_data, container, has_self }); +impl_stable_hash_for!(struct MethodData<'tcx> { fn_data, container, has_self }); #[derive(RustcEncodable, RustcDecodable)] pub struct ClosureData<'tcx> { pub kind: ty::ClosureKind, - pub ty: Lazy>, + pub sig: Lazy>, } -impl_stable_hash_for!(struct ClosureData<'tcx> { kind, ty }); +impl_stable_hash_for!(struct ClosureData<'tcx> { kind, sig }); diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index b7abc707a38..326c1df69eb 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -205,11 +205,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // FIXME(canndrew): This is_never should probably be an is_uninhabited let diverges = expr.ty.is_never(); let intrinsic = match ty.sty { - ty::TyFnDef(def_id, _, ref f) if - f.abi() == Abi::RustIntrinsic || - f.abi() == Abi::PlatformIntrinsic => - { - Some(this.hir.tcx().item_name(def_id).as_str()) + ty::TyFnDef(def_id, _) => { + let f = ty.fn_sig(this.hir.tcx()); + if f.abi() == Abi::RustIntrinsic || + f.abi() == Abi::PlatformIntrinsic { + Some(this.hir.tcx().item_name(def_id).as_str()) + } else { + None + } } _ => None }; diff --git a/src/librustc_borrowck/borrowck/mir/mod.rs b/src/librustc_mir/dataflow/drop_flag_effects.rs similarity index 67% rename from src/librustc_borrowck/borrowck/mir/mod.rs rename to src/librustc_mir/dataflow/drop_flag_effects.rs index e3b99b9d4bd..daafbecc5df 100644 --- a/src/librustc_borrowck/borrowck/mir/mod.rs +++ b/src/librustc_mir/dataflow/drop_flag_effects.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-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,33 +8,24 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use borrowck::BorrowckCtxt; - use syntax::ast::{self, MetaItem}; use syntax_pos::DUMMY_SP; -use rustc::mir::{self, BasicBlock, BasicBlockData, Mir, Statement, Terminator, Location}; + +use rustc::mir::{self, Mir, BasicBlock, Location}; use rustc::session::Session; use rustc::ty::{self, TyCtxt}; -use rustc_mir::util::elaborate_drops::DropFlagState; -use rustc_data_structures::indexed_set::{IdxSet, IdxSetBuf}; - -mod abs_domain; -pub mod elaborate_drops; -mod dataflow; -mod gather_moves; -// mod graphviz; - -use self::dataflow::{BitDenotation}; -use self::dataflow::{DataflowOperator}; -use self::dataflow::{Dataflow, DataflowAnalysis, DataflowResults}; -use self::dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals}; -use self::dataflow::{DefinitelyInitializedLvals}; -use self::gather_moves::{HasMoveData, MoveData, MovePathIndex, LookupResult}; +use util::elaborate_drops::DropFlagState; +use rustc_data_structures::indexed_set::{IdxSet}; use std::fmt; -fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option { +use super::{Dataflow, DataflowBuilder, DataflowAnalysis}; +use super::{BitDenotation, DataflowOperator, DataflowResults}; +use super::indexes::MovePathIndex; +use super::move_paths::{MoveData, LookupResult}; + +pub(crate) fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option { for attr in attrs { if attr.check_name("rustc_mir") { let items = attr.meta_item_list(); @@ -50,69 +41,11 @@ fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option } pub struct MoveDataParamEnv<'tcx> { - move_data: MoveData<'tcx>, - param_env: ty::ParamEnv<'tcx>, + pub(crate) move_data: MoveData<'tcx>, + pub(crate) param_env: ty::ParamEnv<'tcx>, } -pub fn borrowck_mir(bcx: &mut BorrowckCtxt, - id: ast::NodeId, - attributes: &[ast::Attribute]) { - let tcx = bcx.tcx; - let def_id = tcx.hir.local_def_id(id); - debug!("borrowck_mir({:?}) UNIMPLEMENTED", def_id); - - // It is safe for us to borrow `mir_validated()`: `optimized_mir` - // steals it, but it forces the `borrowck` query. - let mir = &tcx.mir_validated(def_id).borrow(); - - let param_env = tcx.param_env(def_id); - let move_data = MoveData::gather_moves(mir, tcx, param_env); - let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env }; - let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len()); - let flow_inits = - do_dataflow(tcx, mir, id, attributes, &dead_unwinds, - MaybeInitializedLvals::new(tcx, mir, &mdpe), - |bd, i| &bd.move_data().move_paths[i]); - let flow_uninits = - do_dataflow(tcx, mir, id, attributes, &dead_unwinds, - MaybeUninitializedLvals::new(tcx, mir, &mdpe), - |bd, i| &bd.move_data().move_paths[i]); - let flow_def_inits = - do_dataflow(tcx, mir, id, attributes, &dead_unwinds, - DefinitelyInitializedLvals::new(tcx, mir, &mdpe), - |bd, i| &bd.move_data().move_paths[i]); - - if has_rustc_mir_with(attributes, "rustc_peek_maybe_init").is_some() { - dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &flow_inits); - } - if has_rustc_mir_with(attributes, "rustc_peek_maybe_uninit").is_some() { - dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &flow_uninits); - } - if has_rustc_mir_with(attributes, "rustc_peek_definite_init").is_some() { - dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &flow_def_inits); - } - - if has_rustc_mir_with(attributes, "stop_after_dataflow").is_some() { - bcx.tcx.sess.fatal("stop_after_dataflow ended compilation"); - } - - let mut mbcx = MirBorrowckCtxt { - bcx: bcx, - mir: mir, - node_id: id, - move_data: &mdpe.move_data, - flow_inits: flow_inits, - flow_uninits: flow_uninits, - }; - - for bb in mir.basic_blocks().indices() { - mbcx.process_basic_block(bb); - } - - debug!("borrowck_mir done"); -} - -fn do_dataflow<'a, 'tcx, BD, P>(tcx: TyCtxt<'a, 'tcx, 'tcx>, +pub(crate) fn do_dataflow<'a, 'tcx, BD, P>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &Mir<'tcx>, node_id: ast::NodeId, attributes: &[ast::Attribute], @@ -142,7 +75,7 @@ fn do_dataflow<'a, 'tcx, BD, P>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let print_postflow_to = name_found(tcx.sess, attributes, "borrowck_graphviz_postflow"); - let mut mbcx = MirBorrowckCtxtPreDataflow { + let mut mbcx = DataflowBuilder { node_id: node_id, print_preflow_to: print_preflow_to, print_postflow_to: print_postflow_to, @@ -153,46 +86,7 @@ fn do_dataflow<'a, 'tcx, BD, P>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mbcx.flow_state.results() } - -pub struct MirBorrowckCtxtPreDataflow<'a, 'tcx: 'a, BD> where BD: BitDenotation -{ - node_id: ast::NodeId, - flow_state: DataflowAnalysis<'a, 'tcx, BD>, - print_preflow_to: Option, - print_postflow_to: Option, -} - -#[allow(dead_code)] -pub struct MirBorrowckCtxt<'b, 'a: 'b, 'tcx: 'a> { - bcx: &'b mut BorrowckCtxt<'a, 'tcx>, - mir: &'b Mir<'tcx>, - node_id: ast::NodeId, - move_data: &'b MoveData<'tcx>, - flow_inits: DataflowResults>, - flow_uninits: DataflowResults> -} - -impl<'b, 'a: 'b, 'tcx: 'a> MirBorrowckCtxt<'b, 'a, 'tcx> { - fn process_basic_block(&mut self, bb: BasicBlock) { - let BasicBlockData { ref statements, ref terminator, is_cleanup: _ } = - self.mir[bb]; - for stmt in statements { - self.process_statement(bb, stmt); - } - - self.process_terminator(bb, terminator); - } - - fn process_statement(&mut self, bb: BasicBlock, stmt: &Statement<'tcx>) { - debug!("MirBorrowckCtxt::process_statement({:?}, {:?}", bb, stmt); - } - - fn process_terminator(&mut self, bb: BasicBlock, term: &Option>) { - debug!("MirBorrowckCtxt::process_terminator({:?}, {:?})", bb, term); - } -} - -fn move_path_children_matching<'tcx, F>(move_data: &MoveData<'tcx>, +pub fn move_path_children_matching<'tcx, F>(move_data: &MoveData<'tcx>, path: MovePathIndex, mut cond: F) -> Option @@ -253,7 +147,7 @@ fn lvalue_contents_drop_state_cannot_differ<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx } } -fn on_lookup_result_bits<'a, 'tcx, F>( +pub(crate) fn on_lookup_result_bits<'a, 'tcx, F>( tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &Mir<'tcx>, move_data: &MoveData<'tcx>, @@ -271,7 +165,7 @@ fn on_lookup_result_bits<'a, 'tcx, F>( } } -fn on_all_children_bits<'a, 'tcx, F>( +pub(crate) fn on_all_children_bits<'a, 'tcx, F>( tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &Mir<'tcx>, move_data: &MoveData<'tcx>, @@ -312,7 +206,7 @@ fn on_all_children_bits<'a, 'tcx, F>( on_all_children_bits(tcx, mir, move_data, move_path_index, &mut each_child); } -fn on_all_drop_children_bits<'a, 'tcx, F>( +pub(crate) fn on_all_drop_children_bits<'a, 'tcx, F>( tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &Mir<'tcx>, ctxt: &MoveDataParamEnv<'tcx>, @@ -333,7 +227,7 @@ fn on_all_drop_children_bits<'a, 'tcx, F>( }) } -fn drop_flag_effects_for_function_entry<'a, 'tcx, F>( +pub(crate) fn drop_flag_effects_for_function_entry<'a, 'tcx, F>( tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &Mir<'tcx>, ctxt: &MoveDataParamEnv<'tcx>, @@ -350,7 +244,7 @@ fn drop_flag_effects_for_function_entry<'a, 'tcx, F>( } } -fn drop_flag_effects_for_location<'a, 'tcx, F>( +pub(crate) fn drop_flag_effects_for_location<'a, 'tcx, F>( tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &Mir<'tcx>, ctxt: &MoveDataParamEnv<'tcx>, diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs b/src/librustc_mir/dataflow/graphviz.rs similarity index 97% rename from src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs rename to src/librustc_mir/dataflow/graphviz.rs index 7f95f07f48d..e6d77aa2686 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs +++ b/src/librustc_mir/dataflow/graphviz.rs @@ -15,7 +15,6 @@ use rustc::mir::{BasicBlock, Mir}; use rustc_data_structures::bitslice::bits_to_string; use rustc_data_structures::indexed_set::{IdxSet}; use rustc_data_structures::indexed_vec::Idx; -use rustc_mir::util as mir_util; use dot; use dot::IntoCow; @@ -28,8 +27,10 @@ use std::marker::PhantomData; use std::mem; use std::path::Path; -use super::super::MirBorrowckCtxtPreDataflow; +use util; + use super::{BitDenotation, DataflowState}; +use super::DataflowBuilder; impl DataflowState { fn each_bit(&self, words: &IdxSet, mut f: F) @@ -86,7 +87,7 @@ pub trait MirWithFlowState<'tcx> { fn flow_state(&self) -> &DataflowState; } -impl<'a, 'tcx: 'a, BD> MirWithFlowState<'tcx> for MirBorrowckCtxtPreDataflow<'a, 'tcx, BD> +impl<'a, 'tcx: 'a, BD> MirWithFlowState<'tcx> for DataflowBuilder<'a, 'tcx, BD> where 'tcx: 'a, BD: BitDenotation { type BD = BD; @@ -103,8 +104,8 @@ struct Graph<'a, 'tcx, MWF:'a, P> where render_idx: P, } -pub fn print_borrowck_graph_to<'a, 'tcx, BD, P>( - mbcx: &MirBorrowckCtxtPreDataflow<'a, 'tcx, BD>, +pub(crate) fn print_borrowck_graph_to<'a, 'tcx, BD, P>( + mbcx: &DataflowBuilder<'a, 'tcx, BD>, path: &Path, render_idx: P) -> io::Result<()> @@ -220,7 +221,7 @@ impl<'a, 'tcx, MWF, P> dot::Labeller<'a> for Graph<'a, 'tcx, MWF, P> } Ok(()) } - mir_util::write_graphviz_node_label( + util::write_graphviz_node_label( *n, self.mbcx.mir(), &mut v, 4, |w| { let flow = self.mbcx.flow_state(); diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs b/src/librustc_mir/dataflow/impls/mod.rs similarity index 96% rename from src/librustc_borrowck/borrowck/mir/dataflow/impls.rs rename to src/librustc_mir/dataflow/impls/mod.rs index 1a1ac7f9c74..97c996dea68 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs +++ b/src/librustc_mir/dataflow/impls/mod.rs @@ -8,25 +8,26 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! Dataflow analyses are built upon some interpretation of the +//! bitvectors attached to each basic block, represented via a +//! zero-sized structure. + use rustc::ty::TyCtxt; use rustc::mir::{self, Mir, Location}; use rustc_data_structures::bitslice::BitSlice; // adds set_bit/get_bit to &[usize] bitvector rep. use rustc_data_structures::bitslice::{BitwiseOperator}; use rustc_data_structures::indexed_set::{IdxSet}; use rustc_data_structures::indexed_vec::Idx; -use rustc_mir::util::elaborate_drops::DropFlagState; -use super::super::gather_moves::{HasMoveData, MoveData, MoveOutIndex, MovePathIndex}; -use super::super::MoveDataParamEnv; -use super::super::drop_flag_effects_for_function_entry; -use super::super::drop_flag_effects_for_location; -use super::super::on_lookup_result_bits; +use super::MoveDataParamEnv; +use util::elaborate_drops::DropFlagState; +use super::move_paths::{HasMoveData, MoveData, MoveOutIndex, MovePathIndex}; use super::{BitDenotation, BlockSets, DataflowOperator}; -// Dataflow analyses are built upon some interpretation of the -// bitvectors attached to each basic block, represented via a -// zero-sized structure. +use super::drop_flag_effects_for_function_entry; +use super::drop_flag_effects_for_location; +use super::on_lookup_result_bits; /// `MaybeInitializedLvals` tracks all l-values that might be /// initialized upon reaching a particular point in the control flow @@ -219,6 +220,16 @@ pub struct MovingOutStatements<'a, 'tcx: 'a> { mdpe: &'a MoveDataParamEnv<'tcx>, } +impl<'a, 'tcx: 'a> MovingOutStatements<'a, 'tcx> { + pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &'a Mir<'tcx>, + mdpe: &'a MoveDataParamEnv<'tcx>) + -> Self + { + MovingOutStatements { tcx: tcx, mir: mir, mdpe: mdpe } + } +} + impl<'a, 'tcx> HasMoveData<'tcx> for MovingOutStatements<'a, 'tcx> { fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data } } diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs similarity index 95% rename from src/librustc_borrowck/borrowck/mir/dataflow/mod.rs rename to src/librustc_mir/dataflow/mod.rs index f0f082a2561..d7ad9f9c09a 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use syntax::ast; + use rustc_data_structures::indexed_set::{IdxSet, IdxSetBuf}; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::bitslice::{bitwise, BitwiseOperator}; -use rustc::ty::TyCtxt; +use rustc::ty::{TyCtxt}; use rustc::mir::{self, Mir}; use std::fmt::Debug; @@ -21,21 +23,31 @@ use std::mem; use std::path::PathBuf; use std::usize; -use super::MirBorrowckCtxtPreDataflow; - -pub use self::sanity_check::sanity_check_via_rustc_peek; pub use self::impls::{MaybeInitializedLvals, MaybeUninitializedLvals}; pub use self::impls::{DefinitelyInitializedLvals, MovingOutStatements}; +pub(crate) use self::drop_flag_effects::*; + +mod drop_flag_effects; mod graphviz; -mod sanity_check; mod impls; +pub mod move_paths; + +pub(crate) use self::move_paths::indexes; + +pub(crate) struct DataflowBuilder<'a, 'tcx: 'a, BD> where BD: BitDenotation +{ + node_id: ast::NodeId, + flow_state: DataflowAnalysis<'a, 'tcx, BD>, + print_preflow_to: Option, + print_postflow_to: Option, +} pub trait Dataflow { fn dataflow

(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> &Debug; } -impl<'a, 'tcx: 'a, BD> Dataflow for MirBorrowckCtxtPreDataflow<'a, 'tcx, BD> +impl<'a, 'tcx: 'a, BD> Dataflow for DataflowBuilder<'a, 'tcx, BD> where BD: BitDenotation + DataflowOperator { fn dataflow

(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> &Debug { @@ -135,7 +147,7 @@ fn dataflow_path(context: &str, prepost: &str, path: &str) -> PathBuf { path } -impl<'a, 'tcx: 'a, BD> MirBorrowckCtxtPreDataflow<'a, 'tcx, BD> +impl<'a, 'tcx: 'a, BD> DataflowBuilder<'a, 'tcx, BD> where BD: BitDenotation { fn pre_dataflow_instrumentation

(&self, p: P) -> io::Result<()> @@ -195,7 +207,7 @@ impl<'a, 'tcx: 'a, O> DataflowAnalysis<'a, 'tcx, O> pub fn mir(&self) -> &'a Mir<'tcx> { self.mir } } -pub struct DataflowResults(DataflowState) where O: BitDenotation; +pub struct DataflowResults(pub(crate) DataflowState) where O: BitDenotation; impl DataflowResults { pub fn sets(&self) -> &AllSets { @@ -213,7 +225,7 @@ pub struct DataflowState pub sets: AllSets, /// operator used to initialize, combine, and interpret bits. - operator: O, + pub(crate) operator: O, } #[derive(Debug)] @@ -240,9 +252,9 @@ pub struct AllSets { } pub struct BlockSets<'a, E: Idx> { - on_entry: &'a mut IdxSet, - gen_set: &'a mut IdxSet, - kill_set: &'a mut IdxSet, + pub(crate) on_entry: &'a mut IdxSet, + pub(crate) gen_set: &'a mut IdxSet, + pub(crate) kill_set: &'a mut IdxSet, } impl<'a, E:Idx> BlockSets<'a, E> { diff --git a/src/librustc_borrowck/borrowck/mir/abs_domain.rs b/src/librustc_mir/dataflow/move_paths/abs_domain.rs similarity index 100% rename from src/librustc_borrowck/borrowck/mir/abs_domain.rs rename to src/librustc_mir/dataflow/move_paths/abs_domain.rs diff --git a/src/librustc_borrowck/borrowck/mir/gather_moves.rs b/src/librustc_mir/dataflow/move_paths/mod.rs similarity index 98% rename from src/librustc_borrowck/borrowck/mir/gather_moves.rs rename to src/librustc_mir/dataflow/move_paths/mod.rs index a0ecdcc8e2f..d7ed0938e88 100644 --- a/src/librustc_borrowck/borrowck/mir/gather_moves.rs +++ b/src/librustc_mir/dataflow/move_paths/mod.rs @@ -21,14 +21,16 @@ use std::fmt; use std::mem; use std::ops::{Index, IndexMut}; -use super::abs_domain::{AbstractElem, Lift}; +use self::abs_domain::{AbstractElem, Lift}; + +mod abs_domain; // This submodule holds some newtype'd Index wrappers that are using // NonZero to ensure that Option occupies only a single word. // They are in a submodule to impose privacy restrictions; namely, to // ensure that other code does not accidentally access `index.0` // (which is likely to yield a subtle off-by-one error). -mod indexes { +pub(crate) mod indexes { use std::fmt; use core::nonzero::NonZero; use rustc_data_structures::indexed_vec::Idx; @@ -65,7 +67,7 @@ mod indexes { pub use self::indexes::MovePathIndex; pub use self::indexes::MoveOutIndex; -impl self::indexes::MoveOutIndex { +impl MoveOutIndex { pub fn move_path_index(&self, move_data: &MoveData) -> MovePathIndex { move_data.moves[*self].path } @@ -128,7 +130,7 @@ pub trait HasMoveData<'tcx> { pub struct LocationMap { /// Location-indexed (BasicBlock for outer index, index within BB /// for inner index) map. - map: IndexVec>, + pub(crate) map: IndexVec>, } impl Index for LocationMap { @@ -188,7 +190,7 @@ pub struct MovePathLookup<'tcx> { projections: FxHashMap<(MovePathIndex, AbstractElem<'tcx>), MovePathIndex> } -struct MoveDataBuilder<'a, 'tcx: 'a> { +pub(super) struct MoveDataBuilder<'a, 'tcx: 'a> { mir: &'a Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 474feefabbb..0010f312ef9 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -19,7 +19,6 @@ use rustc::middle::const_val::ConstVal; use rustc::ty::{self, AdtKind, VariantDef, Ty}; use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow}; use rustc::ty::cast::CastKind as TyCastKind; -use rustc::ty::subst::Subst; use rustc::hir; impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { @@ -586,7 +585,7 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, }); Expr { temp_lifetime: temp_lifetime, - ty: cx.tcx.type_of(def_id).subst(cx.tcx, substs), + ty: cx.tcx().mk_fn_def(def_id, substs), span: expr.span, kind: ExprKind::Literal { literal: Literal::Value { diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index bfa31c052e4..71855d3805e 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -26,6 +26,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![feature(rustc_diagnostic_macros)] #![feature(placement_in_syntax)] #![feature(collection_placement)] +#![feature(nonzero)] #[macro_use] extern crate log; extern crate graphviz as dot; @@ -40,10 +41,12 @@ extern crate syntax; extern crate syntax_pos; extern crate rustc_const_math; extern crate rustc_const_eval; +extern crate core; // for NonZero pub mod diagnostics; mod build; +pub mod dataflow; mod hair; mod shim; pub mod transform; diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 54779cbe301..11ad5d1509d 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -58,7 +58,7 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, // types in the MIR. They will be substituted again with // the param-substs, but because they are concrete, this // will not do any harm. - let sig = tcx.erase_late_bound_regions(&ty.fn_sig()); + let sig = tcx.erase_late_bound_regions(&ty.fn_sig(tcx)); let arg_tys = sig.inputs(); build_call_shim( @@ -153,8 +153,8 @@ fn build_drop_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, } else { Substs::identity_for_item(tcx, def_id) }; - let fn_ty = tcx.type_of(def_id).subst(tcx, substs); - let sig = tcx.erase_late_bound_regions(&fn_ty.fn_sig()); + let sig = tcx.fn_sig(def_id).subst(tcx, substs); + let sig = tcx.erase_late_bound_regions(&sig); let span = tcx.def_span(def_id); let source_info = SourceInfo { span, scope: ARGUMENT_VISIBILITY_SCOPE }; @@ -276,8 +276,8 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, call_kind={:?}, untuple_args={:?})", def_id, rcvr_adjustment, call_kind, untuple_args); - let fn_ty = tcx.type_of(def_id); - let sig = tcx.erase_late_bound_regions(&fn_ty.fn_sig()); + let sig = tcx.fn_sig(def_id); + let sig = tcx.erase_late_bound_regions(&sig); let span = tcx.def_span(def_id); debug!("build_call_shim: sig={:?}", sig); @@ -409,11 +409,8 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>, { let tcx = infcx.tcx; let def_id = tcx.hir.local_def_id(ctor_id); - let sig = match tcx.type_of(def_id).sty { - ty::TyFnDef(_, _, fty) => tcx.no_late_bound_regions(&fty) - .expect("LBR in ADT constructor signature"), - _ => bug!("unexpected type for ctor {:?}", def_id) - }; + let sig = tcx.no_late_bound_regions(&tcx.fn_sig(def_id)) + .expect("LBR in ADT constructor signature"); let sig = tcx.erase_regions(&sig); let (adt_def, substs) = match sig.output().sty { diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs similarity index 94% rename from src/librustc_borrowck/borrowck/mir/elaborate_drops.rs rename to src/librustc_mir/transform/elaborate_drops.rs index 83369772608..b158cb43ce7 100644 --- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -8,12 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use super::gather_moves::{HasMoveData, MoveData, MovePathIndex, LookupResult}; -use super::dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals}; -use super::dataflow::{DataflowResults}; -use super::{on_all_children_bits, on_all_drop_children_bits}; -use super::{drop_flag_effects_for_location, on_lookup_result_bits}; -use super::MoveDataParamEnv; +use dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex, LookupResult}; +use dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals}; +use dataflow::{DataflowResults}; +use dataflow::{on_all_children_bits, on_all_drop_children_bits}; +use dataflow::{drop_flag_effects_for_location, on_lookup_result_bits}; +use dataflow::MoveDataParamEnv; +use dataflow; use rustc::ty::{self, TyCtxt}; use rustc::mir::*; use rustc::mir::transform::{MirPass, MirSource}; @@ -21,9 +22,9 @@ use rustc::middle::const_val::ConstVal; use rustc::util::nodemap::FxHashMap; use rustc_data_structures::indexed_set::IdxSetBuf; use rustc_data_structures::indexed_vec::Idx; -use rustc_mir::util::patch::MirPatch; -use rustc_mir::util::elaborate_drops::{DropFlagState, Unwind, elaborate_drop}; -use rustc_mir::util::elaborate_drops::{DropElaborator, DropStyle, DropFlagMode}; +use util::patch::MirPatch; +use util::elaborate_drops::{DropFlagState, Unwind, elaborate_drop}; +use util::elaborate_drops::{DropElaborator, DropStyle, DropFlagMode}; use syntax::ast; use syntax_pos::Span; @@ -54,13 +55,13 @@ impl MirPass for ElaborateDrops { }; let dead_unwinds = find_dead_unwinds(tcx, mir, id, &env); let flow_inits = - super::do_dataflow(tcx, mir, id, &[], &dead_unwinds, - MaybeInitializedLvals::new(tcx, mir, &env), - |bd, p| &bd.move_data().move_paths[p]); + dataflow::do_dataflow(tcx, mir, id, &[], &dead_unwinds, + MaybeInitializedLvals::new(tcx, mir, &env), + |bd, p| &bd.move_data().move_paths[p]); let flow_uninits = - super::do_dataflow(tcx, mir, id, &[], &dead_unwinds, - MaybeUninitializedLvals::new(tcx, mir, &env), - |bd, p| &bd.move_data().move_paths[p]); + dataflow::do_dataflow(tcx, mir, id, &[], &dead_unwinds, + MaybeUninitializedLvals::new(tcx, mir, &env), + |bd, p| &bd.move_data().move_paths[p]); ElaborateDropsCtxt { tcx: tcx, @@ -91,7 +92,7 @@ fn find_dead_unwinds<'a, 'tcx>( // reach cleanup blocks, which can't have unwind edges themselves. let mut dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len()); let flow_inits = - super::do_dataflow(tcx, mir, id, &[], &dead_unwinds, + dataflow::do_dataflow(tcx, mir, id, &[], &dead_unwinds, MaybeInitializedLvals::new(tcx, mir, &env), |bd, p| &bd.move_data().move_paths[p]); for (bb, bb_data) in mir.basic_blocks().iter_enumerated() { @@ -242,7 +243,7 @@ impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> { } fn field_subpath(&self, path: Self::Path, field: Field) -> Option { - super::move_path_children_matching(self.ctxt.move_data(), path, |p| { + dataflow::move_path_children_matching(self.ctxt.move_data(), path, |p| { match p { &Projection { elem: ProjectionElem::Field(idx, _), .. @@ -253,7 +254,7 @@ impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> { } fn deref_subpath(&self, path: Self::Path) -> Option { - super::move_path_children_matching(self.ctxt.move_data(), path, |p| { + dataflow::move_path_children_matching(self.ctxt.move_data(), path, |p| { match p { &Projection { elem: ProjectionElem::Deref, .. } => true, _ => false @@ -262,7 +263,7 @@ impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> { } fn downcast_subpath(&self, path: Self::Path, variant: usize) -> Option { - super::move_path_children_matching(self.ctxt.move_data(), path, |p| { + dataflow::move_path_children_matching(self.ctxt.move_data(), path, |p| { match p { &Projection { elem: ProjectionElem::Downcast(_, idx), .. @@ -560,7 +561,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { fn drop_flags_for_args(&mut self) { let loc = Location { block: START_BLOCK, statement_index: 0 }; - super::drop_flag_effects_for_function_entry( + dataflow::drop_flag_effects_for_function_entry( self.tcx, self.mir, self.env, |path, ds| { self.set_drop_flag(loc, path, ds); } @@ -605,7 +606,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { } } let loc = Location { block: bb, statement_index: i }; - super::drop_flag_effects_for_location( + dataflow::drop_flag_effects_for_location( self.tcx, self.mir, self.env, loc, |path, ds| { if ds == DropFlagState::Absent || allow_initializations { self.set_drop_flag(loc, path, ds) diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index e809695c180..eb283df869f 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -67,12 +67,13 @@ impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> { } fn visit_statement(&mut self, - _block: BasicBlock, + block: BasicBlock, statement: &mut Statement<'tcx>, - _location: Location) { + location: Location) { if let StatementKind::EndRegion(_) = statement.kind { statement.kind = StatementKind::Nop; } + self.super_statement(block, statement, location); } } diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 0ac35a5fdd4..5f80c7bee14 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -87,7 +87,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { let terminator = bb_data.terminator(); if let TerminatorKind::Call { func: Operand::Constant(ref f), .. } = terminator.kind { - if let ty::TyFnDef(callee_def_id, substs, _) = f.ty.sty { + if let ty::TyFnDef(callee_def_id, substs) = f.ty.sty { callsites.push_back(CallSite { callee: callee_def_id, substs: substs, @@ -131,7 +131,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { let terminator = bb_data.terminator(); if let TerminatorKind::Call { func: Operand::Constant(ref f), .. } = terminator.kind { - if let ty::TyFnDef(callee_def_id, substs, _) = f.ty.sty { + if let ty::TyFnDef(callee_def_id, substs) = f.ty.sty { // Don't inline the same function multiple times. if callsite.callee != callee_def_id { callsites.push_back(CallSite { @@ -270,8 +270,9 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { } TerminatorKind::Call {func: Operand::Constant(ref f), .. } => { - if let ty::TyFnDef(.., f) = f.ty.sty { + if let ty::TyFnDef(def_id, _) = f.ty.sty { // Don't give intrinsics the extra penalty for calls + let f = tcx.fn_sig(def_id); if f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic { cost += INSTR_COST; } else { diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 4594c611d59..1530ea8e0df 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -30,6 +30,8 @@ pub mod simplify; pub mod erase_regions; pub mod no_landing_pads; pub mod type_check; +pub mod rustc_peek; +pub mod elaborate_drops; pub mod add_call_guards; pub mod promote_consts; pub mod qualify_consts; diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 05a6cdd57ff..68b687a2e61 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -750,8 +750,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { let fn_ty = func.ty(self.mir, self.tcx); let (is_shuffle, is_const_fn) = match fn_ty.sty { - ty::TyFnDef(def_id, _, f) => { - (f.abi() == Abi::PlatformIntrinsic && + ty::TyFnDef(def_id, _) => { + (self.tcx.fn_sig(def_id).abi() == Abi::PlatformIntrinsic && self.tcx.item_name(def_id).as_str().starts_with("simd_shuffle"), self.tcx.is_const_fn(def_id)) } @@ -996,7 +996,7 @@ impl MirPass for QualifyAndPromoteConstants { tcx.require_lang_item(lang_items::SyncTraitLangItem), cause); if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(&err); + infcx.report_fulfillment_errors(&err, None); } }); } diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs b/src/librustc_mir/transform/rustc_peek.rs similarity index 69% rename from src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs rename to src/librustc_mir/transform/rustc_peek.rs index 2c55460fb30..5918de0c688 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -14,12 +14,67 @@ use syntax_pos::Span; use rustc::ty::{self, TyCtxt}; use rustc::mir::{self, Mir}; +use rustc::mir::transform::{MirPass, MirSource}; +use rustc_data_structures::indexed_set::IdxSetBuf; use rustc_data_structures::indexed_vec::Idx; -use super::super::gather_moves::{MovePathIndex, LookupResult}; -use super::BitDenotation; -use super::DataflowResults; -use super::super::gather_moves::HasMoveData; +use dataflow::do_dataflow; +use dataflow::MoveDataParamEnv; +use dataflow::BitDenotation; +use dataflow::DataflowResults; +use dataflow::{DefinitelyInitializedLvals, MaybeInitializedLvals, MaybeUninitializedLvals}; +use dataflow::move_paths::{MovePathIndex, LookupResult}; +use dataflow::move_paths::{HasMoveData, MoveData}; +use dataflow; + +use dataflow::has_rustc_mir_with; + +pub struct SanityCheck; + +impl MirPass for SanityCheck { + fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, + src: MirSource, mir: &mut Mir<'tcx>) { + let id = src.item_id(); + let def_id = tcx.hir.local_def_id(id); + if !tcx.has_attr(def_id, "rustc_mir_borrowck") { + debug!("skipping rustc_peek::SanityCheck on {}", tcx.item_path_str(def_id)); + return; + } else { + debug!("running rustc_peek::SanityCheck on {}", tcx.item_path_str(def_id)); + } + + let attributes = tcx.get_attrs(def_id); + let param_env = tcx.param_env(def_id); + let move_data = MoveData::gather_moves(mir, tcx, param_env); + let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env }; + let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len()); + let flow_inits = + do_dataflow(tcx, mir, id, &attributes, &dead_unwinds, + MaybeInitializedLvals::new(tcx, mir, &mdpe), + |bd, i| &bd.move_data().move_paths[i]); + let flow_uninits = + do_dataflow(tcx, mir, id, &attributes, &dead_unwinds, + MaybeUninitializedLvals::new(tcx, mir, &mdpe), + |bd, i| &bd.move_data().move_paths[i]); + let flow_def_inits = + do_dataflow(tcx, mir, id, &attributes, &dead_unwinds, + DefinitelyInitializedLvals::new(tcx, mir, &mdpe), + |bd, i| &bd.move_data().move_paths[i]); + + if has_rustc_mir_with(&attributes, "rustc_peek_maybe_init").is_some() { + sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_inits); + } + if has_rustc_mir_with(&attributes, "rustc_peek_maybe_uninit").is_some() { + sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_uninits); + } + if has_rustc_mir_with(&attributes, "rustc_peek_definite_init").is_some() { + sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_def_inits); + } + if has_rustc_mir_with(&attributes, "stop_after_dataflow").is_some() { + tcx.sess.fatal("stop_after_dataflow ended compilation"); + } + } +} /// This function scans `mir` for all calls to the intrinsic /// `rustc_peek` that have the expression form `rustc_peek(&expr)`. @@ -92,7 +147,7 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // of the argument at time immediate preceding Call to // `rustc_peek`). - let mut sets = super::BlockSets { on_entry: &mut entry, + let mut sets = dataflow::BlockSets { on_entry: &mut entry, gen_set: &mut gen, kill_set: &mut kill }; @@ -161,18 +216,13 @@ fn is_rustc_peek<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, terminator: &'a Option>) -> Option<(&'a [mir::Operand<'tcx>], Span)> { if let Some(mir::Terminator { ref kind, source_info, .. }) = *terminator { - if let mir::TerminatorKind::Call { func: ref oper, ref args, .. } = *kind - { - if let mir::Operand::Constant(ref func) = *oper - { - if let ty::TyFnDef(def_id, _, sig) = func.ty.sty - { - let abi = sig.abi(); + if let mir::TerminatorKind::Call { func: ref oper, ref args, .. } = *kind { + if let mir::Operand::Constant(ref func) = *oper { + if let ty::TyFnDef(def_id, _) = func.ty.sty { + let abi = tcx.fn_sig(def_id).abi(); let name = tcx.item_name(def_id); - if abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic { - if name == "rustc_peek" { - return Some((args, source_info.span)); - } + if abi == Abi::RustIntrinsic && name == "rustc_peek" { + return Some((args, source_info.span)); } } } diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index efde39ad6a4..7e6fccf3019 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -462,7 +462,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { let func_ty = func.ty(mir, tcx); debug!("check_terminator: call, func_ty={:?}", func_ty); let sig = match func_ty.sty { - ty::TyFnDef(.., sig) | ty::TyFnPtr(sig) => sig, + ty::TyFnDef(..) | ty::TyFnPtr(_) => func_ty.fn_sig(tcx), _ => { span_mirbug!(self, term, "call to non-function {:?}", func_ty); return; diff --git a/src/librustc_msan/build.rs b/src/librustc_msan/build.rs index dcadbe86966..7e2a82dd0ab 100644 --- a/src/librustc_msan/build.rs +++ b/src/librustc_msan/build.rs @@ -32,4 +32,5 @@ fn main() { .build_target("msan") .build(); } + println!("cargo:rerun-if-env-changed=LLVM_CONFIG"); } diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 7c443a4ac75..6ad03186dc7 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -93,6 +93,17 @@ impl<'a> AstValidator<'a> { } } } + + /// matches '-' lit | lit (cf. parser::Parser::parse_pat_literal_maybe_minus) + fn check_expr_within_pat(&self, expr: &Expr) { + match expr.node { + ExprKind::Lit(..) | ExprKind::Path(..) => {} + ExprKind::Unary(UnOp::Neg, ref inner) + if match inner.node { ExprKind::Lit(_) => true, _ => false } => {} + _ => self.err_handler().span_err(expr.span, "arbitrary expressions aren't allowed \ + in patterns") + } + } } impl<'a> Visitor<'a> for AstValidator<'a> { @@ -308,6 +319,21 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } visit::walk_generics(self, g) } + + fn visit_pat(&mut self, pat: &'a Pat) { + match pat.node { + PatKind::Lit(ref expr) => { + self.check_expr_within_pat(expr); + } + PatKind::Range(ref start, ref end, _) => { + self.check_expr_within_pat(start); + self.check_expr_within_pat(end); + } + _ => {} + } + + visit::walk_pat(self, pat) + } } pub fn check_crate(session: &Session, krate: &Crate) { diff --git a/src/librustc_passes/static_recursion.rs b/src/librustc_passes/static_recursion.rs index 8d455adc23c..0dbb2d1d4d0 100644 --- a/src/librustc_passes/static_recursion.rs +++ b/src/librustc_passes/static_recursion.rs @@ -12,8 +12,9 @@ // recursively. use rustc::hir::map as hir_map; -use rustc::session::{CompileResult, Session}; +use rustc::session::Session; use rustc::hir::def::{Def, CtorKind}; +use rustc::util::common::ErrorReported; use rustc::util::nodemap::{NodeMap, NodeSet}; use syntax::ast; @@ -86,7 +87,9 @@ impl<'a, 'hir: 'a> Visitor<'hir> for CheckCrateVisitor<'a, 'hir> { } } -pub fn check_crate<'hir>(sess: &Session, hir_map: &hir_map::Map<'hir>) -> CompileResult { +pub fn check_crate<'hir>(sess: &Session, hir_map: &hir_map::Map<'hir>) + -> Result<(), ErrorReported> +{ let mut visitor = CheckCrateVisitor { sess: sess, hir_map: hir_map, diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index fb7258d4266..9eb96fea527 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -400,7 +400,13 @@ impl<'b, 'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { } fn ty(&mut self) -> &mut Self { - self.ev.tcx.type_of(self.item_def_id).visit_with(self); + let ty = self.ev.tcx.type_of(self.item_def_id); + ty.visit_with(self); + if let ty::TyFnDef(def_id, _) = ty.sty { + if def_id == self.item_def_id { + self.ev.tcx.fn_sig(def_id).visit_with(self); + } + } self } @@ -910,7 +916,13 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> { } fn ty(&mut self) -> &mut Self { - self.tcx.type_of(self.item_def_id).visit_with(self); + let ty = self.tcx.type_of(self.item_def_id); + ty.visit_with(self); + if let ty::TyFnDef(def_id, _) = ty.sty { + if def_id == self.item_def_id { + self.tcx.fn_sig(def_id).visit_with(self); + } + } self } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index b97c08b5bde..4b6b754dca6 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -149,14 +149,15 @@ impl<'a> Resolver<'a> { resolve_error(self, view_path.span, ResolutionError::SelfImportsOnlyAllowedWithin); - } else if source_name == "$crate" && full_path.segments.len() == 1 { + } else if source_name == keywords::DollarCrate.name() && + full_path.segments.len() == 1 { let crate_root = self.resolve_crate_root(source.ctxt); let crate_name = match crate_root.kind { ModuleKind::Def(_, name) => name, ModuleKind::Block(..) => unreachable!(), }; source.name = crate_name; - if binding.name == "$crate" { + if binding.name == keywords::DollarCrate.name() { binding.name = crate_name; } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 8c11aa7def8..4bfe4d25ded 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2665,7 +2665,8 @@ impl<'a> Resolver<'a> { }; if path.len() > 1 && !global_by_default && result.base_def() != Def::Err && - path[0].name != keywords::CrateRoot.name() && path[0].name != "$crate" { + path[0].name != keywords::CrateRoot.name() && + path[0].name != keywords::DollarCrate.name() { let unqualified_result = { match self.resolve_path(&[*path.last().unwrap()], Some(ns), false, span) { PathResult::NonModule(path_res) => path_res.base_def(), @@ -2718,7 +2719,7 @@ impl<'a> Resolver<'a> { if i == 0 && ns == TypeNS && ident.name == keywords::CrateRoot.name() { module = Some(self.resolve_crate_root(ident.ctxt.modern())); continue - } else if i == 0 && ns == TypeNS && ident.name == "$crate" { + } else if i == 0 && ns == TypeNS && ident.name == keywords::DollarCrate.name() { module = Some(self.resolve_crate_root(ident.ctxt)); continue } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 60c07eda4d5..0fbc596f2e1 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -128,7 +128,7 @@ impl<'a> base::Resolver for Resolver<'a> { impl<'a, 'b> Folder for EliminateCrateVar<'a, 'b> { fn fold_path(&mut self, mut path: ast::Path) -> ast::Path { let ident = path.segments[0].identifier; - if ident.name == "$crate" { + if ident.name == keywords::DollarCrate.name() { path.segments[0].identifier.name = keywords::CrateRoot.name(); let module = self.0.resolve_crate_root(ident.ctxt); if !module.is_local() { diff --git a/src/librustc_trans/Cargo.toml b/src/librustc_trans/Cargo.toml index 86590bff4ff..a512cf2f02a 100644 --- a/src/librustc_trans/Cargo.toml +++ b/src/librustc_trans/Cargo.toml @@ -15,6 +15,7 @@ flate2 = "0.2" jobserver = "0.1.5" log = "0.3" owning_ref = "0.3.3" +rustc-demangle = "0.1.4" rustc = { path = "../librustc" } rustc_back = { path = "../librustc_back" } rustc_bitflags = { path = "../librustc_bitflags" } diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans/back/symbol_names.rs index 8e14335ceac..10b66fb1991 100644 --- a/src/librustc_trans/back/symbol_names.rs +++ b/src/librustc_trans/back/symbol_names.rs @@ -154,6 +154,13 @@ fn get_symbol_hash<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, assert!(!item_type.has_erasable_regions()); hasher.visit_ty(item_type); + // If this is a function, we hash the signature as well. + // This is not *strictly* needed, but it may help in some + // situations, see the `run-make/a-b-a-linker-guard` test. + if let ty::TyFnDef(..) = item_type.sty { + item_type.fn_sig(tcx).visit_with(&mut hasher); + } + // also include any type parameters (for generic items) if let Some(substs) = substs { assert!(!substs.has_erasable_regions()); diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 7e99ea0ee19..562d7171156 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -29,15 +29,18 @@ use syntax_pos::MultiSpan; use context::{is_pie_binary, get_reloc_model}; use jobserver::{Client, Acquired}; use crossbeam::{scope, Scope}; +use rustc_demangle; use std::cmp; use std::ffi::CString; use std::fs; use std::io; +use std::io::Write; use std::path::{Path, PathBuf}; use std::str; use std::sync::mpsc::{channel, Sender}; -use libc::{c_uint, c_void}; +use std::slice; +use libc::{c_uint, c_void, c_char, size_t}; pub const RELOC_MODEL_ARGS : [(&'static str, llvm::RelocMode); 7] = [ ("pic", llvm::RelocMode::PIC), @@ -510,8 +513,40 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, if config.emit_ir { let out = output_names.temp_path(OutputType::LlvmAssembly, module_name); let out = path2cstr(&out); + + extern "C" fn demangle_callback(input_ptr: *const c_char, + input_len: size_t, + output_ptr: *mut c_char, + output_len: size_t) -> size_t { + let input = unsafe { + slice::from_raw_parts(input_ptr as *const u8, input_len as usize) + }; + + let input = match str::from_utf8(input) { + Ok(s) => s, + Err(_) => return 0, + }; + + let output = unsafe { + slice::from_raw_parts_mut(output_ptr as *mut u8, output_len as usize) + }; + let mut cursor = io::Cursor::new(output); + + let demangled = match rustc_demangle::try_demangle(input) { + Ok(d) => d, + Err(_) => return 0, + }; + + if let Err(_) = write!(cursor, "{:#}", demangled) { + // Possible only if provided buffer is not big enough + return 0; + } + + cursor.position() as size_t + } + with_codegen(tm, llmod, config.no_builtins, |cpm| { - llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr()); + llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr(), demangle_callback); llvm::LLVMDisposePassManager(cpm); }) } diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index d723cf32571..a76abcf7b49 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -195,7 +195,7 @@ use rustc::hir::map as hir_map; use rustc::hir::def_id::DefId; use rustc::middle::lang_items::{ExchangeMallocFnLangItem}; use rustc::traits; -use rustc::ty::subst::{Substs, Subst}; +use rustc::ty::subst::Substs; use rustc::ty::{self, TypeFoldable, TyCtxt}; use rustc::ty::adjustment::CustomCoerceUnsized; use rustc::mir::{self, Location}; @@ -304,6 +304,11 @@ fn collect_roots<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, scx.tcx().hir.krate().visit_all_item_likes(&mut visitor); } + // We can only translate items that are instantiable - items all of + // whose predicates hold. Luckily, items that aren't instantiable + // can't actually be used, so we can just skip translating them. + roots.retain(|root| root.is_instantiable(scx.tcx())); + roots } @@ -587,7 +592,7 @@ fn visit_fn_use<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, is_direct_call: bool, output: &mut Vec>) { - if let ty::TyFnDef(def_id, substs, _) = ty.sty { + if let ty::TyFnDef(def_id, substs) = ty.sty { let instance = monomorphize::resolve(scx, def_id, substs); visit_instance_use(scx, instance, is_direct_call, output); } @@ -937,14 +942,9 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(scx: &SharedCrateContext<'a, ' let instance = monomorphize::resolve(scx, method.def_id, callee_substs); - let predicates = tcx.predicates_of(instance.def_id()).predicates - .subst(tcx, instance.substs); - if !traits::normalize_and_test_predicates(tcx, predicates) { - continue; - } - - if should_trans_locally(tcx, &instance) { - output.push(create_fn_trans_item(instance)); + let trans_item = create_fn_trans_item(instance); + if trans_item.is_instantiable(tcx) && should_trans_locally(tcx, &instance) { + output.push(trans_item); } } } diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index a6f3fb709a0..9b0803908b1 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -495,12 +495,12 @@ pub fn ty_fn_sig<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, -> ty::PolyFnSig<'tcx> { match ty.sty { - ty::TyFnDef(_, _, sig) => sig, + ty::TyFnDef(..) | // Shims currently have type TyFnPtr. Not sure this should remain. - ty::TyFnPtr(sig) => sig, + ty::TyFnPtr(_) => ty.fn_sig(ccx.tcx()), ty::TyClosure(def_id, substs) => { let tcx = ccx.tcx(); - let sig = tcx.closure_type(def_id).subst(tcx, substs.substs); + let sig = tcx.fn_sig(def_id).subst(tcx, substs.substs); let env_region = ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrEnv); let env_ty = match tcx.closure_kind(def_id) { diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 95ceec610ea..0cc19936011 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -488,7 +488,6 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, debug!("type_metadata: {:?}", t); - let sty = &t.sty; let ptr_metadata = |ty: Ty<'tcx>| { match ty.sty { ty::TySlice(typ) => { @@ -518,7 +517,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } }; - let MetadataCreationResult { metadata, already_stored_in_typemap } = match *sty { + let MetadataCreationResult { metadata, already_stored_in_typemap } = match t.sty { ty::TyNever | ty::TyBool | ty::TyChar | @@ -557,10 +556,10 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, Err(metadata) => return metadata, } } - ty::TyFnDef(.., sig) | ty::TyFnPtr(sig) => { + ty::TyFnDef(..) | ty::TyFnPtr(_) => { let fn_metadata = subroutine_type_metadata(cx, unique_type_id, - sig, + t.fn_sig(cx.tcx()), usage_site_span).metadata; match debug_context(cx).type_map .borrow() @@ -610,7 +609,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, usage_site_span).finalize(cx) } _ => { - bug!("debuginfo: unexpected type in type_metadata: {:?}", sty) + bug!("debuginfo: unexpected type in type_metadata: {:?}", t) } }; diff --git a/src/librustc_trans/debuginfo/type_names.rs b/src/librustc_trans/debuginfo/type_names.rs index 13ff6646e66..bfca4fec706 100644 --- a/src/librustc_trans/debuginfo/type_names.rs +++ b/src/librustc_trans/debuginfo/type_names.rs @@ -96,8 +96,8 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, push_type_params(cx, principal.substs, output); } }, - ty::TyFnDef(.., sig) | - ty::TyFnPtr(sig) => { + ty::TyFnDef(..) | ty::TyFnPtr(_) => { + let sig = t.fn_sig(cx.tcx()); if sig.unsafety() == hir::Unsafety::Unsafe { output.push_str("unsafe "); } diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs index 367f0398fa8..c2f44c089a2 100644 --- a/src/librustc_trans/glue.rs +++ b/src/librustc_trans/glue.rs @@ -76,7 +76,7 @@ pub fn size_and_align_of_dst<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, t: Ty<'tcx>, inf } assert!(!info.is_null()); match t.sty { - ty::TyAdt(def, substs) => { + ty::TyAdt(..) | ty::TyTuple(..) => { let ccx = bcx.ccx; // First get the size of all statically known fields. // Don't use size_of because it also rounds up to alignment, which we @@ -101,8 +101,14 @@ pub fn size_and_align_of_dst<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, t: Ty<'tcx>, inf // Recurse to get the size of the dynamically sized field (must be // the last field). - let last_field = def.struct_variant().fields.last().unwrap(); - let field_ty = monomorphize::field_ty(bcx.tcx(), substs, last_field); + let field_ty = match t.sty { + ty::TyAdt(def, substs) => { + let last_field = def.struct_variant().fields.last().unwrap(); + monomorphize::field_ty(bcx.tcx(), substs, last_field) + }, + ty::TyTuple(tys, _) => tys.last().unwrap(), + _ => unreachable!(), + }; let (unsized_size, unsized_align) = size_and_align_of_dst(bcx, field_ty, info); // FIXME (#26403, #27023): We should be adding padding diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index de908bb24a7..9956c28e641 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -95,11 +95,12 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, let ccx = bcx.ccx; let tcx = ccx.tcx(); - let (def_id, substs, sig) = match callee_ty.sty { - ty::TyFnDef(def_id, substs, sig) => (def_id, substs, sig), + let (def_id, substs) = match callee_ty.sty { + ty::TyFnDef(def_id, substs) => (def_id, substs), _ => bug!("expected fn item type, found {}", callee_ty) }; + let sig = callee_ty.fn_sig(tcx); let sig = tcx.erase_late_bound_regions_and_normalize(&sig); let arg_tys = sig.inputs(); let ret_ty = sig.output(); @@ -986,7 +987,7 @@ fn generic_simd_intrinsic<'a, 'tcx>( let tcx = bcx.tcx(); - let sig = tcx.erase_late_bound_regions_and_normalize(&callee_ty.fn_sig()); + let sig = tcx.erase_late_bound_regions_and_normalize(&callee_ty.fn_sig(tcx)); let arg_tys = sig.inputs(); // every intrinsic takes a SIMD vector as its first argument diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 859c6574787..6acd10cb887 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -34,7 +34,6 @@ #![feature(rustc_diagnostic_macros)] #![feature(slice_patterns)] #![feature(conservative_impl_trait)] -#![feature(command_envs)] use rustc::dep_graph::WorkProduct; use syntax_pos::symbol::Symbol; @@ -53,6 +52,7 @@ extern crate rustc_const_math; #[macro_use] #[no_link] extern crate rustc_bitflags; +extern crate rustc_demangle; extern crate jobserver; #[macro_use] extern crate log; diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index 8863c7ffae6..48b166c61de 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -28,6 +28,7 @@ use type_of; use type_::Type; use syntax::symbol::Symbol; +use syntax_pos::Pos; use std::cmp; @@ -333,6 +334,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { let filename = Symbol::intern(&loc.file.name).as_str(); let filename = C_str_slice(bcx.ccx, filename); let line = C_u32(bcx.ccx, loc.line as u32); + let col = C_u32(bcx.ccx, loc.col.to_usize() as u32 + 1); // Put together the arguments to the panic entry point. let (lang_item, args, const_err) = match *msg { @@ -347,29 +349,29 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { index: index as u64 })); - let file_line = C_struct(bcx.ccx, &[filename, line], false); - let align = llalign_of_min(bcx.ccx, common::val_ty(file_line)); - let file_line = consts::addr_of(bcx.ccx, - file_line, - align, - "panic_bounds_check_loc"); + let file_line_col = C_struct(bcx.ccx, &[filename, line, col], false); + let align = llalign_of_min(bcx.ccx, common::val_ty(file_line_col)); + let file_line_col = consts::addr_of(bcx.ccx, + file_line_col, + align, + "panic_bounds_check_loc"); (lang_items::PanicBoundsCheckFnLangItem, - vec![file_line, index, len], + vec![file_line_col, index, len], const_err) } mir::AssertMessage::Math(ref err) => { let msg_str = Symbol::intern(err.description()).as_str(); let msg_str = C_str_slice(bcx.ccx, msg_str); - let msg_file_line = C_struct(bcx.ccx, - &[msg_str, filename, line], + let msg_file_line_col = C_struct(bcx.ccx, + &[msg_str, filename, line, col], false); - let align = llalign_of_min(bcx.ccx, common::val_ty(msg_file_line)); - let msg_file_line = consts::addr_of(bcx.ccx, - msg_file_line, - align, - "panic_loc"); + let align = llalign_of_min(bcx.ccx, common::val_ty(msg_file_line_col)); + let msg_file_line_col = consts::addr_of(bcx.ccx, + msg_file_line_col, + align, + "panic_loc"); (lang_items::PanicFnLangItem, - vec![msg_file_line], + vec![msg_file_line_col], Some(ErrKind::Math(err.clone()))) } }; @@ -404,20 +406,18 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { // Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar. let callee = self.trans_operand(&bcx, func); - let (instance, mut llfn, sig) = match callee.ty.sty { - ty::TyFnDef(def_id, substs, sig) => { + let (instance, mut llfn) = match callee.ty.sty { + ty::TyFnDef(def_id, substs) => { (Some(monomorphize::resolve(bcx.ccx.shared(), def_id, substs)), - None, - sig) + None) } - ty::TyFnPtr(sig) => { - (None, - Some(callee.immediate()), - sig) + ty::TyFnPtr(_) => { + (None, Some(callee.immediate())) } _ => bug!("{} is not callable", callee.ty) }; let def = instance.map(|i| i.def); + let sig = callee.ty.fn_sig(bcx.tcx()); let sig = bcx.tcx().erase_late_bound_regions_and_normalize(&sig); let abi = sig.abi; diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 16ef32ccf57..fcb4b25e6fe 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -334,7 +334,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { let fn_ty = func.ty(self.mir, tcx); let fn_ty = self.monomorphize(&fn_ty); let (def_id, substs) = match fn_ty.sty { - ty::TyFnDef(def_id, substs, _) => (def_id, substs), + ty::TyFnDef(def_id, substs) => (def_id, substs), _ => span_bug!(span, "calling {:?} (of type {}) in constant", func, fn_ty) }; @@ -560,7 +560,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { let val = match *kind { mir::CastKind::ReifyFnPointer => { match operand.ty.sty { - ty::TyFnDef(def_id, substs, _) => { + ty::TyFnDef(def_id, substs) => { callee::resolve_and_get_fn(self.ccx, def_id, substs) } _ => { @@ -579,7 +579,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { .find(|it| it.kind == ty::AssociatedKind::Method) .unwrap().def_id; // Now create its substs [Closure, Tuple] - let input = tcx.closure_type(def_id) + let input = tcx.fn_sig(def_id) .subst(tcx, substs.substs).input(0); let input = tcx.erase_late_bound_regions_and_normalize(&input); let substs = tcx.mk_substs([operand.ty, input] diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index 61e537c9cc0..4bd5091a4f3 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -180,7 +180,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { let val = match *kind { mir::CastKind::ReifyFnPointer => { match operand.ty.sty { - ty::TyFnDef(def_id, substs, _) => { + ty::TyFnDef(def_id, substs) => { OperandValue::Immediate( callee::resolve_and_get_fn(bcx.ccx, def_id, substs)) } diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs index d27eeb2b646..1f6a262162d 100644 --- a/src/librustc_trans/monomorphize.rs +++ b/src/librustc_trans/monomorphize.rs @@ -40,7 +40,7 @@ fn fn_once_adapter_instance<'a, 'tcx>( let self_ty = tcx.mk_closure_from_closure_substs( closure_did, substs); - let sig = tcx.closure_type(closure_did).subst(tcx, substs.substs); + let sig = tcx.fn_sig(closure_did).subst(tcx, substs.substs); let sig = tcx.erase_late_bound_regions_and_normalize(&sig); assert_eq!(sig.inputs().len(), 1); let substs = tcx.mk_substs([ @@ -165,9 +165,11 @@ pub fn resolve<'a, 'tcx>( } else { let item_type = def_ty(scx, def_id, substs); let def = match item_type.sty { - ty::TyFnDef(_, _, f) if - f.abi() == Abi::RustIntrinsic || - f.abi() == Abi::PlatformIntrinsic => + ty::TyFnDef(..) if { + let f = item_type.fn_sig(scx.tcx()); + f.abi() == Abi::RustIntrinsic || + f.abi() == Abi::PlatformIntrinsic + } => { debug!(" => intrinsic"); ty::InstanceDef::Intrinsic(def_id) diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index 0dc2bc85e30..2a6e7c5ace6 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -25,8 +25,9 @@ use llvm; use monomorphize::Instance; use rustc::hir; use rustc::hir::def_id::DefId; +use rustc::traits; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; -use rustc::ty::subst::Substs; +use rustc::ty::subst::{Subst, Substs}; use syntax::ast::{self, NodeId}; use syntax::attr; use syntax_pos::Span; @@ -250,6 +251,44 @@ impl<'a, 'tcx> TransItem<'tcx> { } } + /// Returns whether this instance is instantiable - whether it has no unsatisfied + /// predicates. + /// + /// In order to translate an item, all of its predicates must hold, because + /// otherwise the item does not make sense. Type-checking ensures that + /// the predicates of every item that is *used by* a valid item *do* + /// hold, so we can rely on that. + /// + /// However, we translate collector roots (reachable items) and functions + /// in vtables when they are seen, even if they are not used, and so they + /// might not be instantiable. For example, a programmer can define this + /// public function: + /// + /// pub fn foo<'a>(s: &'a mut ()) where &'a mut (): Clone { + /// <&mut () as Clone>::clone(&s); + /// } + /// + /// That function can't be translated, because the method `<&mut () as Clone>::clone` + /// does not exist. Luckily for us, that function can't ever be used, + /// because that would require for `&'a mut (): Clone` to hold, so we + /// can just not emit any code, or even a linker reference for it. + /// + /// Similarly, if a vtable method has such a signature, and therefore can't + /// be used, we can just not emit it and have a placeholder (a null pointer, + /// which will never be accessed) in its place. + pub fn is_instantiable(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool { + debug!("is_instantiable({:?})", self); + let (def_id, substs) = match *self { + TransItem::Fn(ref instance) => (instance.def_id(), instance.substs), + TransItem::Static(node_id) => (tcx.hir.local_def_id(node_id), Substs::empty()), + // global asm never has predicates + TransItem::GlobalAsm(..) => return true + }; + + let predicates = tcx.predicates_of(def_id).predicates.subst(tcx, substs); + traits::normalize_and_test_predicates(tcx, predicates) + } + pub fn to_string(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String { let hir_map = &tcx.hir; @@ -401,8 +440,9 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { output); } }, - ty::TyFnDef(.., sig) | - ty::TyFnPtr(sig) => { + ty::TyFnDef(..) | + ty::TyFnPtr(_) => { + let sig = t.fn_sig(self.tcx); if sig.unsafety() == hir::Unsafety::Unsafe { output.push_str("unsafe "); } diff --git a/src/librustc_tsan/build.rs b/src/librustc_tsan/build.rs index 5ea52f17a0f..641d9c3647d 100644 --- a/src/librustc_tsan/build.rs +++ b/src/librustc_tsan/build.rs @@ -32,4 +32,5 @@ fn main() { .build_target("tsan") .build(); } + println!("cargo:rerun-if-env-changed=LLVM_CONFIG"); } diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index bdd8169b84f..68726a7b1c4 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -619,7 +619,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Type check the path. let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id); // Replace constructor type with constructed type for tuple struct patterns. - let pat_ty = pat_ty.fn_sig().output(); + let pat_ty = pat_ty.fn_sig(tcx).output(); let pat_ty = tcx.no_late_bound_regions(&pat_ty).expect("expected fn type"); self.demand_eqtype(pat.span, expected, pat_ty); diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 385ed7eb0e3..a0801a74866 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -108,7 +108,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // haven't yet decided on whether the closure is fn vs // fnmut vs fnonce. If so, we have to defer further processing. if self.closure_kind(def_id).is_none() { - let closure_ty = self.closure_type(def_id).subst(self.tcx, substs.substs); + let closure_ty = self.fn_sig(def_id).subst(self.tcx, substs.substs); let fn_sig = self.replace_late_bound_regions_with_fresh_var(call_expr.span, infer::FnCall, &closure_ty) @@ -196,8 +196,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { expected: Expectation<'tcx>) -> Ty<'tcx> { let (fn_sig, def_span) = match callee_ty.sty { - ty::TyFnDef(def_id, .., sig) => { - (sig, self.tcx.hir.span_if_local(def_id)) + ty::TyFnDef(def_id, _) => { + (callee_ty.fn_sig(self.tcx), self.tcx.hir.span_if_local(def_id)) } ty::TyFnPtr(sig) => (sig, None), ref t => { diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 91aeade65aa..7bd24c939ca 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -40,9 +40,11 @@ use super::{Diverges, FnCtxt}; -use lint; +use errors::DiagnosticBuilder; use hir::def_id::DefId; +use lint; use rustc::hir; +use rustc::session::Session; use rustc::traits; use rustc::ty::{self, Ty, TypeFoldable}; use rustc::ty::cast::{CastKind, CastTy}; @@ -112,6 +114,18 @@ enum CastError { NonScalar, } +fn make_invalid_casting_error<'a, 'gcx, 'tcx>(sess: &'a Session, + span: Span, + expr_ty: Ty<'tcx>, + cast_ty: Ty<'tcx>, + fcx: &FnCtxt<'a, 'gcx, 'tcx>) + -> DiagnosticBuilder<'a> { + type_error_struct!(sess, span, expr_ty, E0606, + "casting `{}` as `{}` is invalid", + fcx.ty_to_string(expr_ty), + fcx.ty_to_string(cast_ty)) +} + impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { pub fn new(fcx: &FnCtxt<'a, 'gcx, 'tcx>, expr: &'tcx hir::Expr, @@ -146,14 +160,9 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { match e { CastError::NeedDeref => { let error_span = self.span; + let mut err = make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, + self.cast_ty, fcx); let cast_ty = fcx.ty_to_string(self.cast_ty); - let mut err = fcx.type_error_struct(error_span, - |actual| { - format!("casting `{}` as `{}` is invalid", - actual, - cast_ty) - }, - self.expr_ty); err.span_label(error_span, format!("cannot cast `{}` as `{}`", fcx.ty_to_string(self.expr_ty), @@ -166,13 +175,8 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { } CastError::NeedViaThinPtr | CastError::NeedViaPtr => { - let mut err = fcx.type_error_struct(self.span, - |actual| { - format!("casting `{}` as `{}` is invalid", - actual, - fcx.ty_to_string(self.cast_ty)) - }, - self.expr_ty); + let mut err = make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, + self.cast_ty, fcx); if self.cast_ty.is_uint() { err.help(&format!("cast through {} first", match e { @@ -184,13 +188,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { err.emit(); } CastError::NeedViaInt => { - fcx.type_error_struct(self.span, - |actual| { - format!("casting `{}` as `{}` is invalid", - actual, - fcx.ty_to_string(self.cast_ty)) - }, - self.expr_ty) + make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, self.cast_ty, fcx) .help(&format!("cast through {} first", match e { CastError::NeedViaInt => "an integer", @@ -198,6 +196,15 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { })) .emit(); } + CastError::IllegalCast => { + make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, self.cast_ty, fcx) + .emit(); + } + CastError::DifferingKinds => { + make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, self.cast_ty, fcx) + .note("vtable kinds may not match") + .emit(); + } CastError::CastToBool => { struct_span_err!(fcx.tcx.sess, self.span, E0054, "cannot cast as `bool`") .span_label(self.span, "unsupported cast") @@ -205,51 +212,23 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { .emit(); } CastError::CastToChar => { - fcx.type_error_message(self.span, - |actual| { - format!("only `u8` can be cast as `char`, not `{}`", - actual) - }, - self.expr_ty); + type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0604, + "only `u8` can be cast as `char`, not `{}`", self.expr_ty).emit(); } CastError::NonScalar => { - fcx.type_error_message(self.span, - |actual| { - format!("non-scalar cast: `{}` as `{}`", - actual, - fcx.ty_to_string(self.cast_ty)) - }, - self.expr_ty); - } - CastError::IllegalCast => { - fcx.type_error_message(self.span, - |actual| { - format!("casting `{}` as `{}` is invalid", - actual, - fcx.ty_to_string(self.cast_ty)) - }, - self.expr_ty); + type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0605, + "non-primitive cast: `{}` as `{}`", + self.expr_ty, + fcx.ty_to_string(self.cast_ty)) + .note("an `as` expression can only be used to convert between \ + primitive types. Consider using the `From` trait") + .emit(); } CastError::SizedUnsizedCast => { - fcx.type_error_message(self.span, - |actual| { - format!("cannot cast thin pointer `{}` to fat pointer \ - `{}`", - actual, - fcx.ty_to_string(self.cast_ty)) - }, - self.expr_ty) - } - CastError::DifferingKinds => { - fcx.type_error_struct(self.span, - |actual| { - format!("casting `{}` as `{}` is invalid", - actual, - fcx.ty_to_string(self.cast_ty)) - }, - self.expr_ty) - .note("vtable kinds may not match") - .emit(); + type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0607, + "cannot cast thin pointer `{}` to fat pointer `{}`", + self.expr_ty, + fcx.ty_to_string(self.cast_ty)).emit(); } } } @@ -260,12 +239,10 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { } let tstr = fcx.ty_to_string(self.cast_ty); - let mut err = - fcx.type_error_struct(self.span, - |actual| { - format!("cast to unsized type: `{}` as `{}`", actual, tstr) - }, - self.expr_ty); + let mut err = type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0620, + "cast to unsized type: `{}` as `{}`", + fcx.resolve_type_vars_if_possible(&self.expr_ty), + tstr); match self.expr_ty.sty { ty::TyRef(_, ty::TypeAndMut { mutbl: mt, .. }) => { let mtstr = match mt { @@ -377,8 +354,9 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { (Some(t_from), Some(t_cast)) => (t_from, t_cast), // Function item types may need to be reified before casts. (None, Some(t_cast)) => { - if let ty::TyFnDef(.., f) = self.expr_ty.sty { + if let ty::TyFnDef(..) = self.expr_ty.sty { // Attempt a coercion to a fn pointer type. + let f = self.expr_ty.fn_sig(fcx.tcx); let res = fcx.try_coerce(self.expr, self.expr_ty, self.expr_diverges, diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 30ac7b4bfb9..968e893b9a0 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -76,6 +76,7 @@ use rustc::ty::relate::RelateResult; use rustc::ty::subst::Subst; use errors::DiagnosticBuilder; use syntax::abi; +use syntax::feature_gate; use syntax::ptr::P; use syntax_pos; @@ -210,13 +211,13 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { } match a.sty { - ty::TyFnDef(.., a_f) => { + ty::TyFnDef(..) => { // Function items are coercible to any closure // type; function pointers are not (that would // require double indirection). // Additionally, we permit coercion of function // items to drop the unsafe qualifier. - self.coerce_from_fn_item(a, a_f, b) + self.coerce_from_fn_item(a, b) } ty::TyFnPtr(a_f) => { // We permit coercion of fn pointers to drop the @@ -520,6 +521,8 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { coerce_source, &[coerce_target])); + let mut has_unsized_tuple_coercion = false; + // Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid // emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where // inference might unify those two inner type variables later. @@ -527,7 +530,15 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { while let Some(obligation) = queue.pop_front() { debug!("coerce_unsized resolve step: {:?}", obligation); let trait_ref = match obligation.predicate { - ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => tr.clone(), + ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => { + if unsize_did == tr.def_id() { + if let ty::TyTuple(..) = tr.0.input_types().nth(1).unwrap().sty { + debug!("coerce_unsized: found unsized tuple coercion"); + has_unsized_tuple_coercion = true; + } + } + tr.clone() + } _ => { coercion.obligations.push(obligation); continue; @@ -557,6 +568,14 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { } } + if has_unsized_tuple_coercion && !self.tcx.sess.features.borrow().unsized_tuple_coercion { + feature_gate::emit_feature_err(&self.tcx.sess.parse_sess, + "unsized_tuple_coercion", + self.cause.span, + feature_gate::GateIssue::Language, + feature_gate::EXPLAIN_UNSIZED_TUPLE_COERCION); + } + Ok(coercion) } @@ -600,7 +619,6 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { fn coerce_from_fn_item(&self, a: Ty<'tcx>, - fn_ty_a: ty::PolyFnSig<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> { //! Attempts to coerce from the type of a Rust function item @@ -612,9 +630,17 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { match b.sty { ty::TyFnPtr(_) => { - let a_fn_pointer = self.tcx.mk_fn_ptr(fn_ty_a); - self.coerce_from_safe_fn(a_fn_pointer, fn_ty_a, b, - simple(Adjust::ReifyFnPointer), simple(Adjust::ReifyFnPointer)) + let a_sig = a.fn_sig(self.tcx); + let InferOk { value: a_sig, mut obligations } = + self.normalize_associated_types_in_as_infer_ok(self.cause.span, &a_sig); + + let a_fn_pointer = self.tcx.mk_fn_ptr(a_sig); + let InferOk { value, obligations: o2 } = + self.coerce_from_safe_fn(a_fn_pointer, a_sig, b, + simple(Adjust::ReifyFnPointer), simple(Adjust::ReifyFnPointer))?; + + obligations.extend(o2); + Ok(InferOk { value, obligations }) } _ => self.unify_and(a, b, identity), } @@ -639,7 +665,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { // `extern "rust-call" fn((arg0,arg1,...)) -> _` // to // `fn(arg0,arg1,...) -> _` - let sig = self.closure_type(def_id_a).subst(self.tcx, substs_a.substs); + let sig = self.fn_sig(def_id_a).subst(self.tcx, substs_a.substs); let converted_sig = sig.map_bound(|s| { let params_iter = match s.inputs()[0].sty { ty::TyTuple(params, _) => { @@ -775,42 +801,41 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Special-case that coercion alone cannot handle: // Two function item types of differing IDs or Substs. - match (&prev_ty.sty, &new_ty.sty) { - (&ty::TyFnDef(a_def_id, a_substs, a_fty), &ty::TyFnDef(b_def_id, b_substs, b_fty)) => { - // The signature must always match. - let fty = self.at(cause, self.param_env) - .trace(prev_ty, new_ty) - .lub(&a_fty, &b_fty) - .map(|ok| self.register_infer_ok_obligations(ok))?; + if let (&ty::TyFnDef(..), &ty::TyFnDef(..)) = (&prev_ty.sty, &new_ty.sty) { + // Don't reify if the function types have a LUB, i.e. they + // are the same function and their parameters have a LUB. + let lub_ty = self.commit_if_ok(|_| { + self.at(cause, self.param_env) + .lub(prev_ty, new_ty) + .map(|ok| self.register_infer_ok_obligations(ok)) + }); - if a_def_id == b_def_id { - // Same function, maybe the parameters match. - let substs = self.commit_if_ok(|_| { - self.at(cause, self.param_env) - .trace(prev_ty, new_ty) - .lub(&a_substs, &b_substs) - .map(|ok| self.register_infer_ok_obligations(ok)) - }); - - if let Ok(substs) = substs { - // We have a LUB of prev_ty and new_ty, just return it. - return Ok(self.tcx.mk_fn_def(a_def_id, substs, fty)); - } - } - - // Reify both sides and return the reified fn pointer type. - let fn_ptr = self.tcx.mk_fn_ptr(fty); - for expr in exprs.iter().map(|e| e.as_coercion_site()).chain(Some(new)) { - // The only adjustment that can produce an fn item is - // `NeverToAny`, so this should always be valid. - self.apply_adjustments(expr, vec![Adjustment { - kind: Adjust::ReifyFnPointer, - target: fn_ptr - }]); - } - return Ok(fn_ptr); + if lub_ty.is_ok() { + // We have a LUB of prev_ty and new_ty, just return it. + return lub_ty; } - _ => {} + + // The signature must match. + let a_sig = prev_ty.fn_sig(self.tcx); + let a_sig = self.normalize_associated_types_in(new.span, &a_sig); + let b_sig = new_ty.fn_sig(self.tcx); + let b_sig = self.normalize_associated_types_in(new.span, &b_sig); + let sig = self.at(cause, self.param_env) + .trace(prev_ty, new_ty) + .lub(&a_sig, &b_sig) + .map(|ok| self.register_infer_ok_obligations(ok))?; + + // Reify both sides and return the reified fn pointer type. + let fn_ptr = self.tcx.mk_fn_ptr(sig); + for expr in exprs.iter().map(|e| e.as_coercion_site()).chain(Some(new)) { + // The only adjustment that can produce an fn item is + // `NeverToAny`, so this should always be valid. + self.apply_adjustments(expr, vec![Adjustment { + kind: Adjust::ReifyFnPointer, + target: fn_ptr + }]); + } + return Ok(fn_ptr); } let mut coerce = Coerce::new(self, cause.clone()); @@ -1162,6 +1187,18 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E> "`return;` in a function whose return type is not `()`"); db.span_label(cause.span, "return type is not ()"); } + ObligationCauseCode::BlockTailExpression(blk_id) => { + db = fcx.report_mismatched_types(cause, expected, found, err); + + let expr = expression.unwrap_or_else(|| { + span_bug!(cause.span, + "supposed to be part of a block tail expression, but the \ + expression is empty"); + }); + fcx.suggest_mismatched_types_on_tail(&mut db, expr, + expected, found, + cause.span, blk_id); + } _ => { db = fcx.report_mismatched_types(cause, expected, found, err); } diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 29742469f84..bf134f9547d 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -256,17 +256,10 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Compute skolemized form of impl and trait method tys. let tcx = infcx.tcx; - let m_sig = |method: &ty::AssociatedItem| { - match tcx.type_of(method.def_id).sty { - ty::TyFnDef(_, _, f) => f, - _ => bug!() - } - }; - let (impl_sig, _) = infcx.replace_late_bound_regions_with_fresh_var(impl_m_span, infer::HigherRankedType, - &m_sig(impl_m)); + &tcx.fn_sig(impl_m.def_id)); let impl_sig = inh.normalize_associated_types_in(impl_m_span, impl_m_node_id, @@ -277,7 +270,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let trait_sig = inh.liberate_late_bound_regions( impl_m.def_id, - &m_sig(trait_m)); + &tcx.fn_sig(trait_m.def_id)); let trait_sig = trait_sig.subst(tcx, trait_to_skol_substs); let trait_sig = @@ -335,7 +328,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Check that all obligations are satisfied by the implementation's // version. if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(errors); + infcx.report_fulfillment_errors(errors, None); return Err(ErrorReported); } @@ -507,8 +500,7 @@ fn compare_self_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty::ImplContainer(_) => impl_trait_ref.self_ty(), ty::TraitContainer(_) => tcx.mk_self_type() }; - let method_ty = tcx.type_of(method.def_id); - let self_arg_ty = *method_ty.fn_sig().input(0).skip_binder(); + let self_arg_ty = *tcx.fn_sig(method.def_id).input(0).skip_binder(); match ExplicitSelf::determine(untransformed_self_ty, self_arg_ty) { ExplicitSelf::ByValue => "self".to_string(), ExplicitSelf::ByReference(_, hir::MutImmutable) => "&self".to_string(), @@ -637,14 +629,8 @@ fn compare_number_of_method_arguments<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_m: &ty::AssociatedItem, trait_item_span: Option) -> Result<(), ErrorReported> { - let m_fty = |method: &ty::AssociatedItem| { - match tcx.type_of(method.def_id).sty { - ty::TyFnDef(_, _, f) => f, - _ => bug!() - } - }; - let impl_m_fty = m_fty(impl_m); - let trait_m_fty = m_fty(trait_m); + let impl_m_fty = tcx.fn_sig(impl_m.def_id); + let trait_m_fty = tcx.fn_sig(trait_m.def_id); let trait_number_args = trait_m_fty.inputs().skip_binder().len(); let impl_number_args = impl_m_fty.inputs().skip_binder().len(); if trait_number_args != impl_number_args { @@ -807,7 +793,7 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Check that all obligations are satisfied by the implementation's // version. if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(errors); + infcx.report_fulfillment_errors(errors, None); return; } diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 1b6f96cf651..f54ad541872 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -73,15 +73,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } + pub fn demand_coerce(&self, expr: &hir::Expr, checked_ty: Ty<'tcx>, expected: Ty<'tcx>) { + if let Some(mut err) = self.demand_coerce_diag(expr, checked_ty, expected) { + err.emit(); + } + } + // Checks that the type of `expr` can be coerced to `expected`. // // NB: This code relies on `self.diverges` to be accurate. In // particular, assignments to `!` will be permitted if the // diverges flag is currently "always". - pub fn demand_coerce(&self, - expr: &hir::Expr, - checked_ty: Ty<'tcx>, - expected: Ty<'tcx>) { + pub fn demand_coerce_diag(&self, + expr: &hir::Expr, + checked_ty: Ty<'tcx>, + expected: Ty<'tcx>) -> Option> { let expected = self.resolve_type_vars_with_obligations(expected); if let Err(e) = self.try_coerce(expr, checked_ty, self.diverges.get(), expected) { @@ -105,8 +111,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.get_best_match(&suggestions).join("\n"))); } } - err.emit(); + return Some(err); } + None } fn format_method_suggestion(&self, method: &AssociatedItem) -> String { @@ -143,12 +150,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn has_no_input_arg(&self, method: &AssociatedItem) -> bool { match method.def() { Def::Method(def_id) => { - match self.tcx.type_of(def_id).sty { - ty::TypeVariants::TyFnDef(_, _, sig) => { - sig.inputs().skip_binder().len() == 1 - } - _ => false, - } + self.tcx.fn_sig(def_id).inputs().skip_binder().len() == 1 } _ => false, } diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 93057f91997..ed22cd1333e 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -110,7 +110,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>( if let Err(ref errors) = fulfillment_cx.select_all_or_error(&infcx) { // this could be reached when we get lazy normalization - infcx.report_fulfillment_errors(errors); + infcx.report_fulfillment_errors(errors, None); return Err(ErrorReported); } diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 4d9f50b0fc0..96643ae72ab 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -13,7 +13,6 @@ use intrinsics; use rustc::traits::{ObligationCause, ObligationCauseCode}; -use rustc::ty::subst::Substs; use rustc::ty::{self, TyCtxt, Ty}; use rustc::util::nodemap::FxHashMap; use require_same_types; @@ -35,22 +34,22 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, output: Ty<'tcx>) { let def_id = tcx.hir.local_def_id(it.id); - let substs = Substs::for_item(tcx, def_id, - |_, _| tcx.types.re_erased, - |def, _| tcx.mk_param_from_def(def)); + match it.node { + hir::ForeignItemFn(..) => {} + _ => { + struct_span_err!(tcx.sess, it.span, E0622, + "intrinsic must be a function") + .span_label(it.span, "expected a function") + .emit(); + return; + } + } - let fty = tcx.mk_fn_def(def_id, substs, ty::Binder(tcx.mk_fn_sig( - inputs.into_iter(), - output, - false, - hir::Unsafety::Unsafe, - abi - ))); let i_n_tps = tcx.generics_of(def_id).types.len(); if i_n_tps != n_tps { let span = match it.node { hir::ForeignItemFn(_, _, ref generics) => generics.span, - hir::ForeignItemStatic(..) => it.span + _ => bug!() }; struct_span_err!(tcx.sess, span, E0094, @@ -59,14 +58,18 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, i_n_tps, n_tps) .span_label(span, format!("expected {} type parameter", n_tps)) .emit(); - } else { - require_same_types(tcx, - &ObligationCause::new(it.span, - it.id, - ObligationCauseCode::IntrinsicType), - tcx.type_of(def_id), - fty); + return; } + + let fty = tcx.mk_fn_ptr(ty::Binder(tcx.mk_fn_sig( + inputs.into_iter(), + output, + false, + hir::Unsafety::Unsafe, + abi + ))); + let cause = ObligationCause::new(it.span, it.id, ObligationCauseCode::IntrinsicType); + require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(def_id)), fty); } /// Remember to add all intrinsics here, in librustc_trans/trans/intrinsic.rs, @@ -376,7 +379,7 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut structural_to_nomimal = FxHashMap(); - let sig = tcx.type_of(def_id).fn_sig(); + let sig = tcx.fn_sig(def_id); let sig = tcx.no_late_bound_regions(&sig).unwrap(); if intr.inputs.len() != sig.inputs().len() { span_err!(tcx.sess, it.span, E0444, diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 36bd6657389..209245187b1 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -375,7 +375,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { debug!("method_predicates after subst = {:?}", method_predicates); - let sig = self.tcx.type_of(def_id).fn_sig(); + let sig = self.tcx.fn_sig(def_id); // Instantiate late-bound regions and substitute the trait // parameters into the method type to get the actual method type. diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 73c1215f275..4f4169ac93d 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -235,7 +235,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // NB: Instantiate late-bound regions first so that // `instantiate_type_scheme` can normalize associated types that // may reference those regions. - let fn_sig = tcx.type_of(def_id).fn_sig(); + let fn_sig = tcx.fn_sig(def_id); let fn_sig = self.replace_late_bound_regions_with_fresh_var(span, infer::FnCall, &fn_sig).0; diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 2518a1739f7..ee9a347ae95 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -673,7 +673,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { expected: ty::Ty<'tcx>) -> bool { match method.def() { Def::Method(def_id) => { - let fty = self.tcx.type_of(def_id).fn_sig(); + let fty = self.tcx.fn_sig(def_id); self.probe(|_| { let substs = self.fresh_substs_for_item(self.span, method.def_id); let output = fty.output().subst(self.tcx, substs); @@ -1288,7 +1288,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { impl_ty: Ty<'tcx>, substs: &Substs<'tcx>) -> Ty<'tcx> { - let self_ty = self.tcx.type_of(method).fn_sig().input(0); + let self_ty = self.tcx.fn_sig(method).input(0); debug!("xform_self_ty(impl_ty={:?}, self_ty={:?}, substs={:?})", impl_ty, self_ty, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 2bf24d5b350..3241267bbc2 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -102,7 +102,7 @@ use rustc::ty::maps::Providers; use rustc::ty::util::{Representability, IntTypeExt}; use errors::DiagnosticBuilder; use require_c_abi_if_variadic; -use session::{Session, CompileResult}; +use session::{CompileIncomplete, Session}; use TypeAndSubsts; use lint; use util::common::{ErrorReported, indenter}; @@ -124,6 +124,7 @@ use syntax_pos::{self, BytePos, Span}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::itemlikevisit::ItemLikeVisitor; +use rustc::hir::map::Node; use rustc::hir::{self, PatKind}; use rustc::middle::lang_items; use rustc_back::slice; @@ -216,6 +217,8 @@ pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { /// environment is for an item or something where the "callee" is /// not clear. implicit_region_bound: Option>, + + body_id: Option, } impl<'a, 'gcx, 'tcx> Deref for Inherited<'a, 'gcx, 'tcx> { @@ -604,6 +607,7 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { deferred_cast_checks: RefCell::new(Vec::new()), anon_types: RefCell::new(NodeMap()), implicit_region_bound, + body_id, } } @@ -687,30 +691,32 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> { fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem) { } } -pub fn check_wf_new<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CompileResult { +pub fn check_wf_new<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), ErrorReported> { tcx.sess.track_errors(|| { let mut visit = wfcheck::CheckTypeWellFormedVisitor::new(tcx); tcx.hir.krate().visit_all_item_likes(&mut visit.as_deep_visitor()); }) } -pub fn check_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CompileResult { +pub fn check_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), ErrorReported> { tcx.sess.track_errors(|| { tcx.hir.krate().visit_all_item_likes(&mut CheckItemTypesVisitor { tcx }); }) } -pub fn check_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CompileResult { +pub fn check_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), CompileIncomplete> { tcx.typeck_item_bodies(LOCAL_CRATE) } -fn typeck_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) -> CompileResult { +fn typeck_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) + -> Result<(), CompileIncomplete> +{ debug_assert!(crate_num == LOCAL_CRATE); - tcx.sess.track_errors(|| { + Ok(tcx.sess.track_errors(|| { for body_owner_def_id in tcx.body_owners() { tcx.typeck_tables_of(body_owner_def_id); } - }) + })?) } pub fn provide(providers: &mut Providers) { @@ -718,20 +724,12 @@ pub fn provide(providers: &mut Providers) { typeck_item_bodies, typeck_tables_of, has_typeck_tables, - closure_type, closure_kind, adt_destructor, ..*providers }; } -fn closure_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId) - -> ty::PolyFnSig<'tcx> { - let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); - tcx.typeck_tables_of(def_id).closure_tys[&node_id] -} - fn closure_kind<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::ClosureKind { @@ -844,7 +842,7 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, Inherited::build(tcx, def_id).enter(|inh| { let param_env = tcx.param_env(def_id); let fcx = if let Some(decl) = fn_decl { - let fn_sig = tcx.type_of(def_id).fn_sig(); + let fn_sig = tcx.fn_sig(def_id); check_abi(tcx, span, fn_sig.abi()); @@ -985,7 +983,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, *fcx.ps.borrow_mut() = UnsafetyState::function(fn_sig.unsafety, fn_id); let ret_ty = fn_sig.output(); - fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::ReturnType); + fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::SizedReturnType); let ret_ty = fcx.instantiate_anon_types(&ret_ty); fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(ret_ty))); fn_sig = fcx.tcx.mk_fn_sig( @@ -1000,16 +998,17 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, // Add formal parameters. for (arg_ty, arg) in fn_sig.inputs().iter().zip(&body.arguments) { - // The type of the argument must be well-formed. - // - // NB -- this is now checked in wfcheck, but that - // currently only results in warnings, so we issue an - // old-style WF obligation here so that we still get the - // errors that we used to get. - fcx.register_old_wf_obligation(arg_ty, arg.pat.span, traits::MiscObligation); - // Check the pattern. fcx.check_pat_arg(&arg.pat, arg_ty, true); + + // Check that argument is Sized. + // The check for a non-trivial pattern is a hack to avoid duplicate warnings + // for simple cases like `fn foo(x: Trait)`, + // where we would error once on the parameter as a whole, and once on the binding `x`. + if arg.pat.simple_name().is_none() { + fcx.require_type_is_sized(arg_ty, decl.output.span(), traits::MiscObligation); + } + fcx.write_ty(arg.id, arg_ty); } @@ -1908,7 +1907,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Require that the predicate holds for the concrete type. let cause = traits::ObligationCause::new(span, self.body_id, - traits::ReturnType); + traits::SizedReturnType); self.register_predicate(traits::Obligation::new(cause, self.param_env, predicate)); @@ -1985,17 +1984,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } - /// Registers an obligation for checking later, during regionck, that the type `ty` must - /// outlive the region `r`. - pub fn register_region_obligation(&self, - ty: Ty<'tcx>, - region: ty::Region<'tcx>, - cause: traits::ObligationCause<'tcx>) - { - let mut fulfillment_cx = self.fulfillment_cx.borrow_mut(); - fulfillment_cx.register_region_obligation(ty, region, cause); - } - /// Registers an obligation for checking later, during regionck, that the type `ty` must /// outlive the region `r`. pub fn register_wf_obligation(&self, @@ -2010,21 +1998,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty::Predicate::WellFormed(ty))); } - pub fn register_old_wf_obligation(&self, - ty: Ty<'tcx>, - span: Span, - code: traits::ObligationCauseCode<'tcx>) - { - // Registers an "old-style" WF obligation that uses the - // implicator code. This is basically a buggy version of - // `register_wf_obligation` that is being kept around - // temporarily just to help with phasing in the newer rules. - // - // FIXME(#27579) all uses of this should be migrated to register_wf_obligation eventually - let cause = traits::ObligationCause::new(span, self.body_id, code); - self.register_region_obligation(ty, self.tcx.types.re_empty, cause); - } - /// Registers obligations that all types appearing in `substs` are well-formed. pub fn add_wf_bounds(&self, substs: &Substs<'tcx>, expr: &hir::Expr) { @@ -2152,7 +2125,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { match fulfillment_cx.select_all_or_error(self) { Ok(()) => { } - Err(errors) => { self.report_fulfillment_errors(&errors); } + Err(errors) => { self.report_fulfillment_errors(&errors, self.inh.body_id); } } } @@ -2160,7 +2133,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn select_obligations_where_possible(&self) { match self.fulfillment_cx.borrow_mut().select_where_possible(self) { Ok(()) => { } - Err(errors) => { self.report_fulfillment_errors(&errors); } + Err(errors) => { self.report_fulfillment_errors(&errors, self.inh.body_id); } } } @@ -2173,7 +2146,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { -> ty::TypeAndMut<'tcx> { // extract method return type, which will be &T; - // all LB regions should have been instantiated during method lookup let ret_ty = method.sig.output(); // method returns &T, but the type as visible to user is T, so deref @@ -2580,8 +2552,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty::TyUint(ast::UintTy::U8) | ty::TyUint(ast::UintTy::U16) => { variadic_error(tcx.sess, arg.span, arg_ty, "c_uint"); } - ty::TyFnDef(.., f) => { - let ptr_ty = self.tcx.mk_fn_ptr(f); + ty::TyFnDef(..) => { + let ptr_ty = self.tcx.mk_fn_ptr(arg_ty.fn_sig(self.tcx)); let ptr_ty = self.resolve_type_vars_if_possible(&ptr_ty); variadic_error(tcx.sess, arg.span, arg_ty, &format!("{}", ptr_ty)); } @@ -2848,10 +2820,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { "check_return_expr called outside fn body")); let ret_ty = ret_coercion.borrow().expected_ty(); - let return_expr_ty = self.check_expr_with_hint(return_expr, ret_ty); + let return_expr_ty = self.check_expr_with_hint(return_expr, ret_ty.clone()); ret_coercion.borrow_mut() .coerce(self, - &self.misc(return_expr.span), + &self.cause(return_expr.span, + ObligationCauseCode::ReturnType(return_expr.id)), return_expr, return_expr_ty, self.diverges.get()); @@ -3154,11 +3127,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let adt_ty_hint = self.expected_inputs_for_expected_output(span, expected, adt_ty, &[adt_ty]) - .get(0).cloned().unwrap_or(adt_ty); + .get(0).cloned().unwrap_or(adt_ty); + // re-link the regions that EIfEO can erase. + self.demand_eqtype(span, adt_ty_hint, adt_ty); - let (substs, hint_substs, adt_kind, kind_name) = match (&adt_ty.sty, &adt_ty_hint.sty) { - (&ty::TyAdt(adt, substs), &ty::TyAdt(_, hint_substs)) => { - (substs, hint_substs, adt.adt_kind(), adt.variant_descr()) + let (substs, adt_kind, kind_name) = match &adt_ty.sty{ + &ty::TyAdt(adt, substs) => { + (substs, adt.adt_kind(), adt.variant_descr()) } _ => span_bug!(span, "non-ADT passed to check_expr_struct_fields") }; @@ -3174,14 +3149,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Typecheck each field. for field in ast_fields { - let final_field_type; - let field_type_hint; - let ident = tcx.adjust(field.name.node, variant.did, self.body_id).0; - if let Some(v_field) = remaining_fields.remove(&ident) { - final_field_type = self.field_ty(field.span, v_field, substs); - field_type_hint = self.field_ty(field.span, v_field, hint_substs); - + let field_type = if let Some(v_field) = remaining_fields.remove(&ident) { seen_fields.insert(field.name.node, field.span); // we don't look at stability attributes on @@ -3190,10 +3159,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if adt_kind != ty::AdtKind::Enum { tcx.check_stability(v_field.did, expr_id, field.span); } + + self.field_ty(field.span, v_field, substs) } else { error_happened = true; - final_field_type = tcx.types.err; - field_type_hint = tcx.types.err; if let Some(_) = variant.find_field_named(field.name.node) { let mut err = struct_span_err!(self.tcx.sess, field.name.span, @@ -3211,12 +3180,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } else { self.report_unknown_field(adt_ty, variant, field, ast_fields, kind_name); } - } + + tcx.types.err + }; // Make sure to give a type to the field even if there's // an error, so we can continue typechecking - let ty = self.check_expr_with_hint(&field.expr, field_type_hint); - self.demand_coerce(&field.expr, ty, final_field_type); + self.check_expr_coercable_to_type(&field.expr, field_type); } // Make sure the programmer specified correct number of fields. @@ -3883,6 +3853,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if tuple.references_error() { tcx.types.err } else { + self.require_type_is_sized(tuple, expr.span, traits::TupleInitializerSized); tuple } } @@ -4170,8 +4141,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut coerce = ctxt.coerce.as_mut().unwrap(); if let Some(tail_expr_ty) = tail_expr_ty { let tail_expr = tail_expr.unwrap(); + let cause = self.cause(tail_expr.span, + ObligationCauseCode::BlockTailExpression(blk.id)); coerce.coerce(self, - &self.misc(tail_expr.span), + &cause, tail_expr, tail_expr_ty, self.diverges.get()); @@ -4210,6 +4183,130 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty } + /// Given a `NodeId`, return the `FnDecl` of the method it is enclosed by and whether it is + /// `fn main` if it is a method, `None` otherwise. + pub fn get_fn_decl(&self, blk_id: ast::NodeId) -> Option<(hir::FnDecl, bool)> { + // Get enclosing Fn, if it is a function or a trait method, unless there's a `loop` or + // `while` before reaching it, as block tail returns are not available in them. + if let Some(fn_id) = self.tcx.hir.get_return_block(blk_id) { + let parent = self.tcx.hir.get(fn_id); + + if let Node::NodeItem(&hir::Item { + name, node: hir::ItemFn(ref decl, ..), .. + }) = parent { + decl.clone().and_then(|decl| { + // This is less than ideal, it will not present the return type span on any + // method called `main`, regardless of whether it is actually the entry point. + Some((decl, name == Symbol::intern("main"))) + }) + } else if let Node::NodeTraitItem(&hir::TraitItem { + node: hir::TraitItemKind::Method(hir::MethodSig { + ref decl, .. + }, ..), .. + }) = parent { + decl.clone().and_then(|decl| { + Some((decl, false)) + }) + } else { + None + } + } else { + None + } + } + + /// On implicit return expressions with mismatched types, provide the following suggestions: + /// + /// - Point out the method's return type as the reason for the expected type + /// - Possible missing semicolon + /// - Possible missing return type if the return type is the default, and not `fn main()` + pub fn suggest_mismatched_types_on_tail(&self, + err: &mut DiagnosticBuilder<'tcx>, + expression: &'gcx hir::Expr, + expected: Ty<'tcx>, + found: Ty<'tcx>, + cause_span: Span, + blk_id: ast::NodeId) { + self.suggest_missing_semicolon(err, expression, expected, cause_span); + + if let Some((fn_decl, is_main)) = self.get_fn_decl(blk_id) { + // `fn main()` must return `()`, do not suggest changing return type + if !is_main { + self.suggest_missing_return_type(err, &fn_decl, found); + } + } + } + + /// A common error is to forget to add a semicolon at the end of a block: + /// + /// ``` + /// fn foo() { + /// bar_that_returns_u32() + /// } + /// ``` + /// + /// This routine checks if the return expression in a block would make sense on its own as a + /// statement and the return type has been left as defaultor has been specified as `()`. If so, + /// it suggests adding a semicolon. + fn suggest_missing_semicolon(&self, + err: &mut DiagnosticBuilder<'tcx>, + expression: &'gcx hir::Expr, + expected: Ty<'tcx>, + cause_span: Span) { + if expected.is_nil() { + // `BlockTailExpression` only relevant if the tail expr would be + // useful on its own. + match expression.node { + hir::ExprCall(..) | + hir::ExprMethodCall(..) | + hir::ExprIf(..) | + hir::ExprWhile(..) | + hir::ExprLoop(..) | + hir::ExprMatch(..) | + hir::ExprBlock(..) => { + let sp = cause_span.next_point(); + err.span_suggestion(sp, + "did you mean to add a semicolon here?", + ";".to_string()); + } + _ => (), + } + } + } + + + /// A possible error is to forget to add a return type that is needed: + /// + /// ``` + /// fn foo() { + /// bar_that_returns_u32() + /// } + /// ``` + /// + /// This routine checks if the return type is left as default, the method is not part of an + /// `impl` block and that it isn't the `main` method. If so, it suggests setting the return + /// type. + fn suggest_missing_return_type(&self, + err: &mut DiagnosticBuilder<'tcx>, + fn_decl: &hir::FnDecl, + ty: Ty<'tcx>) { + + // Only recommend changing the return type for methods that + // haven't set a return type at all (and aren't `fn main()` or an impl). + if let &hir::FnDecl { + output: hir::FunctionRetTy::DefaultReturn(span), .. + } = fn_decl { + if ty.is_suggestable() { + err.span_suggestion(span, + "possibly return type missing here?", + format!("-> {} ", ty)); + } else { + err.span_label(span, "possibly return type missing here?"); + } + } + } + + /// A common error is to add an extra semicolon: /// /// ``` @@ -4245,7 +4342,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { hi: original_span.hi, ctxt: original_span.ctxt, }; - err.span_help(span_semi, "consider removing this semicolon:"); + err.span_suggestion(span_semi, "consider removing this semicolon", "".to_string()); } // Instantiates the given path, which must refer to an item with the given @@ -4619,9 +4716,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // If not, error. if alternative.is_ty_var() || alternative.references_error() { if !self.is_tainted_by_errors() { - self.type_error_message(sp, |_actual| { - "the type of this value must be known in this context".to_string() - }, ty); + type_error_struct!(self.tcx.sess, sp, ty, E0619, + "the type of this value must be known in this context") + .emit(); } self.demand_suptype(sp, self.tcx.types.err, ty); ty = self.tcx.types.err; diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 26f708e9345..cbda1227742 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -177,12 +177,11 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { } ty::AssociatedKind::Method => { reject_shadowing_type_parameters(fcx.tcx, item.def_id); - let method_ty = fcx.tcx.type_of(item.def_id); - let method_ty = fcx.normalize_associated_types_in(span, &method_ty); + let sig = fcx.tcx.fn_sig(item.def_id); + let sig = fcx.normalize_associated_types_in(span, &sig); let predicates = fcx.tcx.predicates_of(item.def_id) .instantiate_identity(fcx.tcx); let predicates = fcx.normalize_associated_types_in(span, &predicates); - let sig = method_ty.fn_sig(); this.check_fn_or_method(fcx, span, sig, &predicates, item.def_id, &mut implied_bounds); let sig_if_method = sig_if_method.expect("bad signature for method"); @@ -331,9 +330,8 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { fn check_item_fn(&mut self, item: &hir::Item) { self.for_item(item).with_fcx(|fcx, this| { let def_id = fcx.tcx.hir.local_def_id(item.id); - let ty = fcx.tcx.type_of(def_id); - let item_ty = fcx.normalize_associated_types_in(item.span, &ty); - let sig = item_ty.fn_sig(); + let sig = fcx.tcx.fn_sig(def_id); + let sig = fcx.normalize_associated_types_in(item.span, &sig); let predicates = fcx.tcx.predicates_of(def_id).instantiate_identity(fcx.tcx); let predicates = fcx.normalize_associated_types_in(item.span, &predicates); @@ -461,9 +459,9 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { let span = method_sig.decl.inputs[0].span; - let method_ty = fcx.tcx.type_of(method.def_id); - let fty = fcx.normalize_associated_types_in(span, &method_ty); - let sig = fcx.liberate_late_bound_regions(method.def_id, &fty.fn_sig()); + let sig = fcx.tcx.fn_sig(method.def_id); + let sig = fcx.normalize_associated_types_in(span, &sig); + let sig = fcx.liberate_late_bound_regions(method.def_id, &sig); debug!("check_method_receiver: sig={:?}", sig); diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 4af262bcb78..81e5dae5477 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -377,7 +377,7 @@ impl<'cx, 'gcx, 'tcx> Resolver<'cx, 'gcx, 'tcx> { fn report_error(&self, t: Ty<'tcx>) { if !self.tcx.sess.has_errors() { - self.infcx.need_type_info(self.body.id(), self.span.to_span(&self.tcx), t); + self.infcx.need_type_info(Some(self.body.id()), self.span.to_span(&self.tcx), t); } } } diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index ccbc0299041..9305eff1436 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -386,7 +386,7 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Check that all transitive obligations are satisfied. if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(&errors); + infcx.report_fulfillment_errors(&errors, None); } // Finally, resolve all regions. diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index fb3bcd31e21..fd6dda5ccf4 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -97,6 +97,7 @@ pub fn provide(providers: &mut Providers) { type_param_predicates, trait_def, adt_def, + fn_sig, impl_trait_ref, impl_polarity, is_foreign_item, @@ -447,6 +448,9 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) { tcx.generics_of(def_id); tcx.type_of(def_id); tcx.predicates_of(def_id); + if let hir::ForeignItemFn(..) = item.node { + tcx.fn_sig(def_id); + } } } hir::ItemEnum(ref enum_definition, _) => { @@ -497,6 +501,9 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) { tcx.generics_of(def_id); tcx.type_of(def_id); tcx.predicates_of(def_id); + if let hir::ItemFn(..) = it.node { + tcx.fn_sig(def_id); + } } } } @@ -511,6 +518,9 @@ fn convert_trait_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_item_id: ast: hir::TraitItemKind::Type(_, Some(_)) | hir::TraitItemKind::Method(..) => { tcx.type_of(def_id); + if let hir::TraitItemKind::Method(..) = trait_item.node { + tcx.fn_sig(def_id); + } } hir::TraitItemKind::Type(_, None) => {} @@ -524,6 +534,9 @@ fn convert_impl_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_item_id: ast::N tcx.generics_of(def_id); tcx.type_of(def_id); tcx.predicates_of(def_id); + if let hir::ImplItemKind::Method(..) = tcx.hir.expect_impl_item(impl_item_id).node { + tcx.fn_sig(def_id); + } } fn convert_variant_ctor<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -963,10 +976,9 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, match tcx.hir.get(node_id) { NodeTraitItem(item) => { match item.node { - TraitItemKind::Method(ref sig, _) => { - let fty = AstConv::ty_of_fn(&icx, sig.unsafety, sig.abi, &sig.decl); + TraitItemKind::Method(..) => { let substs = Substs::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id, substs, fty) + tcx.mk_fn_def(def_id, substs) } TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => icx.to_ty(ty), @@ -978,10 +990,9 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, NodeImplItem(item) => { match item.node { - ImplItemKind::Method(ref sig, _) => { - let fty = AstConv::ty_of_fn(&icx, sig.unsafety, sig.abi, &sig.decl); + ImplItemKind::Method(..) => { let substs = Substs::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id, substs, fty) + tcx.mk_fn_def(def_id, substs) } ImplItemKind::Const(ref ty, _) => icx.to_ty(ty), ImplItemKind::Type(ref ty) => { @@ -1001,10 +1012,9 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ItemTy(ref t, _) | ItemImpl(.., ref t, _) => { icx.to_ty(t) } - ItemFn(ref decl, unsafety, _, abi, _, _) => { - let tofd = AstConv::ty_of_fn(&icx, unsafety, abi, &decl); + ItemFn(..) => { let substs = Substs::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id, substs, tofd) + tcx.mk_fn_def(def_id, substs) } ItemEnum(..) | ItemStruct(..) | @@ -1029,11 +1039,10 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } NodeForeignItem(foreign_item) => { - let abi = tcx.hir.get_foreign_abi(node_id); - match foreign_item.node { - ForeignItemFn(ref fn_decl, _, _) => { - compute_type_of_foreign_fn_decl(tcx, def_id, fn_decl, abi) + ForeignItemFn(..) => { + let substs = Substs::identity_for_item(tcx, def_id); + tcx.mk_fn_def(def_id, substs) } ForeignItemStatic(ref t, _) => icx.to_ty(t) } @@ -1041,21 +1050,13 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, NodeStructCtor(&ref def) | NodeVariant(&Spanned { node: hir::Variant_ { data: ref def, .. }, .. }) => { - let ty = tcx.type_of(tcx.hir.get_parent_did(node_id)); match *def { - VariantData::Unit(..) | VariantData::Struct(..) => ty, - VariantData::Tuple(ref fields, _) => { - let inputs = fields.iter().map(|f| { - tcx.type_of(tcx.hir.local_def_id(f.id)) - }); + VariantData::Unit(..) | VariantData::Struct(..) => { + tcx.type_of(tcx.hir.get_parent_did(node_id)) + } + VariantData::Tuple(..) => { let substs = Substs::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id, substs, ty::Binder(tcx.mk_fn_sig( - inputs, - ty, - false, - hir::Unsafety::Normal, - abi::Abi::Rust - ))) + tcx.mk_fn_def(def_id, substs) } } } @@ -1105,6 +1106,58 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } +fn fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId) + -> ty::PolyFnSig<'tcx> { + use rustc::hir::map::*; + use rustc::hir::*; + + let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); + + let icx = ItemCtxt::new(tcx, def_id); + + match tcx.hir.get(node_id) { + NodeTraitItem(&hir::TraitItem { node: TraitItemKind::Method(ref sig, _), .. }) | + NodeImplItem(&hir::ImplItem { node: ImplItemKind::Method(ref sig, _), .. }) => { + AstConv::ty_of_fn(&icx, sig.unsafety, sig.abi, &sig.decl) + } + + NodeItem(&hir::Item { node: ItemFn(ref decl, unsafety, _, abi, _, _), .. }) => { + AstConv::ty_of_fn(&icx, unsafety, abi, decl) + } + + NodeForeignItem(&hir::ForeignItem { node: ForeignItemFn(ref fn_decl, _, _), .. }) => { + let abi = tcx.hir.get_foreign_abi(node_id); + compute_sig_of_foreign_fn_decl(tcx, def_id, fn_decl, abi) + } + + NodeStructCtor(&VariantData::Tuple(ref fields, _)) | + NodeVariant(&Spanned { node: hir::Variant_ { + data: VariantData::Tuple(ref fields, _), .. + }, .. }) => { + let ty = tcx.type_of(tcx.hir.get_parent_did(node_id)); + let inputs = fields.iter().map(|f| { + tcx.type_of(tcx.hir.local_def_id(f.id)) + }); + ty::Binder(tcx.mk_fn_sig( + inputs, + ty, + false, + hir::Unsafety::Normal, + abi::Abi::Rust + )) + } + + NodeExpr(&hir::Expr { node: hir::ExprClosure(..), .. }) => { + tcx.typeck_tables_of(def_id).closure_tys[&node_id] + } + + x => { + bug!("unexpected sort of node in fn_sig(): {:?}", x); + } + } +} + fn impl_trait_ref<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Option> { @@ -1502,12 +1555,12 @@ fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>, } } -fn compute_type_of_foreign_fn_decl<'a, 'tcx>( +fn compute_sig_of_foreign_fn_decl<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, decl: &hir::FnDecl, abi: abi::Abi) - -> Ty<'tcx> + -> ty::PolyFnSig<'tcx> { let fty = AstConv::ty_of_fn(&ItemCtxt::new(tcx, def_id), hir::Unsafety::Unsafe, abi, decl); @@ -1533,8 +1586,7 @@ fn compute_type_of_foreign_fn_decl<'a, 'tcx>( } } - let substs = Substs::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id, substs, fty) + fty } fn is_foreign_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index bc5ba4c323d..37f6f3753d7 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4208,6 +4208,104 @@ println!("{}", v[2]); ``` "##, +E0604: r##" +A cast to `char` was attempted on a type other than `u8`. + +Erroneous code example: + +```compile_fail,E0604 +0u32 as char; // error: only `u8` can be cast as `char`, not `u32` +``` + +As the error message indicates, only `u8` can be cast into `char`. Example: + +``` +let c = 86u8 as char; // ok! +assert_eq!(c, 'V'); +``` + +For more information about casts, take a look at The Book: +https://doc.rust-lang.org/book/first-edition/casting-between-types.html +"##, + +E0605: r##" +An invalid cast was attempted. + +Erroneous code examples: + +```compile_fail,E0605 +let x = 0u8; +x as Vec; // error: non-primitive cast: `u8` as `std::vec::Vec` + +// Another example + +let v = 0 as *const u8; // So here, `v` is a `*const u8`. +v as &u8; // error: non-primitive cast: `*const u8` as `&u8` +``` + +Only primitive types can be cast into each other. Examples: + +``` +let x = 0u8; +x as u32; // ok! + +let v = 0 as *const u8; +v as *const i8; // ok! +``` + +For more information about casts, take a look at The Book: +https://doc.rust-lang.org/book/first-edition/casting-between-types.html +"##, + +E0606: r##" +An incompatible cast was attempted. + +Erroneous code example: + +```compile_fail,E0606 +let x = &0u8; // Here, `x` is a `&u8`. +let y: u32 = x as u32; // error: casting `&u8` as `u32` is invalid +``` + +When casting, keep in mind that only primitive types can be cast into each +other. Example: + +``` +let x = &0u8; +let y: u32 = *x as u32; // We dereference it first and then cast it. +``` + +For more information about casts, take a look at The Book: +https://doc.rust-lang.org/book/first-edition/casting-between-types.html +"##, + +E0607: r##" +A cast between a thin and a fat pointer was attempted. + +Erroneous code example: + +```compile_fail,E0607 +let v = 0 as *const u8; +v as *const [u8]; +``` + +First: what are thin and fat pointers? + +Thin pointers are "simple" pointers: they are purely a reference to a memory +address. + +Fat pointers are pointers referencing Dynamically Sized Types (also called DST). +DST don't have a statically known size, therefore they can only exist behind +some kind of pointers that contain additional information. Slices and trait +objects are DSTs. In the case of slices, the additional information the fat +pointer holds is their size. + +To fix this error, don't try to cast directly between thin and fat pointers. + +For more information about casts, take a look at The Book: +https://doc.rust-lang.org/book/first-edition/casting-between-types.html +"##, + E0609: r##" Attempted to access a non-existent field in a struct. @@ -4567,6 +4665,87 @@ i_am_a_function(); ``` "##, +E0619: r##" +The type-checker needed to know the type of an expression, but that type had not +yet been inferred. + +Erroneous code example: + +```compile_fail,E0619 +let mut x = vec![]; +match x.pop() { + Some(v) => { + // Here, the type of `v` is not (yet) known, so we + // cannot resolve this method call: + v.to_uppercase(); // error: the type of this value must be known in + // this context + } + None => {} +} +``` + +Type inference typically proceeds from the top of the function to the bottom, +figuring out types as it goes. In some cases -- notably method calls and +overloadable operators like `*` -- the type checker may not have enough +information *yet* to make progress. This can be true even if the rest of the +function provides enough context (because the type-checker hasn't looked that +far ahead yet). In this case, type annotations can be used to help it along. + +To fix this error, just specify the type of the variable. Example: + +``` +let mut x: Vec = vec![]; // We precise the type of the vec elements. +match x.pop() { + Some(v) => { + v.to_uppercase(); // Since rustc now knows the type of the vec elements, + // we can use `v`'s methods. + } + None => {} +} +``` +"##, + +E0620: r##" +A cast to an unsized type was attempted. + +Erroneous code example: + +```compile_fail,E0620 +let x = &[1_usize, 2] as [usize]; // error: cast to unsized type: `&[usize; 2]` + // as `[usize]` +``` + +In Rust, some types don't have a known size at compile-time. For example, in a +slice type like `[u32]`, the number of elements is not known at compile-time and +hence the overall size cannot be computed. As a result, such types can only be +manipulated through a reference (e.g., `&T` or `&mut T`) or other pointer-type +(e.g., `Box` or `Rc`). Try casting to a reference instead: + +``` +let x = &[1_usize, 2] as &[usize]; // ok! +``` +"##, + +E0622: r##" +An intrinsic was declared without being a function. + +Erroneous code example: + +```compile_fail,E0622 +#![feature(intrinsics)] +extern "rust-intrinsic" { + pub static breakpoint : unsafe extern "rust-intrinsic" fn(); + // error: intrinsic must be a function +} + +fn main() { unsafe { breakpoint(); } } +``` + +An intrinsic is a function available for use in a given programming language +whose implementation is handled specially by the compiler. In order to fix this +error, just declare a function. +"##, + } register_diagnostics! { diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 9e99af633d5..9b829e6e3ff 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -108,7 +108,7 @@ use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::maps::Providers; use rustc::traits::{FulfillmentContext, ObligationCause, ObligationCauseCode, Reveal}; -use session::config; +use session::{CompileIncomplete, config}; use util::common::time; use syntax::ast; @@ -166,7 +166,7 @@ fn require_same_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, match fulfill_cx.select_all_or_error(infcx) { Ok(()) => true, Err(errors) => { - infcx.report_fulfillment_errors(&errors); + infcx.report_fulfillment_errors(&errors, None); false } } @@ -198,22 +198,21 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } _ => () } - let substs = tcx.intern_substs(&[]); - let se_ty = tcx.mk_fn_def(main_def_id, substs, - ty::Binder(tcx.mk_fn_sig( + let se_ty = tcx.mk_fn_ptr(ty::Binder( + tcx.mk_fn_sig( iter::empty(), tcx.mk_nil(), false, hir::Unsafety::Normal, Abi::Rust - )) - ); + ) + )); require_same_types( tcx, &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType), se_ty, - main_t); + tcx.mk_fn_ptr(tcx.fn_sig(main_def_id))); } _ => { span_bug!(main_span, @@ -248,9 +247,8 @@ fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, _ => () } - let substs = tcx.intern_substs(&[]); - let se_ty = tcx.mk_fn_def(start_def_id, substs, - ty::Binder(tcx.mk_fn_sig( + let se_ty = tcx.mk_fn_ptr(ty::Binder( + tcx.mk_fn_sig( [ tcx.types.isize, tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8)) @@ -259,14 +257,14 @@ fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, false, hir::Unsafety::Normal, Abi::Rust - )) - ); + ) + )); require_same_types( tcx, &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType), se_ty, - start_t); + tcx.mk_fn_ptr(tcx.fn_sig(start_def_id))); } _ => { span_bug!(start_span, @@ -295,7 +293,8 @@ pub fn provide(providers: &mut Providers) { } pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> Result<(), usize> { + -> Result<(), CompileIncomplete> +{ let time_passes = tcx.sess.time_passes(); // this ensures that later parts of type checking can assume that items @@ -330,12 +329,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) check_unused::check_crate(tcx); check_for_entry_fn(tcx); - let err_count = tcx.sess.err_count(); - if err_count == 0 { - Ok(()) - } else { - Err(err_count) - } + tcx.sess.compile_status() } /// A quasi-deprecated helper used in rustdoc and save-analysis to get diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index c434edb1c31..f4963619370 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -14,11 +14,9 @@ //! We walk the set of items and, for each member, generate new constraints. use hir::def_id::DefId; -use middle::resolve_lifetime as rl; use rustc::dep_graph::{AssertDepGraphSafe, DepKind}; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::hir::map as hir_map; use syntax::ast; use rustc::hir; use rustc::hir::itemlikevisit::ItemLikeVisitor; @@ -61,10 +59,10 @@ pub struct Constraint<'a> { /// } /// /// then while we are visiting `Bar`, the `CurrentItem` would have -/// the def-id and generics of `Foo`. -pub struct CurrentItem<'a> { +/// the def-id and the start of `Foo`'s inferreds. +pub struct CurrentItem { def_id: DefId, - generics: &'a ty::Generics, + inferred_start: InferredIndex, } pub fn add_constraints_from_crate<'a, 'tcx>(terms_cx: TermsContext<'a, 'tcx>) @@ -91,8 +89,59 @@ pub fn add_constraints_from_crate<'a, 'tcx>(terms_cx: TermsContext<'a, 'tcx>) impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> { fn visit_item(&mut self, item: &hir::Item) { + match item.node { + hir::ItemStruct(ref struct_def, _) | + hir::ItemUnion(ref struct_def, _) => { + self.visit_node_helper(item.id); + + if let hir::VariantData::Tuple(..) = *struct_def { + self.visit_node_helper(struct_def.id()); + } + } + + hir::ItemEnum(ref enum_def, _) => { + self.visit_node_helper(item.id); + + for variant in &enum_def.variants { + if let hir::VariantData::Tuple(..) = variant.node.data { + self.visit_node_helper(variant.node.data.id()); + } + } + } + + hir::ItemFn(..) => { + self.visit_node_helper(item.id); + } + + hir::ItemForeignMod(ref foreign_mod) => { + for foreign_item in &foreign_mod.items { + if let hir::ForeignItemFn(..) = foreign_item.node { + self.visit_node_helper(foreign_item.id); + } + } + } + + _ => {} + } + } + + fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) { + if let hir::TraitItemKind::Method(..) = trait_item.node { + self.visit_node_helper(trait_item.id); + } + } + + fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) { + if let hir::ImplItemKind::Method(..) = impl_item.node { + self.visit_node_helper(impl_item.id); + } + } +} + +impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { + fn visit_node_helper(&mut self, id: ast::NodeId) { let tcx = self.terms_cx.tcx; - let def_id = tcx.hir.local_def_id(item.id); + let def_id = tcx.hir.local_def_id(id); // Encapsulate constructing the constraints into a task we can // reference later. This can go away once the red-green @@ -100,20 +149,11 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> { // // See README.md for a detailed discussion // on dep-graph management. - match item.node { - hir::ItemEnum(..) | - hir::ItemStruct(..) | - hir::ItemUnion(..) => { - let dep_node = def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints); - tcx.dep_graph.with_task(dep_node, - AssertDepGraphSafe(self), - def_id, - visit_item_task); - } - _ => { - // Nothing to do here, skip the task. - } - } + let dep_node = def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints); + tcx.dep_graph.with_task(dep_node, + AssertDepGraphSafe(self), + def_id, + visit_item_task); fn visit_item_task<'a, 'tcx>(ccx: AssertDepGraphSafe<&mut ConstraintContext<'a, 'tcx>>, def_id: DefId) @@ -122,197 +162,57 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> { } } - fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { - } - - fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { - } -} - -/// Is `param_id` a lifetime according to `map`? -fn is_lifetime(map: &hir_map::Map, param_id: ast::NodeId) -> bool { - match map.find(param_id) { - Some(hir_map::NodeLifetime(..)) => true, - _ => false, - } -} - -impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.terms_cx.tcx } fn build_constraints_for_item(&mut self, def_id: DefId) { let tcx = self.tcx(); - let id = self.tcx().hir.as_local_node_id(def_id).unwrap(); - let item = tcx.hir.expect_item(id); - debug!("visit_item item={}", tcx.hir.node_to_string(item.id)); + debug!("build_constraints_for_item({})", tcx.item_path_str(def_id)); - match item.node { - hir::ItemEnum(..) | - hir::ItemStruct(..) | - hir::ItemUnion(..) => { - let generics = tcx.generics_of(def_id); - let current_item = &CurrentItem { def_id, generics }; + // Skip items with no generics - there's nothing to infer in them. + if tcx.generics_of(def_id).count() == 0 { + return; + } + let id = tcx.hir.as_local_node_id(def_id).unwrap(); + let inferred_start = self.terms_cx.inferred_starts[&id]; + let current_item = &CurrentItem { def_id, inferred_start }; + match tcx.type_of(def_id).sty { + ty::TyAdt(def, _) => { // Not entirely obvious: constraints on structs/enums do not // affect the variance of their type parameters. See discussion // in comment at top of module. // // self.add_constraints_from_generics(generics); - for field in tcx.adt_def(def_id).all_fields() { + for field in def.all_fields() { self.add_constraints_from_ty(current_item, tcx.type_of(field.did), self.covariant); } } - hir::ItemTrait(..) | - hir::ItemExternCrate(_) | - hir::ItemUse(..) | - hir::ItemStatic(..) | - hir::ItemConst(..) | - hir::ItemFn(..) | - hir::ItemMod(..) | - hir::ItemForeignMod(..) | - hir::ItemGlobalAsm(..) | - hir::ItemTy(..) | - hir::ItemImpl(..) | - hir::ItemDefaultImpl(..) => { - span_bug!(item.span, "`build_constraints_for_item` invoked for non-type-def"); - } - } - } - - /// Load the generics for another item, adding a corresponding - /// relation into the dependencies to indicate that the variance - /// for `current` relies on `def_id`. - fn read_generics(&mut self, current: &CurrentItem, def_id: DefId) -> &'tcx ty::Generics { - let generics = self.tcx().generics_of(def_id); - if self.tcx().dep_graph.is_fully_enabled() { - self.dependencies.add(current.def_id, def_id); - } - generics - } - - fn opt_inferred_index(&self, param_id: ast::NodeId) -> Option<&InferredIndex> { - self.terms_cx.inferred_map.get(¶m_id) - } - - fn find_binding_for_lifetime(&self, param_id: ast::NodeId) -> ast::NodeId { - let tcx = self.terms_cx.tcx; - assert!(is_lifetime(&tcx.hir, param_id)); - match tcx.named_region_map.defs.get(¶m_id) { - Some(&rl::Region::EarlyBound(_, lifetime_decl_id)) => lifetime_decl_id, - Some(_) => bug!("should not encounter non early-bound cases"), - - // The lookup should only fail when `param_id` is - // itself a lifetime binding: use it as the decl_id. - None => param_id, - } - - } - - /// Is `param_id` a type parameter for which we infer variance? - fn is_to_be_inferred(&self, param_id: ast::NodeId) -> bool { - let result = self.terms_cx.inferred_map.contains_key(¶m_id); - - // To safe-guard against invalid inferred_map constructions, - // double-check if variance is inferred at some use of a type - // parameter (by inspecting parent of its binding declaration - // to see if it is introduced by a type or by a fn/impl). - - let check_result = |this: &ConstraintContext| -> bool { - let tcx = this.terms_cx.tcx; - let decl_id = this.find_binding_for_lifetime(param_id); - // Currently only called on lifetimes; double-checking that. - assert!(is_lifetime(&tcx.hir, param_id)); - let parent_id = tcx.hir.get_parent(decl_id); - let parent = tcx.hir - .find(parent_id) - .unwrap_or_else(|| bug!("tcx.hir missing entry for id: {}", parent_id)); - - let is_inferred; - macro_rules! cannot_happen { () => { { - bug!("invalid parent: {} for {}", - tcx.hir.node_to_string(parent_id), - tcx.hir.node_to_string(param_id)); - } } } - - match parent { - hir_map::NodeItem(p) => { - match p.node { - hir::ItemTy(..) | - hir::ItemEnum(..) | - hir::ItemStruct(..) | - hir::ItemUnion(..) | - hir::ItemTrait(..) => is_inferred = true, - hir::ItemFn(..) => is_inferred = false, - _ => cannot_happen!(), - } - } - hir_map::NodeTraitItem(..) => is_inferred = false, - hir_map::NodeImplItem(..) => is_inferred = false, - _ => cannot_happen!(), + ty::TyFnDef(..) => { + self.add_constraints_from_sig(current_item, + tcx.fn_sig(def_id), + self.covariant); } - return is_inferred; - }; - - assert_eq!(result, check_result(self)); - - return result; - } - - /// Returns a variance term representing the declared variance of the type/region parameter - /// with the given id. - fn declared_variance(&self, - param_def_id: DefId, - item_def_id: DefId, - index: usize) - -> VarianceTermPtr<'a> { - assert_eq!(param_def_id.krate, item_def_id.krate); - - if let Some(param_node_id) = self.tcx().hir.as_local_node_id(param_def_id) { - // Parameter on an item defined within current crate: - // variance not yet inferred, so return a symbolic - // variance. - if let Some(&InferredIndex(index)) = self.opt_inferred_index(param_node_id) { - self.terms_cx.inferred_infos[index].term - } else { - // If there is no inferred entry for a type parameter, - // it must be declared on a (locally defiend) trait -- they don't - // get inferreds because they are always invariant. - if cfg!(debug_assertions) { - let item_node_id = self.tcx().hir.as_local_node_id(item_def_id).unwrap(); - let item = self.tcx().hir.expect_item(item_node_id); - let success = match item.node { - hir::ItemTrait(..) => true, - _ => false, - }; - if !success { - bug!("parameter {:?} has no inferred, but declared on non-trait: {:?}", - item_def_id, - item); - } - } - self.invariant + _ => { + span_bug!(tcx.def_span(def_id), + "`build_constraints_for_item` unsupported for this item"); } - } else { - // Parameter on an item defined within another crate: - // variance already inferred, just look it up. - let variances = self.tcx().variances_of(item_def_id); - self.constant_term(variances[index]) } } fn add_constraint(&mut self, - InferredIndex(index): InferredIndex, + current: &CurrentItem, + index: u32, variance: VarianceTermPtr<'a>) { debug!("add_constraint(index={}, variance={:?})", index, variance); self.constraints.push(Constraint { - inferred: InferredIndex(index), + inferred: InferredIndex(current.inferred_start.0 + index as usize), variance: variance, }); } @@ -354,15 +254,26 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { debug!("add_constraints_from_trait_ref: trait_ref={:?} variance={:?}", trait_ref, variance); + self.add_constraints_from_invariant_substs(current, trait_ref.substs, variance); + } - let trait_generics = self.tcx().generics_of(trait_ref.def_id); + fn add_constraints_from_invariant_substs(&mut self, + current: &CurrentItem, + substs: &Substs<'tcx>, + variance: VarianceTermPtr<'a>) { + debug!("add_constraints_from_invariant_substs: substs={:?} variance={:?}", + substs, + variance); - self.add_constraints_from_substs(current, - trait_ref.def_id, - &trait_generics.types, - &trait_generics.regions, - trait_ref.substs, - variance); + // Trait are always invariant so we can take advantage of that. + let variance_i = self.invariant(variance); + for ty in substs.types() { + self.add_constraints_from_ty(current, ty, variance_i); + } + + for region in substs.regions() { + self.add_constraints_from_region(current, region, variance_i); + } } /// Adds constraints appropriate for an instance of `ty` appearing @@ -382,8 +293,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { // leaf type -- noop } - ty::TyClosure(..) | - ty::TyAnon(..) => { + ty::TyFnDef(..) | + ty::TyClosure(..) => { bug!("Unexpected closure type in variance computation"); } @@ -409,26 +320,15 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } ty::TyAdt(def, substs) => { - let adt_generics = self.read_generics(current, def.did); - - self.add_constraints_from_substs(current, - def.did, - &adt_generics.types, - &adt_generics.regions, - substs, - variance); + self.add_constraints_from_substs(current, def.did, substs, variance); } ty::TyProjection(ref data) => { - let trait_ref = &data.trait_ref; - let trait_generics = self.tcx().generics_of(trait_ref.def_id); + self.add_constraints_from_trait_ref(current, data.trait_ref, variance); + } - self.add_constraints_from_substs(current, - trait_ref.def_id, - &trait_generics.types, - &trait_generics.regions, - trait_ref.substs, - variance); + ty::TyAnon(_, substs) => { + self.add_constraints_from_invariant_substs(current, substs, variance); } ty::TyDynamic(ref data, r) => { @@ -447,26 +347,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } ty::TyParam(ref data) => { - assert_eq!(current.generics.parent, None); - let mut i = data.idx as usize; - if !current.generics.has_self || i > 0 { - i -= current.generics.regions.len(); - } - let def_id = current.generics.types[i].def_id; - let node_id = self.tcx().hir.as_local_node_id(def_id).unwrap(); - match self.terms_cx.inferred_map.get(&node_id) { - Some(&index) => { - self.add_constraint(index, variance); - } - None => { - // We do not infer variance for type parameters - // declared on methods. They will not be present - // in the inferred_map. - } - } + self.add_constraint(current, data.idx, variance); } - ty::TyFnDef(.., sig) | ty::TyFnPtr(sig) => { self.add_constraints_from_sig(current, sig, variance); } @@ -489,8 +372,6 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { fn add_constraints_from_substs(&mut self, current: &CurrentItem, def_id: DefId, - type_param_defs: &[ty::TypeParameterDef], - region_param_defs: &[ty::RegionParameterDef], substs: &Substs<'tcx>, variance: VarianceTermPtr<'a>) { debug!("add_constraints_from_substs(def_id={:?}, substs={:?}, variance={:?})", @@ -498,21 +379,45 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { substs, variance); - for p in type_param_defs { - let variance_decl = self.declared_variance(p.def_id, def_id, p.index as usize); + // We don't record `inferred_starts` entries for empty generics. + if substs.is_empty() { + return; + } + + // Add a corresponding relation into the dependencies to + // indicate that the variance for `current` relies on `def_id`. + if self.tcx().dep_graph.is_fully_enabled() { + self.dependencies.add(current.def_id, def_id); + } + + let (local, remote) = if let Some(id) = self.tcx().hir.as_local_node_id(def_id) { + (Some(self.terms_cx.inferred_starts[&id]), None) + } else { + (None, Some(self.tcx().variances_of(def_id))) + }; + + for (i, k) in substs.iter().enumerate() { + let variance_decl = if let Some(InferredIndex(start)) = local { + // Parameter on an item defined within current crate: + // variance not yet inferred, so return a symbolic + // variance. + self.terms_cx.inferred_terms[start + i] + } else { + // Parameter on an item defined within another crate: + // variance already inferred, just look it up. + self.constant_term(remote.as_ref().unwrap()[i]) + }; let variance_i = self.xform(variance, variance_decl); - let substs_ty = substs.type_for_def(p); debug!("add_constraints_from_substs: variance_decl={:?} variance_i={:?}", variance_decl, variance_i); - self.add_constraints_from_ty(current, substs_ty, variance_i); - } - - for p in region_param_defs { - let variance_decl = self.declared_variance(p.def_id, def_id, p.index as usize); - let variance_i = self.xform(variance, variance_decl); - let substs_r = substs.region_for_def(p); - self.add_constraints_from_region(current, substs_r, variance_i); + if let Some(ty) = k.as_type() { + self.add_constraints_from_ty(current, ty, variance_i); + } else if let Some(r) = k.as_region() { + self.add_constraints_from_region(current, r, variance_i); + } else { + bug!(); + } } } @@ -537,21 +442,14 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { variance: VarianceTermPtr<'a>) { match *region { ty::ReEarlyBound(ref data) => { - assert_eq!(current.generics.parent, None); - let i = data.index as usize - current.generics.has_self as usize; - let def_id = current.generics.regions[i].def_id; - let node_id = self.tcx().hir.as_local_node_id(def_id).unwrap(); - if self.is_to_be_inferred(node_id) { - let &index = self.opt_inferred_index(node_id).unwrap(); - self.add_constraint(index, variance); - } + self.add_constraint(current, data.index, variance); } ty::ReStatic => {} ty::ReLateBound(..) => { - // We do not infer variance for region parameters on - // methods or in fn types. + // Late-bound regions do not get substituted the same + // way early-bound regions do, so we skip them here. } ty::ReFree(..) | diff --git a/src/librustc_typeck/variance/mod.rs b/src/librustc_typeck/variance/mod.rs index 8f9f40ca40b..7a9f35545e2 100644 --- a/src/librustc_typeck/variance/mod.rs +++ b/src/librustc_typeck/variance/mod.rs @@ -54,45 +54,63 @@ fn crate_variances<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) fn variances_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId) -> Rc> { - let item_id = tcx.hir.as_local_node_id(item_def_id).expect("expected local def-id"); - let item = tcx.hir.expect_item(item_id); - match item.node { - hir::ItemTrait(..) => { - // Traits are always invariant. - let generics = tcx.generics_of(item_def_id); - assert!(generics.parent.is_none()); - Rc::new(vec![ty::Variance::Invariant; generics.count()]) - } + let id = tcx.hir.as_local_node_id(item_def_id).expect("expected local def-id"); + let unsupported = || { + // Variance not relevant. + span_bug!(tcx.hir.span(id), "asked to compute variance for wrong kind of item") + }; + match tcx.hir.get(id) { + hir::map::NodeItem(item) => match item.node { + hir::ItemEnum(..) | + hir::ItemStruct(..) | + hir::ItemUnion(..) | + hir::ItemFn(..) => {} - hir::ItemEnum(..) | - hir::ItemStruct(..) | - hir::ItemUnion(..) => { - // Everything else must be inferred. + _ => unsupported() + }, - // Lacking red/green, we read the variances for all items here - // but ignore the dependencies, then re-synthesize the ones we need. - let crate_map = tcx.dep_graph.with_ignore(|| tcx.crate_variances(LOCAL_CRATE)); - let dep_node = item_def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints); + hir::map::NodeTraitItem(item) => match item.node { + hir::TraitItemKind::Method(..) => {} + + _ => unsupported() + }, + + hir::map::NodeImplItem(item) => match item.node { + hir::ImplItemKind::Method(..) => {} + + _ => unsupported() + }, + + hir::map::NodeForeignItem(item) => match item.node { + hir::ForeignItemFn(..) => {} + + _ => unsupported() + }, + + hir::map::NodeVariant(_) | hir::map::NodeStructCtor(_) => {} + + _ => unsupported() + } + + // Everything else must be inferred. + + // Lacking red/green, we read the variances for all items here + // but ignore the dependencies, then re-synthesize the ones we need. + let crate_map = tcx.dep_graph.with_ignore(|| tcx.crate_variances(LOCAL_CRATE)); + let dep_node = item_def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints); + tcx.dep_graph.read(dep_node); + for &dep_def_id in crate_map.dependencies.less_than(&item_def_id) { + if dep_def_id.is_local() { + let dep_node = dep_def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints); + tcx.dep_graph.read(dep_node); + } else { + let dep_node = dep_def_id.to_dep_node(tcx, DepKind::ItemVariances); tcx.dep_graph.read(dep_node); - for &dep_def_id in crate_map.dependencies.less_than(&item_def_id) { - if dep_def_id.is_local() { - let dep_node = dep_def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints); - tcx.dep_graph.read(dep_node); - } else { - let dep_node = dep_def_id.to_dep_node(tcx, DepKind::ItemVariances); - tcx.dep_graph.read(dep_node); - } - } - - crate_map.variances.get(&item_def_id) - .unwrap_or(&crate_map.empty_variance) - .clone() - } - - _ => { - // Variance not relevant. - span_bug!(item.span, "asked to compute variance for wrong kind of item") } } + + crate_map.variances.get(&item_def_id) + .unwrap_or(&crate_map.empty_variance) + .clone() } diff --git a/src/librustc_typeck/variance/solve.rs b/src/librustc_typeck/variance/solve.rs index af8ad491ec0..495eb95419a 100644 --- a/src/librustc_typeck/variance/solve.rs +++ b/src/librustc_typeck/variance/solve.rs @@ -36,15 +36,18 @@ struct SolveContext<'a, 'tcx: 'a> { pub fn solve_constraints(constraints_cx: ConstraintContext) -> ty::CrateVariancesMap { let ConstraintContext { terms_cx, dependencies, constraints, .. } = constraints_cx; - let solutions = terms_cx.inferred_infos - .iter() - .map(|ii| ii.initial_variance) - .collect(); + let mut solutions = vec![ty::Bivariant; terms_cx.inferred_terms.len()]; + for &(id, ref variances) in &terms_cx.lang_items { + let InferredIndex(start) = terms_cx.inferred_starts[&id]; + for (i, &variance) in variances.iter().enumerate() { + solutions[start + i] = variance; + } + } let mut solutions_cx = SolveContext { - terms_cx: terms_cx, - constraints: constraints, - solutions: solutions, + terms_cx, + constraints, + solutions, }; solutions_cx.solve(); let variances = solutions_cx.create_map(); @@ -71,12 +74,9 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { let old_value = self.solutions[inferred]; let new_value = glb(variance, old_value); if old_value != new_value { - debug!("Updating inferred {} (node {}) \ + debug!("Updating inferred {} \ from {:?} to {:?} due to {:?}", inferred, - self.terms_cx - .inferred_infos[inferred] - .param_id, old_value, new_value, term); @@ -89,49 +89,28 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { } fn create_map(&self) -> FxHashMap>> { - // Collect all the variances for a particular item and stick - // them into the variance map. We rely on the fact that we - // generate all the inferreds for a particular item - // consecutively (that is, we collect solutions for an item - // until we see a new item id, and we assume (1) the solutions - // are in the same order as the type parameters were declared - // and (2) all solutions or a given item appear before a new - // item id). - let tcx = self.terms_cx.tcx; - let mut map = FxHashMap(); - let solutions = &self.solutions; - let inferred_infos = &self.terms_cx.inferred_infos; - let mut index = 0; - let num_inferred = self.terms_cx.num_inferred(); - while index < num_inferred { - let item_id = inferred_infos[index].item_id; + self.terms_cx.inferred_starts.iter().map(|(&id, &InferredIndex(start))| { + let def_id = tcx.hir.local_def_id(id); + let generics = tcx.generics_of(def_id); - let mut item_variances = vec![]; + let mut variances = solutions[start..start+generics.count()].to_vec(); - while index < num_inferred && inferred_infos[index].item_id == item_id { - let info = &inferred_infos[index]; - let variance = solutions[index]; - debug!("Index {} Info {} Variance {:?}", - index, - info.index, - variance); + debug!("id={} variances={:?}", id, variances); - assert_eq!(item_variances.len(), info.index); - item_variances.push(variance); - index += 1; + // Functions can have unused type parameters: make those invariant. + if let ty::TyFnDef(..) = tcx.type_of(def_id).sty { + for variance in &mut variances { + if *variance == ty::Bivariant { + *variance = ty::Invariant; + } + } } - debug!("item_id={} item_variances={:?}", item_id, item_variances); - - let item_def_id = tcx.hir.local_def_id(item_id); - - map.insert(item_def_id, Rc::new(item_variances)); - } - - map + (def_id, Rc::new(variances)) + }).collect() } fn evaluate(&self, term: VarianceTermPtr<'a>) -> ty::Variance { diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs index ad787c57e76..38457146a97 100644 --- a/src/librustc_typeck/variance/terms.rs +++ b/src/librustc_typeck/variance/terms.rs @@ -22,7 +22,6 @@ use arena::TypedArena; use rustc::ty::{self, TyCtxt}; use std::fmt; -use std::rc::Rc; use syntax::ast; use rustc::hir; use rustc::hir::itemlikevisit::ItemLikeVisitor; @@ -63,31 +62,17 @@ pub struct TermsContext<'a, 'tcx: 'a> { pub tcx: TyCtxt<'a, 'tcx, 'tcx>, pub arena: &'a TypedArena>, - pub empty_variances: Rc>, - // For marker types, UnsafeCell, and other lang items where // variance is hardcoded, records the item-id and the hardcoded // variance. pub lang_items: Vec<(ast::NodeId, Vec)>, - // Maps from the node id of a type/generic parameter to the - // corresponding inferred index. - pub inferred_map: NodeMap, + // Maps from the node id of an item to the first inferred index + // used for its type & region parameters. + pub inferred_starts: NodeMap, - // Maps from an InferredIndex to the info for that variable. - pub inferred_infos: Vec>, -} - -pub struct InferredInfo<'a> { - pub item_id: ast::NodeId, - pub index: usize, - pub param_id: ast::NodeId, - pub term: VarianceTermPtr<'a>, - - // Initial value to use for this parameter when inferring - // variance. For most parameters, this is Bivariant. But for lang - // items and input type parameters on traits, it is different. - pub initial_variance: ty::Variance, + // Maps from an InferredIndex to the term for that variable. + pub inferred_terms: Vec>, } pub fn determine_parameters_to_be_inferred<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -96,14 +81,10 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx> let mut terms_cx = TermsContext { tcx: tcx, arena: arena, - inferred_map: NodeMap(), - inferred_infos: Vec::new(), + inferred_starts: NodeMap(), + inferred_terms: vec![], lang_items: lang_items(tcx), - - // cache and share the variance struct used for items with - // no type/region parameters - empty_variances: Rc::new(vec![]), }; // See README.md for a discussion on dep-graph management. @@ -135,67 +116,28 @@ fn lang_items(tcx: TyCtxt) -> Vec<(ast::NodeId, Vec)> { } impl<'a, 'tcx> TermsContext<'a, 'tcx> { - fn add_inferreds_for_item(&mut self, - item_id: ast::NodeId, - generics: &hir::Generics) { - //! Add "inferreds" for the generic parameters declared on this - //! item. This has a lot of annoying parameters because we are - //! trying to drive this from the AST, rather than the - //! ty::Generics, so that we can get span info -- but this - //! means we must accommodate syntactic distinctions. - //! + fn add_inferreds_for_item(&mut self, id: ast::NodeId) { + let tcx = self.tcx; + let def_id = tcx.hir.local_def_id(id); + let count = tcx.generics_of(def_id).count(); + + if count == 0 { + return; + } + + // Record the start of this item's inferreds. + let start = self.inferred_terms.len(); + let newly_added = self.inferred_starts.insert(id, InferredIndex(start)).is_none(); + assert!(newly_added); // NB: In the code below for writing the results back into the // `CrateVariancesMap`, we rely on the fact that all inferreds // for a particular item are assigned continuous indices. - for (p, i) in generics.lifetimes.iter().zip(0..) { - let id = p.lifetime.id; - self.add_inferred(item_id, i, id); - } - - for (p, i) in generics.ty_params.iter().zip(generics.lifetimes.len()..) { - self.add_inferred(item_id, i, p.id); - } - } - - fn add_inferred(&mut self, item_id: ast::NodeId, index: usize, param_id: ast::NodeId) { - let inf_index = InferredIndex(self.inferred_infos.len()); - let term = self.arena.alloc(InferredTerm(inf_index)); - let initial_variance = self.pick_initial_variance(item_id, index); - self.inferred_infos.push(InferredInfo { - item_id: item_id, - index: index, - param_id: param_id, - term: term, - initial_variance: initial_variance, - }); - let newly_added = self.inferred_map.insert(param_id, inf_index).is_none(); - assert!(newly_added); - - debug!("add_inferred(item_path={}, \ - item_id={}, \ - index={}, \ - param_id={}, \ - inf_index={:?}, \ - initial_variance={:?})", - self.tcx.item_path_str(self.tcx.hir.local_def_id(item_id)), - item_id, - index, - param_id, - inf_index, - initial_variance); - } - - fn pick_initial_variance(&self, item_id: ast::NodeId, index: usize) -> ty::Variance { - match self.lang_items.iter().find(|&&(n, _)| n == item_id) { - Some(&(_, ref variances)) => variances[index], - None => ty::Bivariant, - } - } - - pub fn num_inferred(&self) -> usize { - self.inferred_infos.len() + let arena = self.arena; + self.inferred_terms.extend((start..start+count).map(|i| { + &*arena.alloc(InferredTerm(InferredIndex(i))) + })); } } @@ -205,30 +147,50 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> { self.tcx.hir.node_to_string(item.id)); match item.node { - hir::ItemEnum(_, ref generics) | - hir::ItemStruct(_, ref generics) | - hir::ItemUnion(_, ref generics) => { - self.add_inferreds_for_item(item.id, generics); + hir::ItemStruct(ref struct_def, _) | + hir::ItemUnion(ref struct_def, _) => { + self.add_inferreds_for_item(item.id); + + if let hir::VariantData::Tuple(..) = *struct_def { + self.add_inferreds_for_item(struct_def.id()); + } } - hir::ItemTrait(..) | - hir::ItemExternCrate(_) | - hir::ItemUse(..) | - hir::ItemDefaultImpl(..) | - hir::ItemImpl(..) | - hir::ItemStatic(..) | - hir::ItemConst(..) | - hir::ItemFn(..) | - hir::ItemMod(..) | - hir::ItemForeignMod(..) | - hir::ItemGlobalAsm(..) | - hir::ItemTy(..) => {} + hir::ItemEnum(ref enum_def, _) => { + self.add_inferreds_for_item(item.id); + + for variant in &enum_def.variants { + if let hir::VariantData::Tuple(..) = variant.node.data { + self.add_inferreds_for_item(variant.node.data.id()); + } + } + } + + hir::ItemFn(..) => { + self.add_inferreds_for_item(item.id); + } + + hir::ItemForeignMod(ref foreign_mod) => { + for foreign_item in &foreign_mod.items { + if let hir::ForeignItemFn(..) = foreign_item.node { + self.add_inferreds_for_item(foreign_item.id); + } + } + } + + _ => {} } } - fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { + fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) { + if let hir::TraitItemKind::Method(..) = trait_item.node { + self.add_inferreds_for_item(trait_item.id); + } } - fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { + fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) { + if let hir::ImplItemKind::Method(..) = impl_item.node { + self.add_inferreds_for_item(impl_item.id); + } } } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index aeade470482..fa5a999adf1 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -149,7 +149,7 @@ pub fn build_external_trait(cx: &DocContext, did: DefId) -> clean::Trait { } fn build_external_function(cx: &DocContext, did: DefId) -> clean::Function { - let sig = cx.tcx.type_of(did).fn_sig(); + let sig = cx.tcx.fn_sig(did); let constness = if cx.tcx.is_const_fn(did) { hir::Constness::Const diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 8fc8ccd0cfd..478e2fc5085 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1367,7 +1367,7 @@ impl<'tcx> Clean for ty::AssociatedItem { ty::AssociatedKind::Method => { let generics = (cx.tcx.generics_of(self.def_id), &cx.tcx.predicates_of(self.def_id)).clean(cx); - let sig = cx.tcx.type_of(self.def_id).fn_sig(); + let sig = cx.tcx.fn_sig(self.def_id); let mut decl = (self.def_id, sig).clean(cx); if self.method_has_self_argument { @@ -1842,17 +1842,21 @@ impl<'tcx> Clean for ty::Ty<'tcx> { mutability: mt.mutbl.clean(cx), type_: box mt.ty.clean(cx), }, - ty::TyFnDef(.., sig) | - ty::TyFnPtr(sig) => BareFunction(box BareFunctionDecl { - unsafety: sig.unsafety(), - generics: Generics { - lifetimes: Vec::new(), - type_params: Vec::new(), - where_predicates: Vec::new() - }, - decl: (cx.tcx.hir.local_def_id(ast::CRATE_NODE_ID), sig).clean(cx), - abi: sig.abi(), - }), + ty::TyFnDef(..) | + ty::TyFnPtr(_) => { + let ty = cx.tcx.lift(self).unwrap(); + let sig = ty.fn_sig(cx.tcx); + BareFunction(box BareFunctionDecl { + unsafety: sig.unsafety(), + generics: Generics { + lifetimes: Vec::new(), + type_params: Vec::new(), + where_predicates: Vec::new() + }, + decl: (cx.tcx.hir.local_def_id(ast::CRATE_NODE_ID), sig).clean(cx), + abi: sig.abi(), + }) + } ty::TyAdt(def, substs) => { let did = def.did; let kind = match def.adt_kind() { diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 635691dd345..766e76137ca 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1019,7 +1019,11 @@ impl fmt::Display for clean::Import { } } clean::Import::Glob(ref src) => { - write!(f, "use {}::*;", *src) + if src.path.segments.is_empty() { + write!(f, "use *;") + } else { + write!(f, "use {}::*;", *src) + } } } } diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 1f8c88d8ecf..89a40b0db96 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -300,7 +300,7 @@ impl<'a> Classifier<'a> { "Some" | "None" | "Ok" | "Err" => Class::PreludeVal, "$crate" => Class::KeyWord, - _ if tas.tok.is_any_keyword() => Class::KeyWord, + _ if tas.tok.is_reserved_ident() => Class::KeyWord, _ => { if self.in_macro_nonterminal { diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index bea13397eca..03da451fd9a 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -769,7 +769,7 @@ pub fn old_find_testable_code(doc: &str, tests: &mut ::test::Collector, position block_info.should_panic, block_info.no_run, block_info.ignore, block_info.test_harness, block_info.compile_fail, block_info.error_codes, - line, filename); + line, filename, block_info.allow_fail); } else { tests.add_old_test(text, filename); } @@ -859,7 +859,7 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Sp block_info.should_panic, block_info.no_run, block_info.ignore, block_info.test_harness, block_info.compile_fail, block_info.error_codes, - line, filename); + line, filename, block_info.allow_fail); prev_offset = offset; } Event::Start(Tag::Header(level)) => { @@ -889,6 +889,7 @@ struct LangString { test_harness: bool, compile_fail: bool, error_codes: Vec, + allow_fail: bool, } impl LangString { @@ -902,6 +903,7 @@ impl LangString { test_harness: false, compile_fail: false, error_codes: Vec::new(), + allow_fail: false, } } @@ -930,6 +932,7 @@ impl LangString { } "no_run" => { data.no_run = true; seen_rust_tags = !seen_other_tags; } "ignore" => { data.ignore = true; seen_rust_tags = !seen_other_tags; } + "allow_fail" => { data.allow_fail = true; seen_rust_tags = !seen_other_tags; } "rust" => { data.rust = true; seen_rust_tags = true; } "test_harness" => { data.test_harness = true; @@ -1118,7 +1121,7 @@ mod tests { fn test_lang_string_parse() { fn t(s: &str, should_panic: bool, no_run: bool, ignore: bool, rust: bool, test_harness: bool, - compile_fail: bool, error_codes: Vec) { + compile_fail: bool, allow_fail: bool, error_codes: Vec) { assert_eq!(LangString::parse(s), LangString { should_panic: should_panic, no_run: no_run, @@ -1128,25 +1131,31 @@ mod tests { compile_fail: compile_fail, error_codes: error_codes, original: s.to_owned(), + allow_fail: allow_fail, }) } + fn v() -> Vec { + Vec::new() + } + // marker | should_panic| no_run| ignore| rust | test_harness| compile_fail - // | error_codes - t("", false, false, false, true, false, false, Vec::new()); - t("rust", false, false, false, true, false, false, Vec::new()); - t("sh", false, false, false, false, false, false, Vec::new()); - t("ignore", false, false, true, true, false, false, Vec::new()); - t("should_panic", true, false, false, true, false, false, Vec::new()); - t("no_run", false, true, false, true, false, false, Vec::new()); - t("test_harness", false, false, false, true, true, false, Vec::new()); - t("compile_fail", false, true, false, true, false, true, Vec::new()); - t("{.no_run .example}", false, true, false, true, false, false, Vec::new()); - t("{.sh .should_panic}", true, false, false, false, false, false, Vec::new()); - t("{.example .rust}", false, false, false, true, false, false, Vec::new()); - t("{.test_harness .rust}", false, false, false, true, true, false, Vec::new()); - t("text, no_run", false, true, false, false, false, false, Vec::new()); - t("text,no_run", false, true, false, false, false, false, Vec::new()); + // | allow_fail | error_codes + t("", false, false, false, true, false, false, false, v()); + t("rust", false, false, false, true, false, false, false, v()); + t("sh", false, false, false, false, false, false, false, v()); + t("ignore", false, false, true, true, false, false, false, v()); + t("should_panic", true, false, false, true, false, false, false, v()); + t("no_run", false, true, false, true, false, false, false, v()); + t("test_harness", false, false, false, true, true, false, false, v()); + t("compile_fail", false, true, false, true, false, true, false, v()); + t("allow_fail", false, false, false, true, false, false, true, v()); + t("{.no_run .example}", false, true, false, true, false, false, false, v()); + t("{.sh .should_panic}", true, false, false, false, false, false, false, v()); + t("{.example .rust}", false, false, false, true, false, false, false, v()); + t("{.test_harness .rust}", false, false, false, true, true, false, false, v()); + t("text, no_run", false, true, false, false, false, false, false, v()); + t("text,no_run", false, true, false, false, false, false, false, v()); } #[test] diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index cfe2fad0fa4..f012fd974b5 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -25,7 +25,7 @@ use rustc_lint; use rustc::dep_graph::DepGraph; use rustc::hir; use rustc::hir::intravisit; -use rustc::session::{self, config}; +use rustc::session::{self, CompileIncomplete, config}; use rustc::session::config::{OutputType, OutputTypes, Externs}; use rustc::session::search_paths::{SearchPaths, PathKind}; use rustc_back::dynamic_lib::DynamicLibrary; @@ -253,35 +253,25 @@ fn runtest(test: &str, cratename: &str, cfgs: Vec, libs: SearchPaths, driver::compile_input(&sess, &cstore, &input, &out, &None, None, &control) })); - match res { - Ok(r) => { - match r { - Err(count) => { - if count > 0 && !compile_fail { - sess.fatal("aborting due to previous error(s)") - } else if count == 0 && compile_fail { - panic!("test compiled while it wasn't supposed to") - } - if count > 0 && error_codes.len() > 0 { - let out = String::from_utf8(data.lock().unwrap().to_vec()).unwrap(); - error_codes.retain(|err| !out.contains(err)); - } - } - Ok(()) if compile_fail => { - panic!("test compiled while it wasn't supposed to") - } - _ => {} - } + let compile_result = match res { + Ok(Ok(())) | Ok(Err(CompileIncomplete::Stopped)) => Ok(()), + Err(_) | Ok(Err(CompileIncomplete::Errored(_))) => Err(()) + }; + + match (compile_result, compile_fail) { + (Ok(()), true) => { + panic!("test compiled while it wasn't supposed to") } - Err(_) => { - if !compile_fail { - panic!("couldn't compile the test"); - } + (Ok(()), false) => {} + (Err(()), true) => { if error_codes.len() > 0 { let out = String::from_utf8(data.lock().unwrap().to_vec()).unwrap(); error_codes.retain(|err| !out.contains(err)); } } + (Err(()), false) => { + panic!("couldn't compile the test") + } } if error_codes.len() > 0 { @@ -467,7 +457,7 @@ impl Collector { pub fn add_test(&mut self, test: String, should_panic: bool, no_run: bool, should_ignore: bool, as_test_harness: bool, compile_fail: bool, error_codes: Vec, - line: usize, filename: String) { + line: usize, filename: String, allow_fail: bool) { let name = self.generate_name(line, &filename); // to be removed when hoedown is removed if self.render_type == RenderType::Pulldown { @@ -499,6 +489,7 @@ impl Collector { ignore: should_ignore, // compiler failures are test failures should_panic: testing::ShouldPanic::No, + allow_fail: allow_fail, }, testfn: testing::DynTestFn(box move |()| { let panic = io::set_panic(None); diff --git a/src/libstd/env.rs b/src/libstd/env.rs index 1dfae0ce83f..f81adad3ebe 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -949,63 +949,9 @@ mod arch { mod tests { use super::*; - use iter::repeat; - use rand::{self, Rng}; - use ffi::{OsString, OsStr}; + use ffi::OsStr; use path::{Path, PathBuf}; - fn make_rand_name() -> OsString { - let mut rng = rand::thread_rng(); - let n = format!("TEST{}", rng.gen_ascii_chars().take(10) - .collect::()); - let n = OsString::from(n); - assert!(var_os(&n).is_none()); - n - } - - fn eq(a: Option, b: Option<&str>) { - assert_eq!(a.as_ref().map(|s| &**s), b.map(OsStr::new).map(|s| &*s)); - } - - #[test] - fn test_set_var() { - let n = make_rand_name(); - set_var(&n, "VALUE"); - eq(var_os(&n), Some("VALUE")); - } - - #[test] - fn test_remove_var() { - let n = make_rand_name(); - set_var(&n, "VALUE"); - remove_var(&n); - eq(var_os(&n), None); - } - - #[test] - fn test_set_var_overwrite() { - let n = make_rand_name(); - set_var(&n, "1"); - set_var(&n, "2"); - eq(var_os(&n), Some("2")); - set_var(&n, ""); - eq(var_os(&n), Some("")); - } - - #[test] - #[cfg_attr(target_os = "emscripten", ignore)] - fn test_var_big() { - let mut s = "".to_string(); - let mut i = 0; - while i < 100 { - s.push_str("aaaaaaaaaa"); - i += 1; - } - let n = make_rand_name(); - set_var(&n, &s); - eq(var_os(&n), Some(&s)); - } - #[test] #[cfg_attr(target_os = "emscripten", ignore)] fn test_self_exe_path() { @@ -1017,32 +963,6 @@ mod tests { assert!(path.is_absolute()); } - #[test] - #[cfg_attr(target_os = "emscripten", ignore)] - fn test_env_set_get_huge() { - let n = make_rand_name(); - let s = repeat("x").take(10000).collect::(); - set_var(&n, &s); - eq(var_os(&n), Some(&s)); - remove_var(&n); - eq(var_os(&n), None); - } - - #[test] - fn test_env_set_var() { - let n = make_rand_name(); - - let mut e = vars_os(); - set_var(&n, "VALUE"); - assert!(!e.any(|(k, v)| { - &*k == &*n && &*v == "VALUE" - })); - - assert!(vars_os().any(|(k, v)| { - &*k == &*n && &*v == "VALUE" - })); - } - #[test] fn test() { assert!((!Path::new("test-path").is_absolute())); diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index 6134b0b882c..a6eb17c8fa4 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -363,39 +363,29 @@ impl f32 { #[inline] pub fn signum(self) -> f32 { num::Float::signum(self) } - /// Returns `true` if `self`'s sign bit is positive, including - /// `+0.0` and `INFINITY`. + /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with + /// positive sign bit and positive infinity. /// /// ``` - /// use std::f32; - /// - /// let nan = f32::NAN; /// let f = 7.0_f32; /// let g = -7.0_f32; /// /// assert!(f.is_sign_positive()); /// assert!(!g.is_sign_positive()); - /// // Requires both tests to determine if is `NaN` - /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn is_sign_positive(self) -> bool { num::Float::is_sign_positive(self) } - /// Returns `true` if `self`'s sign is negative, including `-0.0` - /// and `NEG_INFINITY`. + /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with + /// negative sign bit and negative infinity. /// /// ``` - /// use std::f32; - /// - /// let nan = f32::NAN; /// let f = 7.0f32; /// let g = -7.0f32; /// /// assert!(!f.is_sign_negative()); /// assert!(g.is_sign_negative()); - /// // Requires both tests to determine if is `NaN`. - /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -1141,13 +1131,16 @@ impl f32 { #[inline] pub fn from_bits(mut v: u32) -> Self { const EXP_MASK: u32 = 0x7F800000; - const QNAN_MASK: u32 = 0x00400000; const FRACT_MASK: u32 = 0x007FFFFF; if v & EXP_MASK == EXP_MASK && v & FRACT_MASK != 0 { - // If we have a NaN value, we - // convert signaling NaN values to quiet NaN - // by setting the the highest bit of the fraction - v |= QNAN_MASK; + // While IEEE 754-2008 specifies encodings for quiet NaNs + // and signaling ones, certain MIPS and PA-RISC + // CPUs treat signaling NaNs differently. + // Therefore to be safe, we pass a known quiet NaN + // if v is any kind of NaN. + // The check above only assumes IEEE 754-1985 to be + // valid. + v = unsafe { ::mem::transmute(NAN) }; } unsafe { ::mem::transmute(v) } } @@ -1184,7 +1177,7 @@ mod tests { assert!(!nan.is_infinite()); assert!(!nan.is_finite()); assert!(!nan.is_normal()); - assert!(!nan.is_sign_positive()); + assert!(nan.is_sign_positive()); assert!(!nan.is_sign_negative()); assert_eq!(Fp::Nan, nan.classify()); } @@ -1428,7 +1421,8 @@ mod tests { assert!(!(-1f32).is_sign_positive()); assert!(!NEG_INFINITY.is_sign_positive()); assert!(!(1f32/NEG_INFINITY).is_sign_positive()); - assert!(!NAN.is_sign_positive()); + assert!(NAN.is_sign_positive()); + assert!(!(-NAN).is_sign_positive()); } #[test] @@ -1441,6 +1435,7 @@ mod tests { assert!(NEG_INFINITY.is_sign_negative()); assert!((1f32/NEG_INFINITY).is_sign_negative()); assert!(!NAN.is_sign_negative()); + assert!((-NAN).is_sign_negative()); } #[test] @@ -1740,8 +1735,15 @@ mod tests { } #[test] fn test_snan_masking() { + // NOTE: this test assumes that our current platform + // implements IEEE 754-2008 that specifies the difference + // in encoding of quiet and signaling NaNs. + // If you are porting Rust to a platform that does not + // implement IEEE 754-2008 (but e.g. IEEE 754-1985, which + // only says that "Signaling NaNs shall be reserved operands" + // but doesn't specify the actual setup), feel free to + // cfg out this test. let snan: u32 = 0x7F801337; - const PAYLOAD_MASK: u32 = 0x003FFFFF; const QNAN_MASK: u32 = 0x00400000; let nan_masked_fl = f32::from_bits(snan); let nan_masked = nan_masked_fl.to_bits(); @@ -1750,7 +1752,5 @@ mod tests { // Ensure that we have a quiet NaN assert_ne!(nan_masked & QNAN_MASK, 0); assert!(nan_masked_fl.is_nan()); - // Ensure the payload wasn't touched during conversion - assert_eq!(nan_masked & PAYLOAD_MASK, snan & PAYLOAD_MASK); } } diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index e8d25cfbf94..4d8d8b4ebe6 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -301,21 +301,15 @@ impl f64 { #[inline] pub fn signum(self) -> f64 { num::Float::signum(self) } - /// Returns `true` if `self`'s sign bit is positive, including - /// `+0.0` and `INFINITY`. + /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with + /// positive sign bit and positive infinity. /// /// ``` - /// use std::f64; - /// - /// let nan: f64 = f64::NAN; - /// /// let f = 7.0_f64; /// let g = -7.0_f64; /// /// assert!(f.is_sign_positive()); /// assert!(!g.is_sign_positive()); - /// // Requires both tests to determine if is `NaN` - /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -326,21 +320,15 @@ impl f64 { #[inline] pub fn is_positive(self) -> bool { num::Float::is_sign_positive(self) } - /// Returns `true` if `self`'s sign is negative, including `-0.0` - /// and `NEG_INFINITY`. + /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with + /// negative sign bit and negative infinity. /// /// ``` - /// use std::f64; - /// - /// let nan = f64::NAN; - /// /// let f = 7.0_f64; /// let g = -7.0_f64; /// /// assert!(!f.is_sign_negative()); /// assert!(g.is_sign_negative()); - /// // Requires both tests to determine if is `NaN`. - /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -1058,13 +1046,16 @@ impl f64 { #[inline] pub fn from_bits(mut v: u64) -> Self { const EXP_MASK: u64 = 0x7FF0000000000000; - const QNAN_MASK: u64 = 0x0001000000000000; const FRACT_MASK: u64 = 0x000FFFFFFFFFFFFF; if v & EXP_MASK == EXP_MASK && v & FRACT_MASK != 0 { - // If we have a NaN value, we - // convert signaling NaN values to quiet NaN - // by setting the the highest bit of the fraction - v |= QNAN_MASK; + // While IEEE 754-2008 specifies encodings for quiet NaNs + // and signaling ones, certain MIPS and PA-RISC + // CPUs treat signaling NaNs differently. + // Therefore to be safe, we pass a known quiet NaN + // if v is any kind of NaN. + // The check above only assumes IEEE 754-1985 to be + // valid. + v = unsafe { ::mem::transmute(NAN) }; } unsafe { ::mem::transmute(v) } } @@ -1101,7 +1092,7 @@ mod tests { assert!(!nan.is_infinite()); assert!(!nan.is_finite()); assert!(!nan.is_normal()); - assert!(!nan.is_sign_positive()); + assert!(nan.is_sign_positive()); assert!(!nan.is_sign_negative()); assert_eq!(Fp::Nan, nan.classify()); } @@ -1347,7 +1338,8 @@ mod tests { assert!(!(-1f64).is_sign_positive()); assert!(!NEG_INFINITY.is_sign_positive()); assert!(!(1f64/NEG_INFINITY).is_sign_positive()); - assert!(!NAN.is_sign_positive()); + assert!(NAN.is_sign_positive()); + assert!(!(-NAN).is_sign_positive()); } #[test] @@ -1360,6 +1352,7 @@ mod tests { assert!(NEG_INFINITY.is_sign_negative()); assert!((1f64/NEG_INFINITY).is_sign_negative()); assert!(!NAN.is_sign_negative()); + assert!((-NAN).is_sign_negative()); } #[test] diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 1a91417ca0e..5f0b11a616e 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -585,11 +585,11 @@ impl From> for CString { } } -#[stable(feature = "box_from_c_string", since = "1.18.0")] -impl Into> for CString { +#[stable(feature = "box_from_c_string", since = "1.20.0")] +impl From for Box { #[inline] - fn into(self) -> Box { - self.into_boxed_c_str() + fn from(s: CString) -> Box { + s.into_boxed_c_str() } } diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index f54d79c201f..02a13ed7a5a 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -29,7 +29,7 @@ use sys_common::{AsInner, IntoInner, FromInner}; /// * On Windows, strings are often arbitrary sequences of non-zero 16-bit /// values, interpreted as UTF-16 when it is valid to do so. /// -/// * In Rust, strings are always valid UTF-8, but may contain zeros. +/// * In Rust, strings are always valid UTF-8, which may contain zeros. /// /// `OsString` and [`OsStr`] bridge this gap by simultaneously representing Rust /// and platform-native string values, and in particular allowing a Rust string @@ -230,8 +230,6 @@ impl OsString { /// # Examples /// /// ``` - /// #![feature(osstring_shrink_to_fit)] - /// /// use std::ffi::OsString; /// /// let mut s = OsString::from("foo"); @@ -242,7 +240,7 @@ impl OsString { /// s.shrink_to_fit(); /// assert_eq!(3, s.capacity()); /// ``` - #[unstable(feature = "osstring_shrink_to_fit", issue = "40421")] + #[stable(feature = "osstring_shrink_to_fit", since = "1.19.0")] pub fn shrink_to_fit(&mut self) { self.inner.shrink_to_fit() } @@ -542,10 +540,10 @@ impl From> for OsString { } } -#[stable(feature = "box_from_os_string", since = "1.18.0")] -impl Into> for OsString { - fn into(self) -> Box { - self.into_boxed_os_str() +#[stable(feature = "box_from_os_string", since = "1.20.0")] +impl From for Box { + fn from(s: OsString) -> Box { + s.into_boxed_os_str() } } diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 5b8c0c33990..88994b284c9 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -653,15 +653,29 @@ impl OpenOptions { /// # Errors /// /// This function will return an error under a number of different - /// circumstances, to include but not limited to: + /// circumstances. Some of these error conditions are listed here, together + /// with their [`ErrorKind`]. The mapping to [`ErrorKind`]s is not part of + /// the compatiblity contract of the function, especially the `Other` kind + /// might change to more specific kinds in the future. /// - /// * Opening a file that does not exist without setting `create` or - /// `create_new`. - /// * Attempting to open a file with access that the user lacks - /// permissions for - /// * Filesystem-level errors (full disk, etc) - /// * Invalid combinations of open options (truncate without write access, - /// no access mode set, etc) + /// * [`NotFound`]: The specified file does not exist and neither `create` + /// or `create_new` is set. + /// * [`NotFound`]: One of the directory components of the file path does + /// not exist. + /// * [`PermissionDenied`]: The user lacks permission to get the specified + /// access rights for the file. + /// * [`PermissionDenied`]: The user lacks permission to open one of the + /// directory components of the specified path. + /// * [`AlreadyExists`]: `create_new` was specified and the file already + /// exists. + /// * [`InvalidInput`]: Invalid combinations of open options (truncate + /// without write access, no access mode set, etc.). + /// * [`Other`]: One of the directory components of the specified file path + /// was not, in fact, a directory. + /// * [`Other`]: Filesystem-level errors: full disk, write permission + /// requested on a read-only file system, exceeded disk quota, too many + /// open files, too long filename, too many symbolic links in the + /// specified path (Unix-like systems only), etc. /// /// # Examples /// @@ -670,6 +684,13 @@ impl OpenOptions { /// /// let file = OpenOptions::new().open("foo.txt"); /// ``` + /// + /// [`ErrorKind`]: ../io/enum.ErrorKind.html + /// [`AlreadyExists`]: ../io/enum.ErrorKind.html#variant.AlreadyExists + /// [`InvalidInput`]: ../io/enum.ErrorKind.html#variant.InvalidInput + /// [`NotFound`]: ../io/enum.ErrorKind.html#variant.NotFound + /// [`Other`]: ../io/enum.ErrorKind.html#variant.Other + /// [`PermissionDenied`]: ../io/enum.ErrorKind.html#variant.PermissionDenied #[stable(feature = "rust1", since = "1.0.0")] pub fn open>(&self, path: P) -> io::Result { self._open(path.as_ref()) diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 680a5f32ae2..71c76008244 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -1589,8 +1589,6 @@ impl Chain { /// # Examples /// /// ``` - /// #![feature(more_io_inner_methods)] - /// /// # use std::io; /// use std::io::prelude::*; /// use std::fs::File; @@ -1604,7 +1602,7 @@ impl Chain { /// # Ok(()) /// # } /// ``` - #[unstable(feature = "more_io_inner_methods", issue="41519")] + #[stable(feature = "more_io_inner_methods", since = "1.20.0")] pub fn into_inner(self) -> (T, U) { (self.first, self.second) } @@ -1614,8 +1612,6 @@ impl Chain { /// # Examples /// /// ``` - /// #![feature(more_io_inner_methods)] - /// /// # use std::io; /// use std::io::prelude::*; /// use std::fs::File; @@ -1629,7 +1625,7 @@ impl Chain { /// # Ok(()) /// # } /// ``` - #[unstable(feature = "more_io_inner_methods", issue="41519")] + #[stable(feature = "more_io_inner_methods", since = "1.20.0")] pub fn get_ref(&self) -> (&T, &U) { (&self.first, &self.second) } @@ -1643,8 +1639,6 @@ impl Chain { /// # Examples /// /// ``` - /// #![feature(more_io_inner_methods)] - /// /// # use std::io; /// use std::io::prelude::*; /// use std::fs::File; @@ -1658,7 +1652,7 @@ impl Chain { /// # Ok(()) /// # } /// ``` - #[unstable(feature = "more_io_inner_methods", issue="41519")] + #[stable(feature = "more_io_inner_methods", since = "1.20.0")] pub fn get_mut(&mut self) -> (&mut T, &mut U) { (&mut self.first, &mut self.second) } @@ -1791,8 +1785,6 @@ impl Take { /// # Examples /// /// ``` - /// #![feature(more_io_inner_methods)] - /// /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; @@ -1808,7 +1800,7 @@ impl Take { /// # Ok(()) /// # } /// ``` - #[unstable(feature = "more_io_inner_methods", issue="41519")] + #[stable(feature = "more_io_inner_methods", since = "1.20.0")] pub fn get_ref(&self) -> &T { &self.inner } @@ -1822,8 +1814,6 @@ impl Take { /// # Examples /// /// ``` - /// #![feature(more_io_inner_methods)] - /// /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; @@ -1839,7 +1829,7 @@ impl Take { /// # Ok(()) /// # } /// ``` - #[unstable(feature = "more_io_inner_methods", issue="41519")] + #[stable(feature = "more_io_inner_methods", since = "1.20.0")] pub fn get_mut(&mut self) -> &mut T { &mut self.inner } diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 9a4c5ec8f6b..6eb9faacf7f 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -41,10 +41,10 @@ macro_rules! panic { panic!("explicit panic") }); ($msg:expr) => ({ - $crate::rt::begin_panic($msg, { + $crate::rt::begin_panic_new($msg, { // static requires less code at runtime, more constant data - static _FILE_LINE: (&'static str, u32) = (file!(), line!()); - &_FILE_LINE + static _FILE_LINE_COL: (&'static str, u32, u32) = (file!(), line!(), column!()); + &_FILE_LINE_COL }) }); ($fmt:expr, $($arg:tt)+) => ({ @@ -53,8 +53,8 @@ macro_rules! panic { // used inside a dead function. Just `#[allow(dead_code)]` is // insufficient, since the user may have // `#[forbid(dead_code)]` and which cannot be overridden. - static _FILE_LINE: (&'static str, u32) = (file!(), line!()); - &_FILE_LINE + static _FILE_LINE_COL: (&'static str, u32, u32) = (file!(), line!(), column!()); + &_FILE_LINE_COL }) }); } diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 6f46a73698f..494376b831e 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -262,6 +262,7 @@ impl<'a> PanicInfo<'a> { pub struct Location<'a> { file: &'a str, line: u32, + col: u32, } impl<'a> Location<'a> { @@ -308,6 +309,29 @@ impl<'a> Location<'a> { pub fn line(&self) -> u32 { self.line } + + /// Returns the column from which the panic originated. + /// + /// # Examples + /// + /// ```should_panic + /// #![feature(panic_col)] + /// use std::panic; + /// + /// panic::set_hook(Box::new(|panic_info| { + /// if let Some(location) = panic_info.location() { + /// println!("panic occured at column {}", location.column()); + /// } else { + /// println!("panic occured but can't get location information..."); + /// } + /// })); + /// + /// panic!("Normal panic"); + /// ``` + #[unstable(feature = "panic_col", reason = "recently added", issue = "42939")] + pub fn column(&self) -> u32 { + self.col + } } fn default_hook(info: &PanicInfo) { @@ -329,6 +353,7 @@ fn default_hook(info: &PanicInfo) { let file = info.location.file; let line = info.location.line; + let col = info.location.col; let msg = match info.payload.downcast_ref::<&'static str>() { Some(s) => *s, @@ -342,8 +367,8 @@ fn default_hook(info: &PanicInfo) { let name = thread.as_ref().and_then(|t| t.name()).unwrap_or(""); let write = |err: &mut ::io::Write| { - let _ = writeln!(err, "thread '{}' panicked at '{}', {}:{}", - name, msg, file, line); + let _ = writeln!(err, "thread '{}' panicked at '{}', {}:{}:{}", + name, msg, file, line, col); #[cfg(feature = "backtrace")] { @@ -467,8 +492,9 @@ pub fn panicking() -> bool { #[unwind] pub extern fn rust_begin_panic(msg: fmt::Arguments, file: &'static str, - line: u32) -> ! { - begin_panic_fmt(&msg, &(file, line)) + line: u32, + col: u32) -> ! { + begin_panic_fmt(&msg, &(file, line, col)) } /// The entry point for panicking with a formatted message. @@ -482,7 +508,7 @@ pub extern fn rust_begin_panic(msg: fmt::Arguments, issue = "0")] #[inline(never)] #[cold] pub fn begin_panic_fmt(msg: &fmt::Arguments, - file_line: &(&'static str, u32)) -> ! { + file_line_col: &(&'static str, u32, u32)) -> ! { use fmt::Write; // We do two allocations here, unfortunately. But (a) they're @@ -492,7 +518,39 @@ pub fn begin_panic_fmt(msg: &fmt::Arguments, let mut s = String::new(); let _ = s.write_fmt(*msg); - begin_panic(s, file_line) + begin_panic_new(s, file_line_col) +} + +// FIXME: In PR #42938, we have added the column as info passed to the panic +// handling code. For this, we want to break the ABI of begin_panic. +// This is not possible to do directly, as the stage0 compiler is hardcoded +// to emit a call to begin_panic in src/libsyntax/ext/build.rs, only +// with the file and line number being passed, but not the colum number. +// By changing the compiler source, we can only affect behaviour of higher +// stages. We need to perform the switch over two stage0 replacements, using +// a temporary function begin_panic_new while performing the switch: +// 0. Right now, we tell stage1 onward to emit a call to begin_panic_new. +// 1. In the first SNAP, stage0 calls begin_panic_new with the new ABI, +// begin_panic stops being used. Now we can change begin_panic to +// the new ABI, and start emitting calls to begin_panic in higher +// stages again, this time with the new ABI. +// 2. After the second SNAP, stage0 calls begin_panic with the new ABI, +// and we can remove the temporary begin_panic_new function. + +/// This is the entry point of panicking for panic!() and assert!(). +#[unstable(feature = "libstd_sys_internals", + reason = "used by the panic! macro", + issue = "0")] +#[inline(never)] #[cold] // avoid code bloat at the call sites as much as possible +pub fn begin_panic_new(msg: M, file_line_col: &(&'static str, u32, u32)) -> ! { + // Note that this should be the only allocation performed in this code path. + // Currently this means that panic!() on OOM will invoke this code path, + // but then again we're not really ready for panic on OOM anyway. If + // we do start doing this, then we should propagate this allocation to + // be performed in the parent of this thread instead of the thread that's + // panicking. + + rust_panic_with_hook(Box::new(msg), file_line_col) } /// This is the entry point of panicking for panic!() and assert!(). @@ -508,7 +566,10 @@ pub fn begin_panic(msg: M, file_line: &(&'static str, u32)) -> ! // be performed in the parent of this thread instead of the thread that's // panicking. - rust_panic_with_hook(Box::new(msg), file_line) + let (file, line) = *file_line; + let file_line_col = (file, line, 0); + + rust_panic_with_hook(Box::new(msg), &file_line_col) } /// Executes the primary logic for a panic, including checking for recursive @@ -520,8 +581,8 @@ pub fn begin_panic(msg: M, file_line: &(&'static str, u32)) -> ! #[inline(never)] #[cold] fn rust_panic_with_hook(msg: Box, - file_line: &(&'static str, u32)) -> ! { - let (file, line) = *file_line; + file_line_col: &(&'static str, u32, u32)) -> ! { + let (file, line, col) = *file_line_col; let panics = update_panic_count(1); @@ -540,8 +601,9 @@ fn rust_panic_with_hook(msg: Box, let info = PanicInfo { payload: &*msg, location: Location { - file: file, - line: line, + file, + line, + col, }, }; HOOK_LOCK.read(); diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 42a54ed6d75..e7c7be981d2 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -276,7 +276,7 @@ impl<'a> Prefix<'a> { /// ``` /// use std::path; /// -/// assert!(path::is_separator('/')); +/// assert!(path::is_separator('/')); // '/' works for both Unix and Windows /// assert!(!path::is_separator('❤')); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -1348,10 +1348,10 @@ impl From> for PathBuf { } } -#[stable(feature = "box_from_path_buf", since = "1.18.0")] -impl Into> for PathBuf { - fn into(self) -> Box { - self.into_boxed_path() +#[stable(feature = "box_from_path_buf", since = "1.20.0")] +impl From for Box { + fn from(p: PathBuf) -> Box { + p.into_boxed_path() } } @@ -1499,9 +1499,9 @@ impl AsRef for PathBuf { /// A slice of a path (akin to [`str`]). /// /// This type supports a number of operations for inspecting a path, including -/// breaking the path into its components (separated by `/` or `\`, depending on -/// the platform), extracting the file name, determining whether the path is -/// absolute, and so on. +/// breaking the path into its components (separated by `/` on Unix and by either +/// `/` or `\` on Windows), extracting the file name, determining whether the path +/// is absolute, and so on. /// /// This is an *unsized* type, meaning that it must always be used behind a /// pointer like `&` or [`Box`]. For an owned version of this type, @@ -1520,10 +1520,11 @@ impl AsRef for PathBuf { /// use std::path::Path; /// use std::ffi::OsStr; /// -/// let path = Path::new("/tmp/foo/bar.txt"); +/// // Note: this example does work on Windows +/// let path = Path::new("./foo/bar.txt"); /// /// let parent = path.parent(); -/// assert_eq!(parent, Some(Path::new("/tmp/foo"))); +/// assert_eq!(parent, Some(Path::new("./foo"))); /// /// let file_stem = path.file_stem(); /// assert_eq!(file_stem, Some(OsStr::new("bar"))); diff --git a/src/libstd/process.rs b/src/libstd/process.rs index df6a648b7b1..7adfcc44ad0 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -447,8 +447,6 @@ impl Command { /// Basic usage: /// /// ```no_run - /// #![feature(command_envs)] - /// /// use std::process::{Command, Stdio}; /// use std::env; /// use std::collections::HashMap; @@ -466,7 +464,7 @@ impl Command { /// .spawn() /// .expect("printenv failed to start"); /// ``` - #[unstable(feature = "command_envs", issue = "38526")] + #[stable(feature = "command_envs", since = "1.19.0")] pub fn envs(&mut self, vars: I) -> &mut Command where I: IntoIterator, K: AsRef, V: AsRef { diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs index 06fd838ea06..2ee63527c14 100644 --- a/src/libstd/rt.rs +++ b/src/libstd/rt.rs @@ -25,7 +25,7 @@ // Reexport some of our utilities which are expected by other crates. -pub use panicking::{begin_panic, begin_panic_fmt, update_panic_count}; +pub use panicking::{begin_panic_new, begin_panic, begin_panic_fmt, update_panic_count}; #[cfg(not(test))] #[lang = "start"] diff --git a/src/libstd/sys/redox/fast_thread_local.rs b/src/libstd/sys/redox/fast_thread_local.rs index 7dc61ce6654..9f0eee024d5 100644 --- a/src/libstd/sys/redox/fast_thread_local.rs +++ b/src/libstd/sys/redox/fast_thread_local.rs @@ -57,7 +57,7 @@ impl Key { } } -unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { +pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { // The fallback implementation uses a vanilla OS-based TLS key to track // the list of destructors that need to be run for this thread. The key // then has its own destructor which runs all the other destructors. @@ -115,3 +115,7 @@ pub unsafe extern fn destroy_value(ptr: *mut u8) { ptr::drop_in_place((*ptr).inner.get()); } } + +pub fn requires_move_before_drop() -> bool { + false +} diff --git a/src/libstd/sys/redox/fs.rs b/src/libstd/sys/redox/fs.rs index 48d9cdcb2c9..c5a19e8debe 100644 --- a/src/libstd/sys/redox/fs.rs +++ b/src/libstd/sys/redox/fs.rs @@ -420,12 +420,19 @@ fn remove_dir_all_recursive(path: &Path) -> io::Result<()> { } pub fn readlink(p: &Path) -> io::Result { - canonicalize(p) + let fd = cvt(syscall::open(p.to_str().unwrap(), syscall::O_SYMLINK | syscall::O_RDONLY))?; + let mut buf: [u8; 4096] = [0; 4096]; + let count = cvt(syscall::read(fd, &mut buf))?; + cvt(syscall::close(fd))?; + Ok(PathBuf::from(unsafe { String::from_utf8_unchecked(Vec::from(&buf[..count])) })) } -pub fn symlink(_src: &Path, _dst: &Path) -> io::Result<()> { - ::sys_common::util::dumb_print(format_args!("Symlink\n")); - unimplemented!(); +pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> { + let fd = cvt(syscall::open(dst.to_str().unwrap(), + syscall::O_SYMLINK | syscall::O_CREAT | syscall::O_WRONLY | 0o777))?; + cvt(syscall::write(fd, src.to_str().unwrap().as_bytes()))?; + cvt(syscall::close(fd))?; + Ok(()) } pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> { diff --git a/src/libstd/sys/redox/net/tcp.rs b/src/libstd/sys/redox/net/tcp.rs index ac3fd2ad6b9..17673f0bd60 100644 --- a/src/libstd/sys/redox/net/tcp.rs +++ b/src/libstd/sys/redox/net/tcp.rs @@ -17,7 +17,6 @@ use sys::fs::{File, OpenOptions}; use sys::syscall::TimeSpec; use sys_common::{AsInner, FromInner, IntoInner}; use time::Duration; -use vec::Vec; use super::{path_to_peer_addr, path_to_local_addr}; diff --git a/src/libstd/sys/redox/pipe.rs b/src/libstd/sys/redox/pipe.rs index 05863adf108..28645facd93 100644 --- a/src/libstd/sys/redox/pipe.rs +++ b/src/libstd/sys/redox/pipe.rs @@ -49,8 +49,8 @@ pub fn read2(p1: AnonPipe, //FIXME: Use event based I/O multiplexing //unimplemented!() - p1.read_to_end(v1)?; - p2.read_to_end(v2)?; + p1.0.read_to_end(v1)?; + p2.0.read_to_end(v2)?; Ok(()) diff --git a/src/libstd/sys/redox/syscall/flag.rs b/src/libstd/sys/redox/syscall/flag.rs index 9f0d3e6f779..bd603cfe6ef 100644 --- a/src/libstd/sys/redox/syscall/flag.rs +++ b/src/libstd/sys/redox/syscall/flag.rs @@ -33,6 +33,7 @@ pub const MAP_WRITE_COMBINE: usize = 2; pub const MODE_TYPE: u16 = 0xF000; pub const MODE_DIR: u16 = 0x4000; pub const MODE_FILE: u16 = 0x8000; +pub const MODE_SYMLINK: u16 = 0xA000; pub const MODE_PERM: u16 = 0x0FFF; pub const MODE_SETUID: u16 = 0o4000; @@ -53,6 +54,7 @@ pub const O_TRUNC: usize = 0x0400_0000; pub const O_EXCL: usize = 0x0800_0000; pub const O_DIRECTORY: usize = 0x1000_0000; pub const O_STAT: usize = 0x2000_0000; +pub const O_SYMLINK: usize = 0x4000_0000; pub const O_ACCMODE: usize = O_RDONLY | O_WRONLY | O_RDWR; pub const SEEK_SET: usize = 0; diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 743b7c3220a..f4fe52ca3b3 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -825,8 +825,6 @@ pub fn park_timeout(dur: Duration) { /// # Examples /// /// ``` -/// #![feature(thread_id)] -/// /// use std::thread; /// /// let other_thread = thread::spawn(|| { @@ -836,7 +834,7 @@ pub fn park_timeout(dur: Duration) { /// let other_thread_id = other_thread.join().unwrap(); /// assert!(thread::current().id() != other_thread_id); /// ``` -#[unstable(feature = "thread_id", issue = "21507")] +#[stable(feature = "thread_id", since = "1.19.0")] #[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)] pub struct ThreadId(u64); @@ -966,8 +964,6 @@ impl Thread { /// # Examples /// /// ``` - /// #![feature(thread_id)] - /// /// use std::thread; /// /// let other_thread = thread::spawn(|| { @@ -977,7 +973,7 @@ impl Thread { /// let other_thread_id = other_thread.join().unwrap(); /// assert!(thread::current().id() != other_thread_id); /// ``` - #[unstable(feature = "thread_id", issue = "21507")] + #[stable(feature = "thread_id", since = "1.19.0")] pub fn id(&self) -> ThreadId { self.inner.id } @@ -1168,8 +1164,6 @@ impl JoinHandle { /// # Examples /// /// ``` - /// #![feature(thread_id)] - /// /// use std::thread; /// /// let builder = thread::Builder::new(); diff --git a/src/libstd_unicode/tables.rs b/src/libstd_unicode/tables.rs index 7173040350e..0938738b52c 100644 --- a/src/libstd_unicode/tables.rs +++ b/src/libstd_unicode/tables.rs @@ -14,7 +14,7 @@ /// The version of [Unicode](http://www.unicode.org/) /// that the unicode parts of `CharExt` and `UnicodeStrPrelude` traits are based on. -pub const UNICODE_VERSION: (u64, u64, u64) = (9, 0, 0); +pub const UNICODE_VERSION: (u64, u64, u64) = (10, 0, 0); // BoolTrie is a trie for representing a set of Unicode codepoints. It is @@ -167,7 +167,7 @@ pub mod general_category { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 6, 7, 0, 0, 8, 0, 0, 0, 6, 0, 0, 0, 0, 0, 8, 0, 8, 0, 0, 0, 0, 0, 8, 0, 9, 6, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, + 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -236,7 +236,7 @@ pub mod derived_property { 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 95, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 96, 97, 36, 36, 36, 36, 98, 99, 36, 100, 101, 36, 102, - 103, 104, 105, 36, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 36, 117, 36, + 103, 104, 105, 36, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 36, 95, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, @@ -244,23 +244,23 @@ pub mod derived_property { 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 118, 119, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 117, 118, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, - 36, 36, 36, 36, 36, 120, 36, 121, 122, 123, 124, 125, 36, 36, 36, 36, 126, 127, 128, - 129, 31, 130, 36, 131, 132, 133, 113, 134 + 36, 36, 36, 36, 36, 119, 36, 120, 121, 122, 123, 124, 36, 36, 36, 36, 125, 126, 127, + 128, 31, 129, 36, 130, 131, 132, 113, 133 ], r3: &[ - 0x00001ffffcffffff, 0x0000000001ffffff, 0x3fdfffff00000000, 0xffff03f8fff00000, - 0xefffffffffffffff, 0xfffe000fffe1dfff, 0xe3c5fdfffff99fef, 0x0003000fb080599f, - 0xc36dfdfffff987ee, 0x003f00005e021987, 0xe3edfdfffffbbfee, 0x0200000f00011bbf, + 0x00001ffffcffffff, 0x000007ff01ffffff, 0x3fdfffff00000000, 0xffff03f8fff00000, + 0xefffffffffffffff, 0xfffe000fffe1dfff, 0xe3c5fdfffff99fef, 0x1003000fb080599f, + 0xc36dfdfffff987ee, 0x003f00005e021987, 0xe3edfdfffffbbfee, 0x1e00000f00011bbf, 0xe3edfdfffff99fee, 0x0002000fb0c0199f, 0xc3ffc718d63dc7ec, 0x0000000000811dc7, 0xe3fffdfffffddfef, 0x0000000f07601ddf, 0xe3effdfffffddfef, 0x0006000f40601ddf, - 0xe7fffffffffddfee, 0xfc00000f80f05ddf, 0x2ffbfffffc7fffec, 0x000c0000ff5f807f, + 0xe7fffffffffddfef, 0xfc00000f80f05ddf, 0x2ffbfffffc7fffec, 0x000c0000ff5f807f, 0x07fffffffffffffe, 0x000000000000207f, 0x3bffecaefef02596, 0x00000000f000205f, 0x0000000000000001, 0xfffe1ffffffffeff, 0x1ffffffffeffff03, 0x0000000000000000, 0xf97fffffffffffff, 0xffffc1e7ffff0000, 0xffffffff3000407f, 0xf7ffffffffff20bf, @@ -278,74 +278,76 @@ pub mod derived_property { 0x000003ffffffffff, 0xffff7fffffffffff, 0xffffffff7fffffff, 0x000c781fffffffff, 0xffff20bfffffffff, 0x000080ffffffffff, 0x7f7f7f7f007fffff, 0xffffffff7f7f7f7f, 0x0000800000000000, 0x1f3e03fe000000e0, 0xfffffffee07fffff, 0xf7ffffffffffffff, - 0xfffe3fffffffffe0, 0x07ffffff00007fff, 0xffff000000000000, 0x00000000003fffff, + 0xfffe7fffffffffe0, 0x07ffffff00007fff, 0xffff000000000000, 0x000007ffffffffff, 0x0000000000001fff, 0x3fffffffffff0000, 0x00000c00ffff1fff, 0x8ff07fffffffffff, 0x0000ffffffffffff, 0xfffffffcff800000, 0x00ff7ffffffff9ff, 0xff80000000000000, 0x000000fffffff7bb, 0x000fffffffffffff, 0x28fc00000000002f, 0xffff07fffffffc00, 0x1fffffff0007ffff, 0xfff7ffffffffffff, 0x7c00ffdf00008000, 0x007fffffffffffff, 0xc47fffff00003fff, 0x7fffffffffffffff, 0x003cffff38000005, 0xffff7f7f007e7e7e, - 0xffff003ff7ffffff, 0x000007ffffffffff, 0xffff000fffffffff, 0x0ffffffffffff87f, - 0xffff3fffffffffff, 0x0000000003ffffff, 0x5f7ffdffe0f8007f, 0xffffffffffffffdb, - 0x0003ffffffffffff, 0xfffffffffff80000, 0x3fffffffffffffff, 0xffffffffffff0000, - 0xfffffffffffcffff, 0x0fff0000000000ff, 0xffdf000000000000, 0x1fffffffffffffff, - 0x07fffffe00000000, 0xffffffc007fffffe, 0x000000001cfcfcfc + 0xffff003ff7ffffff, 0xffff000fffffffff, 0x0ffffffffffff87f, 0xffff3fffffffffff, + 0x0000000003ffffff, 0x5f7ffdffe0f8007f, 0xffffffffffffffdb, 0x0003ffffffffffff, + 0xfffffffffff80000, 0x3fffffffffffffff, 0xffffffffffff0000, 0xfffffffffffcffff, + 0x0fff0000000000ff, 0xffdf000000000000, 0x1fffffffffffffff, 0x07fffffe00000000, + 0xffffffc007fffffe, 0x000000001cfcfcfc ], r4: [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 5, 5, 9, 5, 10, 11, 12, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 13, 14, - 15, 5, 5, 16, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 15, 7, 16, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 ], r5: &[ 0, 1, 2, 3, 4, 5, 4, 4, 4, 4, 6, 7, 8, 9, 10, 11, 2, 2, 12, 13, 14, 15, 4, 4, 2, 2, 2, 2, 16, 17, 4, 4, 18, 19, 20, 21, 22, 4, 23, 4, 24, 25, 26, 27, 28, 29, 30, 4, 2, 31, 32, 32, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 33, 34, 35, 32, 36, 2, 37, 38, 4, 39, 40, 41, 42, 4, 4, 2, 43, 2, 44, 4, 4, 45, 46, 47, 48, 28, 4, 49, 4, 4, 4, 4, 4, 50, 51, 4, 4, 4, - 4, 4, 4, 4, 52, 4, 4, 4, 4, 53, 54, 55, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 56, 4, 2, 57, 2, 2, 2, 58, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 52, 53, 54, 55, 4, 4, 4, 4, 56, 57, 58, 4, 59, 60, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 61, 4, 2, 62, 2, 2, 2, 63, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 57, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 62, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 59, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 64, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, - 2, 2, 2, 2, 52, 20, 4, 60, 16, 61, 62, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 63, 64, - 65, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, + 2, 2, 2, 2, 2, 2, 55, 20, 4, 65, 16, 66, 67, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, + 68, 69, 70, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 66, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 32, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 67, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 71, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 32, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 20, 72, 2, 2, 2, 2, 2, 73, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 2, 68, 69, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 2, 70, 71, 72, 73, 74, 2, 2, 2, 2, 75, 76, 77, 78, 79, 80, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 81, + 4, 4, 4, 4, 4, 4, 4, 2, 74, 75, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 76, 77, 78, 79, 80, 2, 2, 2, 2, 81, 82, 83, 84, 85, 86, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 2, 2, 2, 82, 2, 83, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 84, 85, - 86, 4, 4, 4, 4, 4, 4, 4, 4, 4, 87, 88, 89, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 87, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 2, 2, 2, 88, 2, 89, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 90, 91, 92, 4, 4, 4, 4, 4, 4, 4, 4, 4, 72, 93, 94, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 90, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 95, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 10, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 91, 4, 4, 4, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 96, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 97, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 92, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 98, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ], r6: &[ 0xb7ffff7fffffefff, 0x000000003fff3fff, 0xffffffffffffffff, 0x07ffffffffffffff, 0x0000000000000000, 0x001fffffffffffff, 0xffffffff1fffffff, 0x000000000001ffff, - 0xffff0000ffffffff, 0x07ffffffffff07ff, 0xffffffff3fffffff, 0x00000000003eff0f, + 0xffffe000ffffffff, 0x07ffffffffff07ff, 0xffffffff3fffffff, 0x00000000003eff0f, 0xffff00003fffffff, 0x0fffffffff0fffff, 0xffff00ffffffffff, 0x0000000fffffffff, 0x007fffffffffffff, 0x000000ff003fffff, 0x91bffffffffffd3f, 0x007fffff003fffff, 0x000000007fffffff, 0x0037ffff00000000, 0x03ffffff003fffff, 0xc0ffffffffffffff, @@ -356,17 +358,18 @@ pub mod derived_property { 0x000001ffffffffff, 0xe3edfdfffff99fef, 0x0000000fe081199f, 0x00000000000007bb, 0x00000000000000b3, 0x7f3fffffffffffff, 0x000000003f000000, 0x7fffffffffffffff, 0x0000000000000011, 0x000007ffe3ffffff, 0xffffffff00000000, 0x80000000ffffffff, - 0x01ffffffffffffff, 0x7f7ffffffffffdff, 0xfffc000000000001, 0x007ffefffffcffff, - 0x0000000003ffffff, 0x00007fffffffffff, 0x000000000000000f, 0x000000000000007f, - 0x00003fffffff0000, 0xe0fffff80000000f, 0x000000000000ffff, 0x7fffffffffff001f, - 0x00000000fff80000, 0x0000000100000000, 0x00001fffffffffff, 0x0000000000000003, - 0x1fff07ffffffffff, 0x0000000043ff01ff, 0xffffffffffdfffff, 0xebffde64dfffffff, - 0xffffffffffffffef, 0x7bffffffdfdfe7bf, 0xfffffffffffdfc5f, 0xffffff3fffffffff, - 0xf7fffffff7fffffd, 0xffdfffffffdfffff, 0xffff7fffffff7fff, 0xfffffdfffffffdff, - 0x0000000000000ff7, 0x000007dbf9ffff7f, 0x000000000000001f, 0x000000000000008f, - 0x0af7fe96ffffffef, 0x5ef7f796aa96ea84, 0x0ffffbee0ffffbff, 0xffff000000000000, - 0xffff03ffffff03ff, 0x00000000000003ff, 0x00000000007fffff, 0x00000003ffffffff, - 0x000000003fffffff + 0x7fe7ffffffffffff, 0xffffffffffff0000, 0x0000000000ffffcf, 0x01ffffffffffffff, + 0x7f7ffffffffffdff, 0xfffc000000000001, 0x007ffefffffcffff, 0xb47ffffffffffb7f, + 0x00000000000000cb, 0x0000000003ffffff, 0x00007fffffffffff, 0x000000000000000f, + 0x000000000000007f, 0x00003fffffff0000, 0xe0fffff80000000f, 0x000000000000ffff, + 0x7fffffffffff001f, 0x00000000fff80000, 0x0000000300000000, 0x00001fffffffffff, + 0xffff000000000000, 0x0fffffffffffffff, 0x1fff07ffffffffff, 0x0000000043ff01ff, + 0xffffffffffdfffff, 0xebffde64dfffffff, 0xffffffffffffffef, 0x7bffffffdfdfe7bf, + 0xfffffffffffdfc5f, 0xffffff3fffffffff, 0xf7fffffff7fffffd, 0xffdfffffffdfffff, + 0xffff7fffffff7fff, 0xfffffdfffffffdff, 0x0000000000000ff7, 0x000007dbf9ffff7f, + 0x000000000000001f, 0x000000000000008f, 0x0af7fe96ffffffef, 0x5ef7f796aa96ea84, + 0x0ffffbee0ffffbff, 0xffff03ffffff03ff, 0x00000000000003ff, 0x00000000007fffff, + 0xffff0003ffffffff, 0x00000001ffffffff, 0x000000003fffffff ], }; @@ -426,9 +429,9 @@ pub mod derived_property { r3: &[ 0x00003fffffc00000, 0x000000000e000000, 0x0000000000000000, 0xfffffffffff00000, 0x1400000000000007, 0x0002000c00fe21fe, 0x1000000000000002, 0x0000000c0000201e, - 0x1000000000000006, 0x0023000000023986, 0x0000000c000021be, 0x9000000000000002, + 0x1000000000000006, 0x0023000000023986, 0xfc00000c000021be, 0x9000000000000002, 0x0000000c0040201e, 0x0000000000000004, 0x0000000000002001, 0xc000000000000001, - 0x0000000c00603dc1, 0x0000000c00003040, 0x0000000000000002, 0x00000000005c0400, + 0x0000000c00603dc1, 0x0000000c00003040, 0x1800000000000003, 0x00000000005c0400, 0x07f2000000000000, 0x0000000000007fc0, 0x1bf2000000000000, 0x0000000000003f40, 0x02a0000003000000, 0x7ffe000000000000, 0x1ffffffffeffe0df, 0x0000000000000040, 0x66fde00000000000, 0x001e0001c3000000, 0x0000000020002064, 0x1000000000000000, @@ -437,7 +440,7 @@ pub mod derived_property { 0x0e04018700000000, 0x0000000009800000, 0x9ff81fe57f400000, 0x7fff008000000000, 0x17d000000000000f, 0x000ff80000000004, 0x00003b3c00000003, 0x0003a34000000000, 0x00cff00000000000, 0x3f00000000000000, 0x031021fdfff70000, 0xfffff00000000000, - 0x010007ffffffffff, 0xfffffffff8000000, 0xf83fffffffffffff, 0xa000000000000000, + 0x010007ffffffffff, 0xfffffffff8000000, 0xfbffffffffffffff, 0xa000000000000000, 0x6000e000e000e003, 0x00007c900300f800, 0x8002ffdf00000000, 0x000000001fff0000, 0x0001ffffffff0000, 0x3000000000000000, 0x0003800000000000, 0x8000800000000000, 0xffffffff00000000, 0x0000800000000000, 0x083e3c0000000020, 0x000000007e000000, @@ -465,24 +468,24 @@ pub mod derived_property { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 8, 0, 9, 10, 11, 12, 13, 0, 0, 14, 15, 16, 0, 0, 17, 18, 19, 20, - 0, 0, 21, 22, 23, 24, 25, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 27, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 21, 22, 23, 24, 25, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 28, 29, 0, 0, 0, + 0, 0, 30, 0, 31, 0, 32, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, - 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 35, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 38, 39, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 42, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 35, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 37, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 41, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 44, 45, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 45, - 0, 0, 45, 45, 45, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0 + 50, 51, 0, 0, 51, 51, 51, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 ], r6: &[ 0x0000000000000000, 0x2000000000000000, 0x0000000100000000, 0x07c0000000000000, @@ -491,12 +494,14 @@ pub mod derived_property { 0x0000000000001c00, 0x40d3800000000000, 0x000007f880000000, 0x1000000000000003, 0x001f1fc000000001, 0xff00000000000000, 0x000000000000005c, 0x85f8000000000000, 0x000000000000000d, 0xb03c000000000000, 0x0000000030000001, 0xa7f8000000000000, - 0x0000000000000001, 0x00bf280000000000, 0x00000fbce0000000, 0xbf7f000000000000, - 0x006dfcfffffc0000, 0x001f000000000000, 0x007f000000000000, 0x000000000000000f, - 0x00000000ffff8000, 0x0000000f60000000, 0xfff8038000000000, 0x00003c0000000fe7, - 0x000000000000001c, 0xf87fffffffffffff, 0x00201fffffffffff, 0x0000fffef8000010, - 0x000007dbf9ffff7f, 0x00000000007f0000, 0x00000000000007f0, 0xf800000000000000, - 0xffffffff00000002, 0xffffffffffffffff, 0x0000ffffffffffff + 0x0000000000000001, 0x00bf280000000000, 0x00000fbce0000000, 0x79f800000000067e, + 0x000000000e7e0080, 0x00000000037ffc00, 0xbf7f000000000000, 0x006dfcfffffc0000, + 0xb47e000000000000, 0x00000000000000bf, 0x001f000000000000, 0x007f000000000000, + 0x000000000000000f, 0x00000000ffff8000, 0x0000000300000000, 0x0000000f60000000, + 0xfff8038000000000, 0x00003c0000000fe7, 0x000000000000001c, 0xf87fffffffffffff, + 0x00201fffffffffff, 0x0000fffef8000010, 0x000007dbf9ffff7f, 0x00000000007f0000, + 0x00000000000007f0, 0xf800000000000000, 0xffffffff00000002, 0xffffffffffffffff, + 0x0000ffffffffffff ], }; @@ -851,12 +856,12 @@ pub mod derived_property { 127 ], r3: &[ - 0x00003fffffffffff, 0x000000000fffffff, 0x3fdfffff00000000, 0xfffffffbfff00000, - 0xffffffffffffffff, 0xfffeffcfffffffff, 0xf3c5fdfffff99fef, 0x0003ffcfb080799f, - 0xd36dfdfffff987ee, 0x003fffc05e023987, 0xf3edfdfffffbbfee, 0x0200ffcf00013bbf, + 0x00003fffffffffff, 0x000007ff0fffffff, 0x3fdfffff00000000, 0xfffffffbfff00000, + 0xffffffffffffffff, 0xfffeffcfffffffff, 0xf3c5fdfffff99fef, 0x1003ffcfb080799f, + 0xd36dfdfffff987ee, 0x003fffc05e023987, 0xf3edfdfffffbbfee, 0xfe00ffcf00013bbf, 0xf3edfdfffff99fee, 0x0002ffcfb0c0399f, 0xc3ffc718d63dc7ec, 0x0000ffc000813dc7, 0xe3fffdfffffddfef, 0x0000ffcf07603ddf, 0xf3effdfffffddfef, 0x0006ffcf40603ddf, - 0xe7fffffffffddfee, 0xfc00ffcf80f07ddf, 0x2ffbfffffc7fffec, 0x000cffc0ff5f847f, + 0xfffffffffffddfef, 0xfc00ffcf80f07ddf, 0x2ffbfffffc7fffec, 0x000cffc0ff5f847f, 0x07fffffffffffffe, 0x0000000003ff7fff, 0x3bffecaefef02596, 0x00000000f3ff3f5f, 0xc2a003ff03000001, 0xfffe1ffffffffeff, 0x1ffffffffeffffdf, 0x0000000000000040, 0xffffffffffff03ff, 0xffffffff3fffffff, 0xf7ffffffffff20bf, 0xffffffff3d7f3dff, @@ -867,13 +872,13 @@ pub mod derived_property { 0x003fffffffffffff, 0x0fff0fff7fffffff, 0x001f3fffffffffc0, 0xffff0fffffffffff, 0x0000000007ff03ff, 0xffffffff0fffffff, 0x9fffffff7fffffff, 0x3fff008003ff03ff, 0x0000000000000000, 0x000ff80003ff0fff, 0x000fffffffffffff, 0x3fffffffffffe3ff, - 0x00000000000001ff, 0x037ffffffff70000, 0xf83fffffffffffff, 0xffffffff3f3fffff, + 0x00000000000001ff, 0x03fffffffff70000, 0xfbffffffffffffff, 0xffffffff3f3fffff, 0x3fffffffaaff3f3f, 0x5fdfffffffffffff, 0x1fdc1fff0fcf1fdc, 0x8000000000000000, 0x8002000000100001, 0x000000001fff0000, 0x0001ffe21fff0000, 0xf3fffd503f2ffc84, 0xffffffff000043e0, 0xffff7fffffffffff, 0xffffffff7fffffff, 0x000ff81fffffffff, 0xffff20bfffffffff, 0x800080ffffffffff, 0x7f7f7f7f007fffff, 0xffffffff7f7f7f7f, - 0x1f3efffe000000e0, 0xfffffffee67fffff, 0xf7ffffffffffffff, 0xfffe3fffffffffe0, - 0x07ffffff00007fff, 0xffff000000000000, 0x00000000003fffff, 0x0000000000001fff, + 0x1f3efffe000000e0, 0xfffffffee67fffff, 0xf7ffffffffffffff, 0xfffe7fffffffffe0, + 0x07ffffff00007fff, 0xffff000000000000, 0x000007ffffffffff, 0x0000000000001fff, 0x3fffffffffff0000, 0x00000fffffff1fff, 0xbff0ffffffffffff, 0x0003ffffffffffff, 0xfffffffcff800000, 0x00ff7ffffffff9ff, 0xff80000000000000, 0x000000ffffffffff, 0x28ffffff03ff003f, 0xffff3fffffffffff, 0x1fffffff000fffff, 0x7fffffff03ff8001, @@ -886,60 +891,62 @@ pub mod derived_property { ], r4: [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 5, 5, 9, 5, 10, 11, 5, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 13, - 14, 5, 5, 15, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 14, 7, 15, 16, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 16, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 + 5, 5, 5, 5, 5, 5, 5, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 ], r5: &[ 0, 1, 2, 3, 4, 5, 4, 6, 4, 4, 7, 8, 9, 10, 11, 12, 2, 2, 13, 14, 15, 16, 4, 4, 2, 2, 2, 2, 17, 18, 4, 4, 19, 20, 21, 22, 23, 4, 24, 4, 25, 26, 27, 28, 29, 30, 31, 4, 2, 32, 33, 33, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 34, 3, 35, 36, 37, 2, 38, 39, 4, 40, 41, 42, 43, 4, 4, 2, 44, 2, 45, 4, 4, 46, 47, 2, 48, 49, 50, 51, 4, 4, 4, 4, 4, 52, 53, 4, 4, 4, - 4, 4, 4, 4, 54, 4, 4, 4, 4, 55, 56, 57, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 58, 4, 2, 59, 2, 2, 2, 60, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 54, 55, 56, 57, 4, 4, 4, 4, 58, 59, 60, 4, 61, 62, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 63, 4, 2, 64, 2, 2, 2, 65, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 59, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 64, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 61, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 66, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, - 2, 2, 2, 2, 54, 62, 4, 63, 17, 64, 65, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 66, 67, - 68, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, + 2, 2, 2, 2, 2, 2, 57, 67, 4, 68, 17, 69, 70, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, + 71, 72, 73, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 69, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 33, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 70, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 74, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 33, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 21, 75, 2, 2, 2, 2, 2, 76, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 2, 71, 72, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 73, 74, 4, 4, - 75, 4, 4, 4, 4, 4, 4, 2, 76, 77, 78, 79, 80, 2, 2, 2, 2, 81, 82, 83, 84, 85, 86, 4, 4, - 4, 4, 4, 4, 4, 4, 87, 88, 89, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 90, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 2, 2, 2, 91, 2, 44, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 92, 93, 94, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 95, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 4, 4, 4, 4, 4, 4, 4, 2, 77, 78, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 79, 80, 4, 4, 81, 4, 4, 4, 4, 4, 4, 2, 82, 83, 84, 85, 86, 2, 2, 2, 2, 87, 88, 89, 90, + 91, 92, 4, 4, 4, 4, 4, 4, 4, 4, 93, 94, 95, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 96, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 97, 2, 44, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 98, 99, 100, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 101, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 11, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 11, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 96, 4, 4, 4, 4, 4, 4, 4, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 102, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 103, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 2, 2, 2, 2, 2, 2, 2, 2, 97, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 98, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 104, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 105, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ], r6: &[ 0xb7ffff7fffffefff, 0x000000003fff3fff, 0xffffffffffffffff, 0x07ffffffffffffff, 0x0000000000000000, 0x001fffffffffffff, 0x2000000000000000, 0xffffffff1fffffff, - 0x000000010001ffff, 0xffff0000ffffffff, 0x07ffffffffff07ff, 0xffffffff3fffffff, + 0x000000010001ffff, 0xffffe000ffffffff, 0x07ffffffffff07ff, 0xffffffff3fffffff, 0x00000000003eff0f, 0xffff03ff3fffffff, 0x0fffffffff0fffff, 0xffff00ffffffffff, 0x0000000fffffffff, 0x007fffffffffffff, 0x000000ff003fffff, 0x91bffffffffffd3f, 0x007fffff003fffff, 0x000000007fffffff, 0x0037ffff00000000, 0x03ffffff003fffff, @@ -950,18 +957,20 @@ pub mod derived_property { 0xffff01ffbfffbd7f, 0x03ff07ffffffffff, 0xf3edfdfffff99fef, 0x001f1fcfe081399f, 0x0000000003ff07ff, 0x0000000003ff00bf, 0xff3fffffffffffff, 0x000000003f000001, 0x0000000003ff0011, 0x00ffffffffffffff, 0x00000000000003ff, 0x03ff0fffe3ffffff, - 0xffffffff00000000, 0x800003ffffffffff, 0x01ffffffffffffff, 0xff7ffffffffffdff, - 0xfffc000003ff0001, 0x007ffefffffcffff, 0x0000000003ffffff, 0x00007fffffffffff, - 0x000000000000000f, 0x000000000000007f, 0x000003ff7fffffff, 0x001f3fffffff0000, - 0xe0fffff803ff000f, 0x000000000000ffff, 0x7fffffffffff001f, 0x00000000ffff8000, - 0x0000000100000000, 0x00001fffffffffff, 0x0000000000000003, 0x1fff07ffffffffff, - 0x0000000063ff01ff, 0xf807e3e000000000, 0x00003c0000000fe7, 0x000000000000001c, - 0xffffffffffdfffff, 0xebffde64dfffffff, 0xffffffffffffffef, 0x7bffffffdfdfe7bf, - 0xfffffffffffdfc5f, 0xffffff3fffffffff, 0xf7fffffff7fffffd, 0xffdfffffffdfffff, - 0xffff7fffffff7fff, 0xfffffdfffffffdff, 0xffffffffffffcff7, 0xf87fffffffffffff, - 0x00201fffffffffff, 0x0000fffef8000010, 0x000007dbf9ffff7f, 0x00000000007f001f, - 0x0af7fe96ffffffef, 0x5ef7f796aa96ea84, 0x0ffffbee0ffffbff, 0x00000000007fffff, - 0x00000003ffffffff, 0x000000003fffffff, 0x0000ffffffffffff + 0xffffffff00000000, 0x800003ffffffffff, 0x7fffffffffffffff, 0xffffffffffff0080, + 0x0000000003ffffcf, 0x01ffffffffffffff, 0xff7ffffffffffdff, 0xfffc000003ff0001, + 0x007ffefffffcffff, 0xb47ffffffffffb7f, 0x0000000003ff00ff, 0x0000000003ffffff, + 0x00007fffffffffff, 0x000000000000000f, 0x000000000000007f, 0x000003ff7fffffff, + 0x001f3fffffff0000, 0xe0fffff803ff000f, 0x000000000000ffff, 0x7fffffffffff001f, + 0x00000000ffff8000, 0x0000000300000000, 0x00001fffffffffff, 0xffff000000000000, + 0x0fffffffffffffff, 0x1fff07ffffffffff, 0x0000000063ff01ff, 0xf807e3e000000000, + 0x00003c0000000fe7, 0x000000000000001c, 0xffffffffffdfffff, 0xebffde64dfffffff, + 0xffffffffffffffef, 0x7bffffffdfdfe7bf, 0xfffffffffffdfc5f, 0xffffff3fffffffff, + 0xf7fffffff7fffffd, 0xffdfffffffdfffff, 0xffff7fffffff7fff, 0xfffffdfffffffdff, + 0xffffffffffffcff7, 0xf87fffffffffffff, 0x00201fffffffffff, 0x0000fffef8000010, + 0x000007dbf9ffff7f, 0x00000000007f001f, 0x0af7fe96ffffffef, 0x5ef7f796aa96ea84, + 0x0ffffbee0ffffbff, 0x00000000007fffff, 0xffff0003ffffffff, 0x00000001ffffffff, + 0x000000003fffffff, 0x0000ffffffffffff ], }; @@ -1027,8 +1036,8 @@ pub mod derived_property { 129, 130, 131, 132 ], r3: &[ - 0x00000110043fffff, 0x0000000001ffffff, 0x3fdfffff00000000, 0x0000000000000000, - 0x23fffffffffffff0, 0xfffe0003ff010000, 0x23c5fdfffff99fe1, 0x00030003b0004000, + 0x00000110043fffff, 0x000007ff01ffffff, 0x3fdfffff00000000, 0x0000000000000000, + 0x23fffffffffffff0, 0xfffe0003ff010000, 0x23c5fdfffff99fe1, 0x10030003b0004000, 0x036dfdfffff987e0, 0x001c00005e000000, 0x23edfdfffffbbfe0, 0x0200000300010000, 0x23edfdfffff99fe0, 0x00020003b0000000, 0x03ffc718d63dc7e8, 0x0000000000010000, 0x23fffdfffffddfe0, 0x0000000307000000, 0x23effdfffffddfe1, 0x0006000340000000, @@ -1048,8 +1057,8 @@ pub mod derived_property { 0x1fdc1fff0fcf1fdc, 0x8002000000000000, 0x000000001fff0000, 0xf3fffd503f2ffc84, 0xffffffff000043e0, 0xffff7fffffffffff, 0xffffffff7fffffff, 0x000c781fffffffff, 0xffff20bfffffffff, 0x000080ffffffffff, 0x7f7f7f7f007fffff, 0x000000007f7f7f7f, - 0x1f3e03fe000000e0, 0xfffffffee07fffff, 0xf7ffffffffffffff, 0xfffe3fffffffffe0, - 0x07ffffff00007fff, 0xffff000000000000, 0x00000000003fffff, 0x0000000000001fff, + 0x1f3e03fe000000e0, 0xfffffffee07fffff, 0xf7ffffffffffffff, 0xfffe7fffffffffe0, + 0x07ffffff00007fff, 0xffff000000000000, 0x000007ffffffffff, 0x0000000000001fff, 0x3fffffffffff0000, 0x00000c00ffff1fff, 0x80007fffffffffff, 0xffffffff3fffffff, 0x0000ffffffffffff, 0xfffffffcff800000, 0x00ff7ffffffff9ff, 0xff80000000000000, 0x00000007fffff7bb, 0x000ffffffffffffc, 0x28fc000000000000, 0xffff003ffffffc00, @@ -1064,58 +1073,60 @@ pub mod derived_property { ], r4: [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 5, 5, 9, 5, 10, 11, 5, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 13, - 14, 5, 5, 15, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 14, 7, 15, 16, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 ], r5: &[ 0, 1, 2, 3, 4, 5, 4, 4, 4, 4, 6, 7, 8, 9, 10, 11, 2, 2, 12, 13, 14, 15, 4, 4, 2, 2, 2, 2, 16, 17, 4, 4, 18, 19, 20, 21, 22, 4, 23, 4, 24, 25, 26, 27, 28, 29, 30, 4, 2, 31, 32, 32, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 33, 4, 34, 35, 36, 37, 38, 39, 40, 4, 41, 20, 42, 43, 4, 4, 5, 44, 45, 46, 4, 4, 47, 48, 45, 49, 50, 4, 51, 4, 4, 4, 4, 4, 52, 53, 4, - 4, 4, 4, 4, 4, 4, 54, 4, 4, 4, 4, 55, 56, 57, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 51, 4, 2, 47, 2, 2, 2, 58, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 54, 55, 56, 57, 4, 4, 4, 4, 58, 59, 60, 4, 61, 62, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 51, 4, 2, 47, 2, 2, 2, 63, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 47, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 47, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 59, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 64, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, - 2, 2, 2, 2, 2, 2, 54, 20, 4, 60, 45, 61, 57, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, - 62, 63, 64, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 2, 2, 2, 2, 2, 2, 2, 2, 57, 20, 4, 65, 45, 66, 60, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 2, 67, 68, 69, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 65, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 32, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 66, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 70, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 32, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 20, 71, 2, 2, 2, 2, 2, + 72, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 2, 73, 74, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 75, 76, 77, 78, 79, 2, 2, 2, 2, 80, 81, 82, 83, 84, + 85, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 2, 67, 68, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 69, 70, 71, 72, 73, 2, 2, 2, 2, 74, 75, 76, 77, 78, 79, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 2, 2, 2, 80, 2, 58, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 81, 82, 83, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 84, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 86, 2, 63, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 87, 88, 89, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 90, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 85, 4, 4, 4, 4, 4, 4, 4, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 91, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 92, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 2, 2, 2, 2, 2, 2, 2, 2, 86, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 93, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ], r6: &[ 0xb7ffff7fffffefff, 0x000000003fff3fff, 0xffffffffffffffff, 0x07ffffffffffffff, 0x0000000000000000, 0x001fffffffffffff, 0xffffffff1fffffff, 0x000000000001ffff, - 0xffff0000ffffffff, 0x003fffffffff07ff, 0xffffffff3fffffff, 0x00000000003eff0f, + 0xffffe000ffffffff, 0x003fffffffff07ff, 0xffffffff3fffffff, 0x00000000003eff0f, 0xffff00003fffffff, 0x0fffffffff0fffff, 0xffff00ffffffffff, 0x0000000fffffffff, 0x007fffffffffffff, 0x000000ff003fffff, 0x91bffffffffffd3f, 0x007fffff003fffff, 0x000000007fffffff, 0x0037ffff00000000, 0x03ffffff003fffff, 0xc0ffffffffffffff, @@ -1126,15 +1137,17 @@ pub mod derived_property { 0x00000ffffffbffff, 0xffff01ffbfffbd7f, 0x23edfdfffff99fe0, 0x00000003e0010000, 0x0000000000000780, 0x0000ffffffffffff, 0x00000000000000b0, 0x00007fffffffffff, 0x000000000f000000, 0x0000000000000010, 0x000007ffffffffff, 0x0000000003ffffff, - 0xffffffff00000000, 0x80000000ffffffff, 0x01ffffffffffffff, 0x00007ffffffffdff, - 0xfffc000000000001, 0x000000000000ffff, 0x000000000000000f, 0x000000000000007f, - 0x00003fffffff0000, 0xe0fffff80000000f, 0x000000000001001f, 0x00000000fff80000, - 0x0000000100000000, 0x00001fffffffffff, 0x0000000000000003, 0x1fff07ffffffffff, - 0x0000000003ff01ff, 0xffffffffffdfffff, 0xebffde64dfffffff, 0xffffffffffffffef, - 0x7bffffffdfdfe7bf, 0xfffffffffffdfc5f, 0xffffff3fffffffff, 0xf7fffffff7fffffd, - 0xffdfffffffdfffff, 0xffff7fffffff7fff, 0xfffffdfffffffdff, 0x0000000000000ff7, - 0x000000000000001f, 0x0af7fe96ffffffef, 0x5ef7f796aa96ea84, 0x0ffffbee0ffffbff, - 0x00000000007fffff, 0x00000003ffffffff, 0x000000003fffffff + 0xffffffff00000000, 0x80000000ffffffff, 0x0407fffffffff801, 0xfffffffff0010000, + 0x00000000000003cf, 0x01ffffffffffffff, 0x00007ffffffffdff, 0xfffc000000000001, + 0x000000000000ffff, 0x0001fffffffffb7f, 0x0000000000000040, 0x000000000000000f, + 0x000000000000007f, 0x00003fffffff0000, 0xe0fffff80000000f, 0x000000000001001f, + 0x00000000fff80000, 0x0000000300000000, 0x00001fffffffffff, 0xffff000000000000, + 0x0fffffffffffffff, 0x1fff07ffffffffff, 0x0000000003ff01ff, 0xffffffffffdfffff, + 0xebffde64dfffffff, 0xffffffffffffffef, 0x7bffffffdfdfe7bf, 0xfffffffffffdfc5f, + 0xffffff3fffffffff, 0xf7fffffff7fffffd, 0xffdfffffffdfffff, 0xffff7fffffff7fff, + 0xfffffdfffffffdff, 0x0000000000000ff7, 0x000000000000001f, 0x0af7fe96ffffffef, + 0x5ef7f796aa96ea84, 0x0ffffbee0ffffbff, 0x00000000007fffff, 0xffff0003ffffffff, + 0x00000001ffffffff, 0x000000003fffffff ], }; diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 325a5cdf8fc..d00e29d954f 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -97,9 +97,8 @@ impl Path { } pub fn default_to_global(mut self) -> Path { - let name = self.segments[0].identifier.name; - if !self.is_global() && name != "$crate" && - name != keywords::SelfValue.name() && name != keywords::Super.name() { + if !self.is_global() && + !::parse::token::Ident(self.segments[0].identifier).is_path_segment_keyword() { self.segments.insert(0, PathSegment::crate_root(self.span)); } self diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 5168943d108..1eb749623d8 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -11,7 +11,7 @@ use abi::Abi; use ast::{self, Ident, Generics, Expr, BlockCheckMode, UnOp, PatKind}; use attr; -use syntax_pos::{Span, DUMMY_SP}; +use syntax_pos::{Pos, Span, DUMMY_SP}; use codemap::{dummy_spanned, respan, Spanned}; use ext::base::ExtCtxt; use ptr::P; @@ -768,14 +768,15 @@ impl<'a> AstBuilder for ExtCtxt<'a> { let loc = self.codemap().lookup_char_pos(span.lo); let expr_file = self.expr_str(span, Symbol::intern(&loc.file.name)); let expr_line = self.expr_u32(span, loc.line as u32); - let expr_file_line_tuple = self.expr_tuple(span, vec![expr_file, expr_line]); - let expr_file_line_ptr = self.expr_addr_of(span, expr_file_line_tuple); + let expr_col = self.expr_u32(span, loc.col.to_usize() as u32 + 1); + let expr_loc_tuple = self.expr_tuple(span, vec![expr_file, expr_line, expr_col]); + let expr_loc_ptr = self.expr_addr_of(span, expr_loc_tuple); self.expr_call_global( span, - self.std_path(&["rt", "begin_panic"]), + self.std_path(&["rt", "begin_panic_new"]), vec![ self.expr_str(span, msg), - expr_file_line_ptr]) + expr_loc_ptr]) } fn expr_unreachable(&self, span: Span) -> P { diff --git a/src/libsyntax/ext/tt/quoted.rs b/src/libsyntax/ext/tt/quoted.rs index 18056f60287..4e9e30857b1 100644 --- a/src/libsyntax/ext/tt/quoted.rs +++ b/src/libsyntax/ext/tt/quoted.rs @@ -12,7 +12,7 @@ use ast; use ext::tt::macro_parser; use parse::{ParseSess, token}; use print::pprust; -use symbol::{keywords, Symbol}; +use symbol::keywords; use syntax_pos::{DUMMY_SP, Span, BytePos}; use tokenstream; @@ -199,7 +199,7 @@ fn parse_tree(tree: tokenstream::TokenTree, Some(tokenstream::TokenTree::Token(ident_span, token::Ident(ident))) => { let span = Span { lo: span.lo, ..ident_span }; if ident.name == keywords::Crate.name() { - let ident = ast::Ident { name: Symbol::intern("$crate"), ..ident }; + let ident = ast::Ident { name: keywords::DollarCrate.name(), ..ident }; TokenTree::Token(span, token::Ident(ident)) } else { TokenTree::MetaVar(span, ident) diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 3f3c94536a6..4b0ec1a20e3 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -360,6 +360,12 @@ declare_features! ( // rustc internal (active, abi_thiscall, "1.19.0", None), + + // Allows a test to fail without failing the whole suite + (active, allow_fail, "1.19.0", Some(42219)), + + // Allows unsized tuple coercion. + (active, unsized_tuple_coercion, "1.20.0", Some(42877)), ); declare_features! ( @@ -818,6 +824,11 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG "used internally by rustc", cfg_fn!(rustc_attrs))), + ("allow_fail", Normal, Gated(Stability::Unstable, + "allow_fail", + "allow_fail attribute is currently unstable", + cfg_fn!(allow_fail))), + // Crate level attributes ("crate_name", CrateLevel, Ungated), ("crate_type", CrateLevel, Ungated), @@ -1039,6 +1050,9 @@ pub const EXPLAIN_VIS_MATCHER: &'static str = pub const EXPLAIN_PLACEMENT_IN: &'static str = "placement-in expression syntax is experimental and subject to change."; +pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str = + "Unsized tuple coercion is not stable enough for use and is subject to change"; + struct PostExpansionVisitor<'a> { context: &'a Context<'a>, } diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 66775d8c43d..09cdf26bf1f 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -1285,7 +1285,7 @@ impl<'a> StringReader<'a> { }); let keyword_checking_token = &token::Ident(keyword_checking_ident); let last_bpos = self.pos; - if keyword_checking_token.is_any_keyword() && + if keyword_checking_token.is_reserved_ident() && !keyword_checking_token.is_keyword(keywords::Static) { self.err_span_(start, last_bpos, "lifetimes cannot use keyword names"); } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 2858d49d63d..c248e20b608 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -511,14 +511,13 @@ impl<'a> Parser<'a> { } pub fn this_token_descr(&self) -> String { - let s = self.this_token_to_string(); - if self.token.is_strict_keyword() { - format!("keyword `{}`", s) - } else if self.token.is_reserved_keyword() { - format!("reserved keyword `{}`", s) - } else { - format!("`{}`", s) - } + let prefix = match &self.token { + t if t.is_special_ident() => "reserved identifier ", + t if t.is_used_keyword() => "keyword ", + t if t.is_unused_keyword() => "reserved keyword ", + _ => "", + }; + format!("{}`{}`", prefix, self.this_token_to_string()) } pub fn unexpected_last(&self, t: &token::Token) -> PResult<'a, T> { @@ -637,10 +636,12 @@ impl<'a> Parser<'a> { } pub fn parse_ident(&mut self) -> PResult<'a, ast::Ident> { - self.check_strict_keywords(); - self.check_reserved_keywords(); match self.token { token::Ident(i) => { + if self.token.is_reserved_ident() { + self.span_err(self.span, &format!("expected identifier, found {}", + self.this_token_descr())); + } self.bump(); Ok(i) } @@ -713,25 +714,6 @@ impl<'a> Parser<'a> { } } - /// Signal an error if the given string is a strict keyword - pub fn check_strict_keywords(&mut self) { - if self.token.is_strict_keyword() { - let token_str = self.this_token_to_string(); - let span = self.span; - self.span_err(span, - &format!("expected identifier, found keyword `{}`", - token_str)); - } - } - - /// Signal an error if the current token is a reserved keyword - pub fn check_reserved_keywords(&mut self) { - if self.token.is_reserved_keyword() { - let token_str = self.this_token_to_string(); - self.fatal(&format!("`{}` is a reserved keyword", token_str)).emit() - } - } - fn check_ident(&mut self) -> bool { if self.token.is_ident() { true @@ -1659,8 +1641,10 @@ impl<'a> Parser<'a> { Ok(codemap::Spanned { node: lit, span: lo.to(self.prev_span) }) } - /// matches '-' lit | lit + /// matches '-' lit | lit (cf. ast_validation::AstValidator::check_expr_within_pat) pub fn parse_pat_literal_maybe_minus(&mut self) -> PResult<'a, P> { + maybe_whole_expr!(self); + let minus_lo = self.span; let minus_present = self.eat(&token::BinOp(token::Minus)); let lo = self.span; @@ -2299,7 +2283,7 @@ impl<'a> Parser<'a> { ex = ExprKind::Break(lt, e); hi = self.prev_span; } else if self.token.is_keyword(keywords::Let) { - // Catch this syntax error here, instead of in `check_strict_keywords`, so + // Catch this syntax error here, instead of in `parse_ident`, so // that we can explicitly mention that let is not to be used as an expression let mut db = self.fatal("expected expression, found statement (`let`)"); db.note("variable declaration using `let` is a statement"); @@ -3541,7 +3525,7 @@ impl<'a> Parser<'a> { // Parse box pat let subpat = self.parse_pat()?; pat = PatKind::Box(subpat); - } else if self.token.is_ident() && !self.token.is_any_keyword() && + } else if self.token.is_ident() && !self.token.is_reserved_ident() && self.parse_as_ident() { // Parse ident @ pat // This can give false positives and parse nullary enums, @@ -3816,7 +3800,7 @@ impl<'a> Parser<'a> { fn is_union_item(&self) -> bool { self.token.is_keyword(keywords::Union) && - self.look_ahead(1, |t| t.is_ident() && !t.is_any_keyword()) + self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident()) } fn is_defaultness(&self) -> bool { diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index d4198261d3f..834ac38af98 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -89,7 +89,7 @@ impl Lit { fn ident_can_begin_expr(ident: ast::Ident) -> bool { let ident_token: Token = Ident(ident); - !ident_token.is_any_keyword() || + !ident_token.is_reserved_ident() || ident_token.is_path_segment_keyword() || [ keywords::Do.name(), @@ -112,7 +112,7 @@ fn ident_can_begin_expr(ident: ast::Ident) -> bool { fn ident_can_begin_type(ident: ast::Ident) -> bool { let ident_token: Token = Ident(ident); - !ident_token.is_any_keyword() || + !ident_token.is_reserved_ident() || ident_token.is_path_segment_keyword() || [ keywords::For.name(), @@ -319,7 +319,7 @@ impl Token { pub fn is_path_start(&self) -> bool { self == &ModSep || self.is_qpath_start() || self.is_path() || - self.is_path_segment_keyword() || self.is_ident() && !self.is_any_keyword() + self.is_path_segment_keyword() || self.is_ident() && !self.is_reserved_ident() } /// Returns `true` if the token is a given keyword, `kw`. @@ -331,18 +331,23 @@ impl Token { match self.ident() { Some(id) => id.name == keywords::Super.name() || id.name == keywords::SelfValue.name() || - id.name == keywords::SelfType.name(), + id.name == keywords::SelfType.name() || + id.name == keywords::DollarCrate.name(), None => false, } } - /// Returns `true` if the token is either a strict or reserved keyword. - pub fn is_any_keyword(&self) -> bool { - self.is_strict_keyword() || self.is_reserved_keyword() + // Returns true for reserved identifiers used internally for elided lifetimes, + // unnamed method parameters, crate root module, error recovery etc. + pub fn is_special_ident(&self) -> bool { + match self.ident() { + Some(id) => id.name <= keywords::DollarCrate.name(), + _ => false, + } } - /// Returns `true` if the token is a strict keyword. - pub fn is_strict_keyword(&self) -> bool { + /// Returns `true` if the token is a keyword used in the language. + pub fn is_used_keyword(&self) -> bool { match self.ident() { Some(id) => id.name >= keywords::As.name() && id.name <= keywords::While.name(), _ => false, @@ -350,7 +355,7 @@ impl Token { } /// Returns `true` if the token is a keyword reserved for possible future use. - pub fn is_reserved_keyword(&self) -> bool { + pub fn is_unused_keyword(&self) -> bool { match self.ident() { Some(id) => id.name >= keywords::Abstract.name() && id.name <= keywords::Yield.name(), _ => false, @@ -410,6 +415,11 @@ impl Token { Whitespace | Comment | Shebang(..) | Eof => return None, }) } + + /// Returns `true` if the token is either a special identifier or a keyword. + pub fn is_reserved_ident(&self) -> bool { + self.is_special_ident() || self.is_used_keyword() || self.is_unused_keyword() + } } #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash)] diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index ac5b32c828a..d449e412d6c 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -760,7 +760,7 @@ pub trait PrintState<'a> { word(self.writer(), "::")? } if segment.identifier.name != keywords::CrateRoot.name() && - segment.identifier.name != "$crate" { + segment.identifier.name != keywords::DollarCrate.name() { word(self.writer(), &segment.identifier.name.as_str())?; } } @@ -2374,7 +2374,7 @@ impl<'a> State<'a> { -> io::Result<()> { if segment.identifier.name != keywords::CrateRoot.name() && - segment.identifier.name != "$crate" { + segment.identifier.name != keywords::DollarCrate.name() { self.print_ident(segment.identifier)?; if let Some(ref parameters) = segment.parameters { self.print_path_parameters(parameters, colons_before_params)?; diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index a0d1785c6ff..86f5f42eac7 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -52,7 +52,8 @@ struct Test { path: Vec , bench: bool, ignore: bool, - should_panic: ShouldPanic + should_panic: ShouldPanic, + allow_fail: bool, } struct TestCtxt<'a> { @@ -133,7 +134,8 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> { path: self.cx.path.clone(), bench: is_bench_fn(&self.cx, &i), ignore: is_ignored(&i), - should_panic: should_panic(&i, &self.cx) + should_panic: should_panic(&i, &self.cx), + allow_fail: is_allowed_fail(&i), }; self.cx.testfns.push(test); self.tests.push(i.ident); @@ -383,6 +385,10 @@ fn is_ignored(i: &ast::Item) -> bool { i.attrs.iter().any(|attr| attr.check_name("ignore")) } +fn is_allowed_fail(i: &ast::Item) -> bool { + i.attrs.iter().any(|attr| attr.check_name("allow_fail")) +} + fn should_panic(i: &ast::Item, cx: &TestCtxt) -> ShouldPanic { match i.attrs.iter().find(|attr| attr.check_name("should_panic")) { Some(attr) => { @@ -668,6 +674,7 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P { } } }; + let allow_fail_expr = ecx.expr_bool(span, test.allow_fail); // self::test::TestDesc { ... } let desc_expr = ecx.expr_struct( @@ -675,7 +682,8 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P { test_path("TestDesc"), vec![field("name", name_expr), field("ignore", ignore_expr), - field("should_panic", fail_expr)]); + field("should_panic", fail_expr), + field("allow_fail", allow_fail_expr)]); let mut visible_path = match cx.toplevel_reexport { diff --git a/src/libsyntax_ext/deriving/clone.rs b/src/libsyntax_ext/deriving/clone.rs index 1993d6ebe5b..35a2a2513f4 100644 --- a/src/libsyntax_ext/deriving/clone.rs +++ b/src/libsyntax_ext/deriving/clone.rs @@ -167,7 +167,7 @@ fn cs_clone(name: &str, all_fields = af; vdata = vdata_; } - EnumMatching(_, variant, ref af) => { + EnumMatching(.., variant, ref af) => { ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.node.name]); all_fields = af; vdata = &variant.node.data; diff --git a/src/libsyntax_ext/deriving/debug.rs b/src/libsyntax_ext/deriving/debug.rs index ec4cb815960..38ed596098b 100644 --- a/src/libsyntax_ext/deriving/debug.rs +++ b/src/libsyntax_ext/deriving/debug.rs @@ -60,7 +60,7 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P (substr.type_ident, vdata.is_struct()), - EnumMatching(_, v, _) => (v.node.name, v.node.data.is_struct()), + EnumMatching(_, _, v, _) => (v.node.name, v.node.data.is_struct()), EnumNonMatchingCollapsed(..) | StaticStruct(..) | StaticEnum(..) => cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`"), diff --git a/src/libsyntax_ext/deriving/encodable.rs b/src/libsyntax_ext/deriving/encodable.rs index 33f742282c1..1e19cd99419 100644 --- a/src/libsyntax_ext/deriving/encodable.rs +++ b/src/libsyntax_ext/deriving/encodable.rs @@ -237,7 +237,7 @@ fn encodable_substructure(cx: &mut ExtCtxt, blk]) } - EnumMatching(idx, variant, ref fields) => { + EnumMatching(idx, _, variant, ref fields) => { // We're not generating an AST that the borrow checker is expecting, // so we need to generate a unique local variable to take the // mutable loan out on, otherwise we get conflicts which don't diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 3a15b82d19f..4acd65bbf86 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -305,10 +305,10 @@ pub enum StaticFields { /// A summary of the possible sets of fields. pub enum SubstructureFields<'a> { Struct(&'a ast::VariantData, Vec>), - /// Matching variants of the enum: variant index, ast::Variant, + /// Matching variants of the enum: variant index, variant count, ast::Variant, /// fields: the field name is only non-`None` in the case of a struct /// variant. - EnumMatching(usize, &'a ast::Variant, Vec>), + EnumMatching(usize, usize, &'a ast::Variant, Vec>), /// Non-matching variants of the enum, but with all state hidden from /// the consequent code. The first component holds `Ident`s for all of @@ -1252,7 +1252,7 @@ impl<'a> MethodDef<'a> { // expressions for referencing every field of every // Self arg, assuming all are instances of VariantK. // Build up code associated with such a case. - let substructure = EnumMatching(index, variant, field_tuples); + let substructure = EnumMatching(index, variants.len(), variant, field_tuples); let arm_expr = self.call_substructure_method(cx, trait_, type_ident, @@ -1269,12 +1269,13 @@ impl<'a> MethodDef<'a> { // We need a default case that handles the fieldless variants. // The index and actual variant aren't meaningful in this case, // so just use whatever + let substructure = EnumMatching(0, variants.len(), v, Vec::new()); Some(self.call_substructure_method(cx, trait_, type_ident, &self_args[..], nonself_args, - &EnumMatching(0, v, Vec::new()))) + &substructure)) } _ if variants.len() > 1 && self_args.len() > 1 => { // Since we know that all the arguments will match if we reach diff --git a/src/libsyntax_ext/deriving/hash.rs b/src/libsyntax_ext/deriving/hash.rs index 97d7f2ce800..a341c21d0a1 100644 --- a/src/libsyntax_ext/deriving/hash.rs +++ b/src/libsyntax_ext/deriving/hash.rs @@ -81,7 +81,7 @@ fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) let mut stmts = Vec::new(); let fields = match *substr.fields { - Struct(_, ref fs) => fs, + Struct(_, ref fs) | EnumMatching(_, 1, .., ref fs) => fs, EnumMatching(.., ref fs) => { let variant_value = deriving::call_intrinsic(cx, trait_span, diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 6b5caff27e8..debac70545a 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -237,76 +237,76 @@ macro_rules! declare_keywords {( // NB: leaving holes in the ident table is bad! a different ident will get // interned with the id from the hole, but it will be between the min and max // of the reserved words, and thus tagged as "reserved". -// After modifying this list adjust `is_strict_keyword`/`is_reserved_keyword`, +// After modifying this list adjust `is_special_ident`, `is_used_keyword`/`is_unused_keyword`, // this should be rarely necessary though if the keywords are kept in alphabetic order. declare_keywords! { - // Invalid identifier + // Special reserved identifiers used internally for elided lifetimes, + // unnamed method parameters, crate root module, error recovery etc. (0, Invalid, "") + (1, CrateRoot, "{{root}}") + (2, DollarCrate, "$crate") - // Strict keywords used in the language. - (1, As, "as") - (2, Box, "box") - (3, Break, "break") - (4, Const, "const") - (5, Continue, "continue") - (6, Crate, "crate") - (7, Else, "else") - (8, Enum, "enum") - (9, Extern, "extern") - (10, False, "false") - (11, Fn, "fn") - (12, For, "for") - (13, If, "if") - (14, Impl, "impl") - (15, In, "in") - (16, Let, "let") - (17, Loop, "loop") - (18, Match, "match") - (19, Mod, "mod") - (20, Move, "move") - (21, Mut, "mut") - (22, Pub, "pub") - (23, Ref, "ref") - (24, Return, "return") - (25, SelfValue, "self") - (26, SelfType, "Self") - (27, Static, "static") - (28, Struct, "struct") - (29, Super, "super") - (30, Trait, "trait") - (31, True, "true") - (32, Type, "type") - (33, Unsafe, "unsafe") - (34, Use, "use") - (35, Where, "where") - (36, While, "while") + // Keywords used in the language. + (3, As, "as") + (4, Box, "box") + (5, Break, "break") + (6, Const, "const") + (7, Continue, "continue") + (8, Crate, "crate") + (9, Else, "else") + (10, Enum, "enum") + (11, Extern, "extern") + (12, False, "false") + (13, Fn, "fn") + (14, For, "for") + (15, If, "if") + (16, Impl, "impl") + (17, In, "in") + (18, Let, "let") + (19, Loop, "loop") + (20, Match, "match") + (21, Mod, "mod") + (22, Move, "move") + (23, Mut, "mut") + (24, Pub, "pub") + (25, Ref, "ref") + (26, Return, "return") + (27, SelfValue, "self") + (28, SelfType, "Self") + (29, Static, "static") + (30, Struct, "struct") + (31, Super, "super") + (32, Trait, "trait") + (33, True, "true") + (34, Type, "type") + (35, Unsafe, "unsafe") + (36, Use, "use") + (37, Where, "where") + (38, While, "while") // Keywords reserved for future use. - (37, Abstract, "abstract") - (38, Alignof, "alignof") - (39, Become, "become") - (40, Do, "do") - (41, Final, "final") - (42, Macro, "macro") - (43, Offsetof, "offsetof") - (44, Override, "override") - (45, Priv, "priv") - (46, Proc, "proc") - (47, Pure, "pure") - (48, Sizeof, "sizeof") - (49, Typeof, "typeof") - (50, Unsized, "unsized") - (51, Virtual, "virtual") - (52, Yield, "yield") + (39, Abstract, "abstract") + (40, Alignof, "alignof") + (41, Become, "become") + (42, Do, "do") + (43, Final, "final") + (44, Macro, "macro") + (45, Offsetof, "offsetof") + (46, Override, "override") + (47, Priv, "priv") + (48, Proc, "proc") + (49, Pure, "pure") + (50, Sizeof, "sizeof") + (51, Typeof, "typeof") + (52, Unsized, "unsized") + (53, Virtual, "virtual") + (54, Yield, "yield") // Weak keywords, have special meaning only in specific contexts. - (53, Default, "default") - (54, StaticLifetime, "'static") - (55, Union, "union") - (56, Catch, "catch") - - // A virtual keyword that resolves to the crate root when used in a lexical scope. - (57, CrateRoot, "{{root}}") + (55, Default, "default") + (56, StaticLifetime, "'static") + (57, Union, "union") + (58, Catch, "catch") } // If an interner exists in TLS, return it. Otherwise, prepare a fresh one. diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 2094fd8898d..92cfb862b16 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -212,6 +212,7 @@ pub struct TestDesc { pub name: TestName, pub ignore: bool, pub should_panic: ShouldPanic, + pub allow_fail: bool, } #[derive(Clone)] @@ -523,6 +524,7 @@ pub enum TestResult { TrFailed, TrFailedMsg(String), TrIgnored, + TrAllowedFail, TrMetrics(MetricMap), TrBench(BenchSamples), } @@ -543,6 +545,7 @@ struct ConsoleTestState { passed: usize, failed: usize, ignored: usize, + allowed_fail: usize, filtered_out: usize, measured: usize, metrics: MetricMap, @@ -572,6 +575,7 @@ impl ConsoleTestState { passed: 0, failed: 0, ignored: 0, + allowed_fail: 0, filtered_out: 0, measured: 0, metrics: MetricMap::new(), @@ -594,6 +598,10 @@ impl ConsoleTestState { self.write_short_result("ignored", "i", term::color::YELLOW) } + pub fn write_allowed_fail(&mut self) -> io::Result<()> { + self.write_short_result("FAILED (allowed)", "a", term::color::YELLOW) + } + pub fn write_metric(&mut self) -> io::Result<()> { self.write_pretty("metric", term::color::CYAN) } @@ -669,6 +677,7 @@ impl ConsoleTestState { TrOk => self.write_ok(), TrFailed | TrFailedMsg(_) => self.write_failed(), TrIgnored => self.write_ignored(), + TrAllowedFail => self.write_allowed_fail(), TrMetrics(ref mm) => { self.write_metric()?; self.write_plain(&format!(": {}\n", mm.fmt_metrics())) @@ -702,6 +711,7 @@ impl ConsoleTestState { TrFailed => "failed".to_owned(), TrFailedMsg(ref msg) => format!("failed: {}", msg), TrIgnored => "ignored".to_owned(), + TrAllowedFail => "failed (allowed)".to_owned(), TrMetrics(ref mm) => mm.fmt_metrics(), TrBench(ref bs) => fmt_bench_samples(bs), }, @@ -761,7 +771,8 @@ impl ConsoleTestState { } pub fn write_run_finish(&mut self) -> io::Result { - assert!(self.passed + self.failed + self.ignored + self.measured == self.total); + assert!(self.passed + self.failed + self.ignored + self.measured + + self.allowed_fail == self.total); if self.options.display_output { self.write_outputs()?; @@ -778,12 +789,24 @@ impl ConsoleTestState { } else { self.write_pretty("FAILED", term::color::RED)?; } - let s = format!(". {} passed; {} failed; {} ignored; {} measured; {} filtered out\n\n", - self.passed, - self.failed, - self.ignored, - self.measured, - self.filtered_out); + let s = if self.allowed_fail > 0 { + format!( + ". {} passed; {} failed ({} allowed); {} ignored; {} measured; {} filtered out\n\n", + self.passed, + self.failed + self.allowed_fail, + self.allowed_fail, + self.ignored, + self.measured, + self.filtered_out) + } else { + format!( + ". {} passed; {} failed; {} ignored; {} measured; {} filtered out\n\n", + self.passed, + self.failed, + self.ignored, + self.measured, + self.filtered_out) + }; self.write_plain(&s)?; return Ok(success); } @@ -891,6 +914,7 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec) -> io::Resu st.not_failures.push((test, stdout)); } TrIgnored => st.ignored += 1, + TrAllowedFail => st.allowed_fail += 1, TrMetrics(mm) => { let tname = test.name; let MetricMap(mm) = mm; @@ -945,12 +969,14 @@ fn should_sort_failures_before_printing_them() { name: StaticTestName("a"), ignore: false, should_panic: ShouldPanic::No, + allow_fail: false, }; let test_b = TestDesc { name: StaticTestName("b"), ignore: false, should_panic: ShouldPanic::No, + allow_fail: false, }; let mut st = ConsoleTestState { @@ -962,6 +988,7 @@ fn should_sort_failures_before_printing_them() { passed: 0, failed: 0, ignored: 0, + allowed_fail: 0, filtered_out: 0, measured: 0, max_name_len: 10, @@ -1471,8 +1498,13 @@ fn calc_result(desc: &TestDesc, task_result: Result<(), Box>) -> Tes .unwrap_or(false) { TrOk } else { - TrFailedMsg(format!("Panic did not include expected string '{}'", msg)) + if desc.allow_fail { + TrAllowedFail + } else { + TrFailedMsg(format!("Panic did not include expected string '{}'", msg)) + } }, + _ if desc.allow_fail => TrAllowedFail, _ => TrFailed, } } @@ -1706,6 +1738,7 @@ mod tests { name: StaticTestName("whatever"), ignore: true, should_panic: ShouldPanic::No, + allow_fail: false, }, testfn: DynTestFn(Box::new(move |()| f())), }; @@ -1723,6 +1756,7 @@ mod tests { name: StaticTestName("whatever"), ignore: true, should_panic: ShouldPanic::No, + allow_fail: false, }, testfn: DynTestFn(Box::new(move |()| f())), }; @@ -1742,6 +1776,7 @@ mod tests { name: StaticTestName("whatever"), ignore: false, should_panic: ShouldPanic::Yes, + allow_fail: false, }, testfn: DynTestFn(Box::new(move |()| f())), }; @@ -1761,6 +1796,7 @@ mod tests { name: StaticTestName("whatever"), ignore: false, should_panic: ShouldPanic::YesWithMessage("error message"), + allow_fail: false, }, testfn: DynTestFn(Box::new(move |()| f())), }; @@ -1782,6 +1818,7 @@ mod tests { name: StaticTestName("whatever"), ignore: false, should_panic: ShouldPanic::YesWithMessage(expected), + allow_fail: false, }, testfn: DynTestFn(Box::new(move |()| f())), }; @@ -1799,6 +1836,7 @@ mod tests { name: StaticTestName("whatever"), ignore: false, should_panic: ShouldPanic::Yes, + allow_fail: false, }, testfn: DynTestFn(Box::new(move |()| f())), }; @@ -1832,6 +1870,7 @@ mod tests { name: StaticTestName("1"), ignore: true, should_panic: ShouldPanic::No, + allow_fail: false, }, testfn: DynTestFn(Box::new(move |()| {})), }, @@ -1840,6 +1879,7 @@ mod tests { name: StaticTestName("2"), ignore: false, should_panic: ShouldPanic::No, + allow_fail: false, }, testfn: DynTestFn(Box::new(move |()| {})), }]; @@ -1863,6 +1903,7 @@ mod tests { name: StaticTestName(name), ignore: false, should_panic: ShouldPanic::No, + allow_fail: false, }, testfn: DynTestFn(Box::new(move |()| {})) }) @@ -1944,6 +1985,7 @@ mod tests { name: DynTestName((*name).clone()), ignore: false, should_panic: ShouldPanic::No, + allow_fail: false, }, testfn: DynTestFn(Box::new(move |()| testfn())), }; diff --git a/src/llvm b/src/llvm index d8c9dfcc4f5..8e1b4fedfa4 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit d8c9dfcc4f5289c09bab5736966feee2a0e69594 +Subproject commit 8e1b4fedfa4542e65f82fe124bd6433f3bd0aec5 diff --git a/src/rustllvm/.editorconfig b/src/rustllvm/.editorconfig new file mode 100644 index 00000000000..865cd45f708 --- /dev/null +++ b/src/rustllvm/.editorconfig @@ -0,0 +1,6 @@ +[*.{h,cpp}] +end_of_line = lf +insert_final_newline = true +charset = utf-8 +indent_style = space +indent_size = 2 diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index fdbe4e5f7ad..7fb1eafb30d 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -10,11 +10,14 @@ #include +#include + #include "rustllvm.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/IR/AutoUpgrade.h" +#include "llvm/IR/AssemblyAnnotationWriter.h" #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Host.h" @@ -503,8 +506,129 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR, return LLVMRustResult::Success; } + +// Callback to demangle function name +// Parameters: +// * name to be demangled +// * name len +// * output buffer +// * output buffer len +// Returns len of demangled string, or 0 if demangle failed. +typedef size_t (*DemangleFn)(const char*, size_t, char*, size_t); + + +namespace { + +class RustAssemblyAnnotationWriter : public AssemblyAnnotationWriter { + DemangleFn Demangle; + std::vector Buf; + +public: + RustAssemblyAnnotationWriter(DemangleFn Demangle) : Demangle(Demangle) {} + + // Return empty string if demangle failed + // or if name does not need to be demangled + StringRef CallDemangle(StringRef name) { + if (!Demangle) { + return StringRef(); + } + + if (Buf.size() < name.size() * 2) { + // Semangled name usually shorter than mangled, + // but allocate twice as much memory just in case + Buf.resize(name.size() * 2); + } + + auto R = Demangle(name.data(), name.size(), Buf.data(), Buf.size()); + if (!R) { + // Demangle failed. + return StringRef(); + } + + auto Demangled = StringRef(Buf.data(), R); + if (Demangled == name) { + // Do not print anything if demangled name is equal to mangled. + return StringRef(); + } + + return Demangled; + } + + void emitFunctionAnnot(const Function *F, + formatted_raw_ostream &OS) override { + StringRef Demangled = CallDemangle(F->getName()); + if (Demangled.empty()) { + return; + } + + OS << "; " << Demangled << "\n"; + } + + void emitInstructionAnnot(const Instruction *I, + formatted_raw_ostream &OS) override { + const char *Name; + const Value *Value; + if (const CallInst *CI = dyn_cast(I)) { + Name = "call"; + Value = CI->getCalledValue(); + } else if (const InvokeInst* II = dyn_cast(I)) { + Name = "invoke"; + Value = II->getCalledValue(); + } else { + // Could demangle more operations, e. g. + // `store %place, @function`. + return; + } + + if (!Value->hasName()) { + return; + } + + StringRef Demangled = CallDemangle(Value->getName()); + if (Demangled.empty()) { + return; + } + + OS << "; " << Name << " " << Demangled << "\n"; + } +}; + +class RustPrintModulePass : public ModulePass { + raw_ostream* OS; + DemangleFn Demangle; +public: + static char ID; + RustPrintModulePass() : ModulePass(ID), OS(nullptr), Demangle(nullptr) {} + RustPrintModulePass(raw_ostream &OS, DemangleFn Demangle) + : ModulePass(ID), OS(&OS), Demangle(Demangle) {} + + bool runOnModule(Module &M) override { + RustAssemblyAnnotationWriter AW(Demangle); + + M.print(*OS, &AW, false); + + return false; + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + } + + static StringRef name() { return "RustPrintModulePass"; } +}; + +} // namespace + +namespace llvm { + void initializeRustPrintModulePassPass(PassRegistry&); +} + +char RustPrintModulePass::ID = 0; +INITIALIZE_PASS(RustPrintModulePass, "print-rust-module", + "Print rust module to stderr", false, false) + extern "C" void LLVMRustPrintModule(LLVMPassManagerRef PMR, LLVMModuleRef M, - const char *Path) { + const char *Path, DemangleFn Demangle) { llvm::legacy::PassManager *PM = unwrap(PMR); std::string ErrorInfo; @@ -515,7 +639,7 @@ extern "C" void LLVMRustPrintModule(LLVMPassManagerRef PMR, LLVMModuleRef M, formatted_raw_ostream FOS(OS); - PM->add(createPrintModulePass(FOS)); + PM->add(new RustPrintModulePass(FOS, Demangle)); PM->run(*unwrap(M)); } diff --git a/src/rustllvm/llvm-rebuild-trigger b/src/rustllvm/llvm-rebuild-trigger index e547659d19a..37ba3264452 100644 --- a/src/rustllvm/llvm-rebuild-trigger +++ b/src/rustllvm/llvm-rebuild-trigger @@ -1,4 +1,4 @@ # If this file is modified, then llvm will be (optionally) cleaned and then rebuilt. # The actual contents of this file do not matter, but to trigger a change on the # build bots then the contents should be changed so git updates the mtime. -2017-06-19 +2017-06-27 diff --git a/src/test/compile-fail/E0604.rs b/src/test/compile-fail/E0604.rs new file mode 100644 index 00000000000..c5bf3a77b6c --- /dev/null +++ b/src/test/compile-fail/E0604.rs @@ -0,0 +1,13 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + 1u32 as char; //~ ERROR E0604 +} diff --git a/src/test/compile-fail/E0605.rs b/src/test/compile-fail/E0605.rs new file mode 100644 index 00000000000..add3fd8fd8a --- /dev/null +++ b/src/test/compile-fail/E0605.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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let x = 0u8; + x as Vec; //~ ERROR E0605 + //~| NOTE an `as` expression can only be used to convert between primitive types + + let v = 0 as *const u8; + v as &u8; //~ ERROR E0605 + //~| NOTE an `as` expression can only be used to convert between primitive types +} diff --git a/src/test/compile-fail/E0606.rs b/src/test/compile-fail/E0606.rs new file mode 100644 index 00000000000..55071736bfe --- /dev/null +++ b/src/test/compile-fail/E0606.rs @@ -0,0 +1,13 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + &0u8 as u8; //~ ERROR E0606 +} diff --git a/src/test/compile-fail/E0607.rs b/src/test/compile-fail/E0607.rs new file mode 100644 index 00000000000..fa761f2c178 --- /dev/null +++ b/src/test/compile-fail/E0607.rs @@ -0,0 +1,14 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let v = 0 as *const u8; + v as *const [u8]; //~ ERROR E0607 +} diff --git a/src/test/compile-fail/E0619.rs b/src/test/compile-fail/E0619.rs new file mode 100644 index 00000000000..a5a5ff7218d --- /dev/null +++ b/src/test/compile-fail/E0619.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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let x; + + match x { + (..) => {} //~ ERROR E0619 + _ => {} + } +} + diff --git a/src/test/compile-fail/E0620.rs b/src/test/compile-fail/E0620.rs new file mode 100644 index 00000000000..5e945dfa5c8 --- /dev/null +++ b/src/test/compile-fail/E0620.rs @@ -0,0 +1,13 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let _foo = &[1_usize, 2] as [usize]; //~ ERROR E0620 +} diff --git a/src/test/compile-fail/E0621-does-not-trigger-for-closures.rs b/src/test/compile-fail/E0621-does-not-trigger-for-closures.rs new file mode 100644 index 00000000000..980461bedae --- /dev/null +++ b/src/test/compile-fail/E0621-does-not-trigger-for-closures.rs @@ -0,0 +1,28 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we give the generic E0495 when one of the free regions is +// bound in a closure (rather than suggesting a change to the signature +// of the closure, which is not specified in `foo` but rather in `invoke`). + +// FIXME - This might be better as a UI test, but the finer details +// of the error seem to vary on different machines. +fn invoke<'a, F>(x: &'a i32, f: F) -> &'a i32 +where F: FnOnce(&'a i32, &i32) -> &'a i32 +{ + let y = 22; + f(x, &y) +} + +fn foo<'a>(x: &'a i32) { + invoke(&x, |a, b| if a > b { a } else { b }); //~ ERROR E0495 +} + +fn main() {} diff --git a/src/test/compile-fail/invalid-intrinsic.rs b/src/test/compile-fail/E0622.rs similarity index 86% rename from src/test/compile-fail/invalid-intrinsic.rs rename to src/test/compile-fail/E0622.rs index 2aa2546cb9f..f2bde5b0364 100644 --- a/src/test/compile-fail/invalid-intrinsic.rs +++ b/src/test/compile-fail/E0622.rs @@ -11,6 +11,6 @@ #![feature(intrinsics)] extern "rust-intrinsic" { pub static breakpoint : unsafe extern "rust-intrinsic" fn(); - //~^ ERROR intrinsic has wrong type + //~^ ERROR intrinsic must be a function [E0622] } -fn main() { unsafe { breakpoint(); } } \ No newline at end of file +fn main() { unsafe { breakpoint(); } } diff --git a/src/test/compile-fail/associated-types-path-2.rs b/src/test/compile-fail/associated-types-path-2.rs index cdb7dff692c..d62f6b0f1a3 100644 --- a/src/test/compile-fail/associated-types-path-2.rs +++ b/src/test/compile-fail/associated-types-path-2.rs @@ -38,11 +38,13 @@ pub fn f1_int_uint() { pub fn f1_uint_uint() { f1(2u32, 4u32); //~^ ERROR `u32: Foo` is not satisfied + //~| ERROR `u32: Foo` is not satisfied } pub fn f1_uint_int() { f1(2u32, 4i32); //~^ ERROR `u32: Foo` is not satisfied + //~| ERROR `u32: Foo` is not satisfied } pub fn f2_int() { diff --git a/src/test/compile-fail/cast-from-nil.rs b/src/test/compile-fail/cast-from-nil.rs index 4c6dcaccc9a..ab22d352480 100644 --- a/src/test/compile-fail/cast-from-nil.rs +++ b/src/test/compile-fail/cast-from-nil.rs @@ -8,5 +8,5 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern: non-scalar cast: `()` as `u32` +// error-pattern: non-primitive cast: `()` as `u32` fn main() { let u = (assert!(true) as u32); } diff --git a/src/test/compile-fail/cast-to-bare-fn.rs b/src/test/compile-fail/cast-to-bare-fn.rs index 7cc5c727bc7..d5a998c6e4b 100644 --- a/src/test/compile-fail/cast-to-bare-fn.rs +++ b/src/test/compile-fail/cast-to-bare-fn.rs @@ -13,8 +13,8 @@ fn foo(_x: isize) { } fn main() { let v: u64 = 5; let x = foo as extern "C" fn() -> isize; - //~^ ERROR non-scalar cast + //~^ ERROR non-primitive cast let y = v as extern "Rust" fn(isize) -> (isize, isize); - //~^ ERROR non-scalar cast + //~^ ERROR non-primitive cast y(x()); } diff --git a/src/test/compile-fail/cast-to-nil.rs b/src/test/compile-fail/cast-to-nil.rs index e5fd5bb33eb..27d9e8a42b1 100644 --- a/src/test/compile-fail/cast-to-nil.rs +++ b/src/test/compile-fail/cast-to-nil.rs @@ -8,5 +8,5 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern: non-scalar cast: `u32` as `()` +// error-pattern: non-primitive cast: `u32` as `()` fn main() { let u = 0u32 as (); } diff --git a/src/test/compile-fail/closure-no-fn-3.rs b/src/test/compile-fail/closure-no-fn-3.rs index 85dbc899208..6584c16c9de 100644 --- a/src/test/compile-fail/closure-no-fn-3.rs +++ b/src/test/compile-fail/closure-no-fn-3.rs @@ -14,5 +14,5 @@ fn main() { let b = 0u8; let baz: fn() -> u8 = (|| { b }) as fn() -> u8; - //~^ ERROR non-scalar cast + //~^ ERROR non-primitive cast } diff --git a/src/test/compile-fail/coerce-to-bang-cast.rs b/src/test/compile-fail/coerce-to-bang-cast.rs index 57d2192e635..0479f5cce65 100644 --- a/src/test/compile-fail/coerce-to-bang-cast.rs +++ b/src/test/compile-fail/coerce-to-bang-cast.rs @@ -17,7 +17,7 @@ fn cast_a() { } fn cast_b() { - let y = 22 as !; //~ ERROR non-scalar cast + let y = 22 as !; //~ ERROR non-primitive cast } fn main() { } diff --git a/src/test/compile-fail/dollar-crate-is-keyword-2.rs b/src/test/compile-fail/dollar-crate-is-keyword-2.rs new file mode 100644 index 00000000000..e221fc6e9e0 --- /dev/null +++ b/src/test/compile-fail/dollar-crate-is-keyword-2.rs @@ -0,0 +1,23 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +mod a {} + +macro_rules! m { + () => { + use a::$crate; //~ ERROR unresolved import `a::$crate` + use a::$crate::b; //~ ERROR unresolved import `a::$crate::b` + type A = a::$crate; //~ ERROR cannot find type `$crate` in module `a` + } +} + +m!(); + +fn main() {} diff --git a/src/test/compile-fail/dollar-crate-is-keyword.rs b/src/test/compile-fail/dollar-crate-is-keyword.rs new file mode 100644 index 00000000000..70597a230a8 --- /dev/null +++ b/src/test/compile-fail/dollar-crate-is-keyword.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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +macro_rules! m { + () => { + struct $crate {} //~ ERROR expected identifier, found reserved identifier `$crate` + + use $crate; // OK + //~^ WARN `$crate` may not be imported + use $crate as $crate; //~ ERROR expected identifier, found reserved identifier `$crate` + //~^ WARN `$crate` may not be imported + } +} + +m!(); + +fn main() {} diff --git a/src/test/compile-fail/dst-bad-assign-3.rs b/src/test/compile-fail/dst-bad-assign-3.rs new file mode 100644 index 00000000000..1c3bad5ba56 --- /dev/null +++ b/src/test/compile-fail/dst-bad-assign-3.rs @@ -0,0 +1,50 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Forbid assignment into a dynamically sized type. + +#![feature(unsized_tuple_coercion)] + +type Fat = (isize, &'static str, T); +//~^ WARNING trait bounds are not (yet) enforced + +#[derive(PartialEq,Eq)] +struct Bar; + +#[derive(PartialEq,Eq)] +struct Bar1 { + f: isize +} + +trait ToBar { + fn to_bar(&self) -> Bar; + fn to_val(&self) -> isize; +} + +impl ToBar for Bar1 { + fn to_bar(&self) -> Bar { + Bar + } + fn to_val(&self) -> isize { + self.f + } +} + +pub fn main() { + // Assignment. + let f5: &mut Fat = &mut (5, "some str", Bar1 {f :42}); + let z: Box = Box::new(Bar1 {f: 36}); + f5.2 = Bar1 {f: 36}; + //~^ ERROR mismatched types + //~| expected type `ToBar` + //~| found type `Bar1` + //~| expected trait ToBar, found struct `Bar1` + //~| ERROR `ToBar: std::marker::Sized` is not satisfied +} diff --git a/src/test/compile-fail/dst-bad-coerce1.rs b/src/test/compile-fail/dst-bad-coerce1.rs index 9a3ea54a3a4..b0de84a5300 100644 --- a/src/test/compile-fail/dst-bad-coerce1.rs +++ b/src/test/compile-fail/dst-bad-coerce1.rs @@ -10,6 +10,8 @@ // Attempt to change the type as well as unsizing. +#![feature(unsized_tuple_coercion)] + struct Fat { ptr: T } @@ -29,4 +31,16 @@ pub fn main() { let f2: &Fat = &f1; let f3: &Fat = f2; //~^ ERROR `Foo: Bar` is not satisfied + + // Tuple with a vec of isize. + let f1 = ([1, 2, 3],); + let f2: &([isize; 3],) = &f1; + let f3: &([usize],) = f2; + //~^ ERROR mismatched types + + // Tuple with a trait. + let f1 = (Foo,); + let f2: &(Foo,) = &f1; + let f3: &(Bar,) = f2; + //~^ ERROR `Foo: Bar` is not satisfied } diff --git a/src/test/compile-fail/dst-bad-coerce2.rs b/src/test/compile-fail/dst-bad-coerce2.rs index 160197368d6..9e92f649b2d 100644 --- a/src/test/compile-fail/dst-bad-coerce2.rs +++ b/src/test/compile-fail/dst-bad-coerce2.rs @@ -28,4 +28,14 @@ pub fn main() { let f1 = Fat { ptr: Foo }; let f2: &Fat = &f1; let f3: &mut Fat = f2; //~ ERROR mismatched types + + // Tuple with a vec of ints. + let f1 = ([1, 2, 3],); + let f2: &([isize; 3],) = &f1; + let f3: &mut ([isize],) = f2; //~ ERROR mismatched types + + // Tuple with a trait. + let f1 = (Foo,); + let f2: &(Foo,) = &f1; + let f3: &mut (Bar,) = f2; //~ ERROR mismatched types } diff --git a/src/test/compile-fail/dst-bad-coerce3.rs b/src/test/compile-fail/dst-bad-coerce3.rs index 7bad3bd69d3..35a147c15bb 100644 --- a/src/test/compile-fail/dst-bad-coerce3.rs +++ b/src/test/compile-fail/dst-bad-coerce3.rs @@ -10,6 +10,8 @@ // Attempt to extend the lifetime as well as unsizing. +#![feature(unsized_tuple_coercion)] + struct Fat { ptr: T } @@ -28,6 +30,16 @@ fn baz<'a>() { let f1 = Fat { ptr: Foo }; let f2: &Fat = &f1; //~ ERROR `f1` does not live long enough let f3: &'a Fat = f2; + + // Tuple with a vec of ints. + let f1 = ([1, 2, 3],); + let f2: &([isize; 3],) = &f1; //~ ERROR `f1` does not live long enough + let f3: &'a ([isize],) = f2; + + // Tuple with a trait. + let f1 = (Foo,); + let f2: &(Foo,) = &f1; //~ ERROR `f1` does not live long enough + let f3: &'a (Bar,) = f2; } pub fn main() { diff --git a/src/test/compile-fail/dst-bad-coerce4.rs b/src/test/compile-fail/dst-bad-coerce4.rs index 9d4d56cf791..874b7588ff9 100644 --- a/src/test/compile-fail/dst-bad-coerce4.rs +++ b/src/test/compile-fail/dst-bad-coerce4.rs @@ -10,6 +10,8 @@ // Attempt to coerce from unsized to sized. +#![feature(unsized_tuple_coercion)] + struct Fat { ptr: T } @@ -22,4 +24,12 @@ pub fn main() { //~| expected type `&Fat<[isize; 3]>` //~| found type `&Fat<[isize]>` //~| expected array of 3 elements, found slice + + // Tuple with a vec of isizes. + let f1: &([isize],) = &([1, 2, 3],); + let f2: &([isize; 3],) = f1; + //~^ ERROR mismatched types + //~| expected type `&([isize; 3],)` + //~| found type `&([isize],)` + //~| expected array of 3 elements, found slice } diff --git a/src/test/compile-fail/dst-bad-deep-2.rs b/src/test/compile-fail/dst-bad-deep-2.rs new file mode 100644 index 00000000000..0c812b1d815 --- /dev/null +++ b/src/test/compile-fail/dst-bad-deep-2.rs @@ -0,0 +1,23 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Try to initialise a DST struct where the lost information is deeply nested. +// This is an error because it requires an unsized rvalue. This is a problem +// because it would require stack allocation of an unsized temporary (*g in the +// test). + +#![feature(unsized_tuple_coercion)] + +pub fn main() { + let f: ([isize; 3],) = ([5, 6, 7],); + let g: &([isize],) = &f; + let h: &(([isize],),) = &(*g,); + //~^ ERROR `[isize]: std::marker::Sized` is not satisfied +} diff --git a/src/test/compile-fail/fat-ptr-cast.rs b/src/test/compile-fail/fat-ptr-cast.rs index c62987a5b90..bc2dc1cc5d4 100644 --- a/src/test/compile-fail/fat-ptr-cast.rs +++ b/src/test/compile-fail/fat-ptr-cast.rs @@ -22,7 +22,7 @@ fn main() { a as isize; //~ ERROR casting a as i16; //~ ERROR casting `&[i32]` as `i16` is invalid a as u32; //~ ERROR casting `&[i32]` as `u32` is invalid - b as usize; //~ ERROR non-scalar cast + b as usize; //~ ERROR non-primitive cast p as usize; //~^ ERROR casting //~^^ HELP cast through a thin pointer diff --git a/src/test/compile-fail/feature-gate-allow_fail.rs b/src/test/compile-fail/feature-gate-allow_fail.rs new file mode 100644 index 00000000000..11247402809 --- /dev/null +++ b/src/test/compile-fail/feature-gate-allow_fail.rs @@ -0,0 +1,17 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// check that #[allow_fail] is feature-gated + +#[allow_fail] //~ ERROR allow_fail attribute is currently unstable +fn ok_to_fail() { + assert!(false); +} + diff --git a/src/test/compile-fail/feature-gate-unsized_tuple_coercion.rs b/src/test/compile-fail/feature-gate-unsized_tuple_coercion.rs new file mode 100644 index 00000000000..4ddde011263 --- /dev/null +++ b/src/test/compile-fail/feature-gate-unsized_tuple_coercion.rs @@ -0,0 +1,14 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let _ : &(Send,) = &((),); + //~^ ERROR Unsized tuple coercion is not stable enough +} diff --git a/src/test/compile-fail/issue-10991.rs b/src/test/compile-fail/issue-10991.rs index 25060b94dcf..2d00f339f33 100644 --- a/src/test/compile-fail/issue-10991.rs +++ b/src/test/compile-fail/issue-10991.rs @@ -10,5 +10,5 @@ fn main() { let nil = (); - let _t = nil as usize; //~ ERROR: non-scalar cast: `()` as `usize` + let _t = nil as usize; //~ ERROR: non-primitive cast: `()` as `usize` } diff --git a/src/test/compile-fail/issue-22289.rs b/src/test/compile-fail/issue-22289.rs index bcbc414d353..c23fc4f3344 100644 --- a/src/test/compile-fail/issue-22289.rs +++ b/src/test/compile-fail/issue-22289.rs @@ -9,5 +9,5 @@ // except according to those terms. fn main() { - 0 as &std::any::Any; //~ ERROR non-scalar cast + 0 as &std::any::Any; //~ ERROR non-primitive cast } diff --git a/src/test/compile-fail/issue-22312.rs b/src/test/compile-fail/issue-22312.rs index 4d6e6eded21..2128c420630 100644 --- a/src/test/compile-fail/issue-22312.rs +++ b/src/test/compile-fail/issue-22312.rs @@ -19,7 +19,7 @@ pub trait Array2D: Index { } let i = y * self.columns() + x; let indexer = &(*self as &Index>::Output>); - //~^ERROR non-scalar cast + //~^ERROR non-primitive cast Some(indexer.index(i)) } } diff --git a/src/test/compile-fail/issue-23046.rs b/src/test/compile-fail/issue-23046.rs index 28109747b75..129f7c8b1ea 100644 --- a/src/test/compile-fail/issue-23046.rs +++ b/src/test/compile-fail/issue-23046.rs @@ -24,7 +24,7 @@ pub fn let_<'var, VAR, F: for<'v: 'var> Fn(Expr<'v, VAR>) -> Expr<'v, VAR>> } fn main() { - let ex = |x| { - let_(add(x,x), |y| { //~ ERROR type annotations needed + let ex = |x| { //~ ERROR type annotations needed + let_(add(x,x), |y| { let_(add(x, x), |x|x)})}; } diff --git a/src/test/compile-fail/issue-2995.rs b/src/test/compile-fail/issue-2995.rs index 8fbf97411cc..d735e184d5c 100644 --- a/src/test/compile-fail/issue-2995.rs +++ b/src/test/compile-fail/issue-2995.rs @@ -9,7 +9,7 @@ // except according to those terms. fn bad (p: *const isize) { - let _q: &isize = p as &isize; //~ ERROR non-scalar cast + let _q: &isize = p as &isize; //~ ERROR non-primitive cast } fn main() { } diff --git a/src/test/compile-fail/issue-38954.rs b/src/test/compile-fail/issue-38954.rs index 65b17a3db0b..896728b6da0 100644 --- a/src/test/compile-fail/issue-38954.rs +++ b/src/test/compile-fail/issue-38954.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(rustc_attrs)] - fn _test(ref _p: str) {} +//~^ ERROR the trait bound `str: std::marker::Sized` is not satisfied [E0277] -#[rustc_error] -fn main() { } //~ ERROR compilation successful +fn main() { } diff --git a/src/test/compile-fail/issue-42312.rs b/src/test/compile-fail/issue-42312.rs new file mode 100644 index 00000000000..06573b42b59 --- /dev/null +++ b/src/test/compile-fail/issue-42312.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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::ops::Deref; + +pub trait Foo { + fn baz(_: Self::Target) where Self: Deref {} + //~^ ERROR `::Target: std::marker::Sized` is not satisfied +} + +pub fn f(_: ToString) {} +//~^ ERROR the trait bound `std::string::ToString + 'static: std::marker::Sized` is not satisfied + +fn main() { } diff --git a/src/test/compile-fail/issue-42880.rs b/src/test/compile-fail/issue-42880.rs new file mode 100644 index 00000000000..ebb1ec425d1 --- /dev/null +++ b/src/test/compile-fail/issue-42880.rs @@ -0,0 +1,18 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +type Value = String; + +fn main() { + let f = |&Value::String(_)| (); //~ ERROR no associated item named + + let vec: Vec = Vec::new(); + vec.last().map(f); +} diff --git a/src/test/compile-fail/nonscalar-cast.rs b/src/test/compile-fail/nonscalar-cast.rs index d6f274da967..0abbc05eef0 100644 --- a/src/test/compile-fail/nonscalar-cast.rs +++ b/src/test/compile-fail/nonscalar-cast.rs @@ -8,13 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:non-scalar cast - #[derive(Debug)] struct foo { x: isize } fn main() { - println!("{}", foo{ x: 1 } as isize); + println!("{}", foo{ x: 1 } as isize); //~ non-primitive cast: `foo` as `isize` [E0605] } diff --git a/src/test/compile-fail/on-unimplemented/multiple-impls.rs b/src/test/compile-fail/on-unimplemented/multiple-impls.rs index 0df8c41ffe1..15375936b89 100644 --- a/src/test/compile-fail/on-unimplemented/multiple-impls.rs +++ b/src/test/compile-fail/on-unimplemented/multiple-impls.rs @@ -44,12 +44,18 @@ fn main() { //~^ ERROR E0277 //~| NOTE trait message //~| NOTE required by + //~| ERROR E0277 + //~| NOTE trait message Index::index(&[] as &[i32], Foo(2u32)); //~^ ERROR E0277 //~| NOTE on impl for Foo //~| NOTE required by + //~| ERROR E0277 + //~| NOTE on impl for Foo Index::index(&[] as &[i32], Bar(2u32)); //~^ ERROR E0277 //~| NOTE on impl for Bar //~| NOTE required by + //~| ERROR E0277 + //~| NOTE on impl for Bar } diff --git a/src/test/compile-fail/on-unimplemented/on-impl.rs b/src/test/compile-fail/on-unimplemented/on-impl.rs index 79021cd03cc..66d612baab4 100644 --- a/src/test/compile-fail/on-unimplemented/on-impl.rs +++ b/src/test/compile-fail/on-unimplemented/on-impl.rs @@ -33,4 +33,6 @@ fn main() { //~^ ERROR E0277 //~| NOTE a usize is required //~| NOTE required by + //~| ERROR E0277 + //~| NOTE a usize is required } diff --git a/src/test/compile-fail/patkind-litrange-no-expr.rs b/src/test/compile-fail/patkind-litrange-no-expr.rs new file mode 100644 index 00000000000..afb2cbb7db3 --- /dev/null +++ b/src/test/compile-fail/patkind-litrange-no-expr.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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +macro_rules! enum_number { + ($name:ident { $($variant:ident = $value:expr, )* }) => { + enum $name { + $($variant = $value,)* + } + + fn foo(value: i32) -> Option<$name> { + match value { + $( $value => Some($name::$variant), )* // PatKind::Lit + $( $value ... 42 => Some($name::$variant), )* // PatKind::Range + _ => None + } + } + } +} + +enum_number!(Change { + Pos = 1, + Neg = -1, + Arith = 1 + 1, //~ ERROR arbitrary expressions aren't allowed in patterns + //~^ ERROR arbitrary expressions aren't allowed in patterns + //~^^ ERROR only char and numeric types are allowed in range patterns +}); + +fn main() {} + diff --git a/src/test/compile-fail/tag-variant-cast-non-nullary.rs b/src/test/compile-fail/tag-variant-cast-non-nullary.rs index b0106329126..220537633ea 100644 --- a/src/test/compile-fail/tag-variant-cast-non-nullary.rs +++ b/src/test/compile-fail/tag-variant-cast-non-nullary.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//error-pattern: non-scalar cast - enum non_nullary { nullary, other(isize), @@ -17,5 +15,5 @@ enum non_nullary { fn main() { let v = non_nullary::nullary; - let val = v as isize; + let val = v as isize; //~ ERROR non-primitive cast: `non_nullary` as `isize` [E0605] } diff --git a/src/test/compile-fail/uninhabited-enum-cast.rs b/src/test/compile-fail/uninhabited-enum-cast.rs index b4df5fb1e2a..2a5d25e6b98 100644 --- a/src/test/compile-fail/uninhabited-enum-cast.rs +++ b/src/test/compile-fail/uninhabited-enum-cast.rs @@ -11,7 +11,7 @@ enum E {} fn f(e: E) { - println!("{}", (e as isize).to_string()); //~ ERROR non-scalar cast + println!("{}", (e as isize).to_string()); //~ ERROR non-primitive cast } fn main() {} diff --git a/src/test/compile-fail/unsized3.rs b/src/test/compile-fail/unsized3.rs index 9b6ccf22c8d..e96e0ea3aec 100644 --- a/src/test/compile-fail/unsized3.rs +++ b/src/test/compile-fail/unsized3.rs @@ -54,6 +54,7 @@ fn f9(x1: Box>) { fn f10(x1: Box>) { f5(&(32, *x1)); //~^ ERROR `X: std::marker::Sized` is not satisfied + //~| ERROR `X: std::marker::Sized` is not satisfied } pub fn main() { diff --git a/src/test/compile-fail/use-self-type.rs b/src/test/compile-fail/use-self-type.rs new file mode 100644 index 00000000000..6b5286bf0a7 --- /dev/null +++ b/src/test/compile-fail/use-self-type.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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct S; + +impl S { + fn f() {} + fn g() { + use Self::f; //~ ERROR unresolved import + pub(in Self::f) struct Z; //~ ERROR Use of undeclared type or module `Self` + } +} + +fn main() {} diff --git a/src/test/compile-fail/variance-trait-bounds.rs b/src/test/compile-fail/variance-trait-bounds.rs index 58fb785c48c..9b88e38e085 100644 --- a/src/test/compile-fail/variance-trait-bounds.rs +++ b/src/test/compile-fail/variance-trait-bounds.rs @@ -14,13 +14,11 @@ // Check that bounds on type parameters (other than `Self`) do not // influence variance. -#[rustc_variance] -trait Getter { //~ ERROR [o, o] +trait Getter { fn get(&self) -> T; } -#[rustc_variance] -trait Setter { //~ ERROR [o, o] +trait Setter { fn get(&self, T); } @@ -34,20 +32,6 @@ enum TestEnum> { //~ ERROR [*, +] Foo(T) } -#[rustc_variance] -trait TestTrait> { //~ ERROR [o, o, o] - fn getter(&self, u: U) -> T; -} - -#[rustc_variance] -trait TestTrait2 : Getter { //~ ERROR [o, o] -} - -#[rustc_variance] -trait TestTrait3 { //~ ERROR [o, o] - fn getter>(&self); -} - #[rustc_variance] struct TestContraStruct> { //~ ERROR [*, +] t: T diff --git a/src/test/compile-fail/variance-types-bounds.rs b/src/test/compile-fail/variance-types-bounds.rs index 2df94cc907a..5075dd2ceed 100644 --- a/src/test/compile-fail/variance-types-bounds.rs +++ b/src/test/compile-fail/variance-types-bounds.rs @@ -36,37 +36,14 @@ struct TestIndirect2 { //~ ERROR [o, o] m: TestMut } -#[rustc_variance] -trait Getter { //~ ERROR [o, o] +trait Getter { fn get(&self) -> A; } -#[rustc_variance] -trait Setter { //~ ERROR [o, o] +trait Setter { fn set(&mut self, a: A); } -#[rustc_variance] -trait GetterSetter { //~ ERROR [o, o] - fn get(&self) -> A; - fn set(&mut self, a: A); -} - -#[rustc_variance] -trait GetterInTypeBound { //~ ERROR [o, o] - // Here, the use of `A` in the method bound *does* affect - // variance. Think of it as if the method requested a dictionary - // for `T:Getter`. Since this dictionary is an input, it is - // contravariant, and the Getter is covariant w/r/t A, yielding an - // overall contravariant result. - fn do_it>(&self); -} - -#[rustc_variance] -trait SetterInTypeBound { //~ ERROR [o, o] - fn do_it>(&self); -} - #[rustc_variance] struct TestObject { //~ ERROR [o, o] n: Box+Send>, diff --git a/src/test/parse-fail/macro-keyword.rs b/src/test/parse-fail/macro-keyword.rs index 6a7ccff1554..c7dcaf4137e 100644 --- a/src/test/parse-fail/macro-keyword.rs +++ b/src/test/parse-fail/macro-keyword.rs @@ -10,7 +10,7 @@ // compile-flags: -Z parse-only -fn macro() { //~ ERROR `macro` is a reserved keyword +fn macro() { //~ ERROR expected identifier, found reserved keyword `macro` } pub fn main() { diff --git a/src/test/run-make/llvm-phase/test.rs b/src/test/run-make/llvm-phase/test.rs index ca58e007852..a75dc7e57a9 100644 --- a/src/test/run-make/llvm-phase/test.rs +++ b/src/test/run-make/llvm-phase/test.rs @@ -85,6 +85,6 @@ fn main() { let (result, _) = rustc_driver::run_compiler( &args, &mut JitCalls, Some(box JitLoader), None); if let Err(n) = result { - panic!("Error {}", n); + panic!("Error {:?}", n); } } diff --git a/src/test/run-pass-valgrind/dst-dtor-3.rs b/src/test/run-pass-valgrind/dst-dtor-3.rs new file mode 100644 index 00000000000..1ae66a28a84 --- /dev/null +++ b/src/test/run-pass-valgrind/dst-dtor-3.rs @@ -0,0 +1,34 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// no-prefer-dynamic + +#![feature(unsized_tuple_coercion)] + +static mut DROP_RAN: bool = false; + +struct Foo; +impl Drop for Foo { + fn drop(&mut self) { + unsafe { DROP_RAN = true; } + } +} + +trait Trait { fn dummy(&self) { } } +impl Trait for Foo {} + +pub fn main() { + { + let _x: Box<(i32, Trait)> = Box::<(i32, Foo)>::new((42, Foo)); + } + unsafe { + assert!(DROP_RAN); + } +} diff --git a/src/test/run-pass-valgrind/dst-dtor-4.rs b/src/test/run-pass-valgrind/dst-dtor-4.rs new file mode 100644 index 00000000000..e416f25bc03 --- /dev/null +++ b/src/test/run-pass-valgrind/dst-dtor-4.rs @@ -0,0 +1,31 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// no-prefer-dynamic + +#![feature(unsized_tuple_coercion)] + +static mut DROP_RAN: isize = 0; + +struct Foo; +impl Drop for Foo { + fn drop(&mut self) { + unsafe { DROP_RAN += 1; } + } +} + +pub fn main() { + { + let _x: Box<(i32, [Foo])> = Box::<(i32, [Foo; 3])>::new((42, [Foo, Foo, Foo])); + } + unsafe { + assert_eq!(DROP_RAN, 3); + } +} diff --git a/src/test/run-pass/allocator-alloc-one.rs b/src/test/run-pass/allocator-alloc-one.rs new file mode 100644 index 00000000000..7cc547dcc04 --- /dev/null +++ b/src/test/run-pass/allocator-alloc-one.rs @@ -0,0 +1,27 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(alloc, allocator_api, heap_api, unique)] + +extern crate alloc; + +use alloc::heap::HeapAlloc; +use alloc::allocator::Alloc; + +fn main() { + unsafe { + let ptr = HeapAlloc.alloc_one::().unwrap_or_else(|e| { + HeapAlloc.oom(e) + }); + *ptr.as_ptr() = 4; + assert_eq!(*ptr.as_ptr(), 4); + HeapAlloc.dealloc_one(ptr); + } +} diff --git a/src/test/run-pass/associated-types-sugar-path.rs b/src/test/run-pass/associated-types-sugar-path.rs index 587fb3f80d6..d8d42f2cba2 100644 --- a/src/test/run-pass/associated-types-sugar-path.rs +++ b/src/test/run-pass/associated-types-sugar-path.rs @@ -15,8 +15,6 @@ use std::ops::Deref; pub trait Foo { type A; fn boo(&self) -> Self::A; - - fn baz(_: Self::Target) where Self: Deref {} } impl Foo for isize { diff --git a/src/test/run-pass/deriving-hash.rs b/src/test/run-pass/deriving-hash.rs index 91bfc2f9201..18b2fbe015b 100644 --- a/src/test/run-pass/deriving-hash.rs +++ b/src/test/run-pass/deriving-hash.rs @@ -45,8 +45,8 @@ impl<'a> Hasher for FakeHasher<'a> { } } -fn fake_hash(v: &mut Vec, e: E) { - e.hash(&mut FakeHasher(v)); +fn fake_hash(v: &mut Vec, a: A) { + a.hash(&mut FakeHasher(v)); } fn main() { @@ -69,4 +69,13 @@ fn main() { fake_hash(&mut va, E::A); fake_hash(&mut vb, E::B); assert!(va != vb); + + // issue #39137: single variant enum hash should not hash discriminant + #[derive(Hash)] + enum SingleVariantEnum { + A(u8), + } + let mut v = vec![]; + fake_hash(&mut v, SingleVariantEnum::A(17)); + assert_eq!(vec![17], v); } diff --git a/src/test/run-pass/dst-irrefutable-bind.rs b/src/test/run-pass/dst-irrefutable-bind.rs index 9f8067f372a..b1d6c732e7f 100644 --- a/src/test/run-pass/dst-irrefutable-bind.rs +++ b/src/test/run-pass/dst-irrefutable-bind.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(unsized_tuple_coercion)] + struct Test(T); fn main() { @@ -21,4 +23,14 @@ fn main() { let slice = &[1,2,3]; let x = Test(&slice); let Test(&_slice) = x; + + + let x = (10, [1,2,3]); + let x : &(i32, [i32]) = &x; + + let & ref _y = x; + + let slice = &[1,2,3]; + let x = (10, &slice); + let (_, &_slice) = x; } diff --git a/src/test/run-pass/dst-raw.rs b/src/test/run-pass/dst-raw.rs index 3a74626b029..9ebfbee8a33 100644 --- a/src/test/run-pass/dst-raw.rs +++ b/src/test/run-pass/dst-raw.rs @@ -11,6 +11,8 @@ // Test DST raw pointers +#![feature(unsized_tuple_coercion)] + trait Trait { fn foo(&self) -> isize; } @@ -45,6 +47,14 @@ pub fn main() { }; assert_eq!(r, 42); + // raw DST tuple + let p = (A { f: 42 },); + let o: *const (Trait,) = &p; + let r = unsafe { + (&*o).0.foo() + }; + assert_eq!(r, 42); + // raw slice let a: *const [_] = &[1, 2, 3]; unsafe { @@ -72,6 +82,15 @@ pub fn main() { assert_eq!(len, 3); } + // raw DST tuple with slice + let c: *const ([_],) = &([1, 2, 3],); + unsafe { + let b = (&*c).0[0]; + assert_eq!(b, 1); + let len = (&*c).0.len(); + assert_eq!(len, 3); + } + // all of the above with *mut let mut x = A { f: 42 }; let z: *mut Trait = &mut x; @@ -87,6 +106,13 @@ pub fn main() { }; assert_eq!(r, 42); + let mut p = (A { f: 42 },); + let o: *mut (Trait,) = &mut p; + let r = unsafe { + (&*o).0.foo() + }; + assert_eq!(r, 42); + let a: *mut [_] = &mut [1, 2, 3]; unsafe { let b = (*a)[2]; @@ -110,4 +136,12 @@ pub fn main() { let len = (&*c).f.len(); assert_eq!(len, 3); } + + let c: *mut ([_],) = &mut ([1, 2, 3],); + unsafe { + let b = (&*c).0[0]; + assert_eq!(b, 1); + let len = (&*c).0.len(); + assert_eq!(len, 3); + } } diff --git a/src/test/run-pass/dst-trait-tuple.rs b/src/test/run-pass/dst-trait-tuple.rs new file mode 100644 index 00000000000..9803e26f5f8 --- /dev/null +++ b/src/test/run-pass/dst-trait-tuple.rs @@ -0,0 +1,111 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +#![allow(unused_features)] +#![feature(box_syntax)] +#![feature(unsized_tuple_coercion)] + +type Fat = (isize, &'static str, T); + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +struct Bar; + +#[derive(Copy, Clone, PartialEq, Eq)] +struct Bar1 { + f: isize +} + +trait ToBar { + fn to_bar(&self) -> Bar; + fn to_val(&self) -> isize; +} + +impl ToBar for Bar { + fn to_bar(&self) -> Bar { + *self + } + fn to_val(&self) -> isize { + 0 + } +} +impl ToBar for Bar1 { + fn to_bar(&self) -> Bar { + Bar + } + fn to_val(&self) -> isize { + self.f + } +} + +// x is a fat pointer +fn foo(x: &Fat) { + assert_eq!(x.0, 5); + assert_eq!(x.1, "some str"); + assert_eq!(x.2.to_bar(), Bar); + assert_eq!(x.2.to_val(), 42); + + let y = &x.2; + assert_eq!(y.to_bar(), Bar); + assert_eq!(y.to_val(), 42); +} + +fn bar(x: &ToBar) { + assert_eq!(x.to_bar(), Bar); + assert_eq!(x.to_val(), 42); +} + +fn baz(x: &Fat>) { + assert_eq!(x.0, 5); + assert_eq!(x.1, "some str"); + assert_eq!((x.2).0, 8); + assert_eq!((x.2).1, "deep str"); + assert_eq!((x.2).2.to_bar(), Bar); + assert_eq!((x.2).2.to_val(), 42); + + let y = &(x.2).2; + assert_eq!(y.to_bar(), Bar); + assert_eq!(y.to_val(), 42); + +} + +pub fn main() { + let f1 = (5, "some str", Bar1 {f :42}); + foo(&f1); + let f2 = &f1; + foo(f2); + let f3: &Fat = f2; + foo(f3); + let f4: &Fat = &f1; + foo(f4); + let f5: &Fat = &(5, "some str", Bar1 {f :42}); + foo(f5); + + // Zero size object. + let f6: &Fat = &(5, "some str", Bar); + assert_eq!(f6.2.to_bar(), Bar); + + // &* + // + let f7: Box = Box::new(Bar1 {f :42}); + bar(&*f7); + + // Deep nesting + let f1 = (5, "some str", (8, "deep str", Bar1 {f :42})); + baz(&f1); + let f2 = &f1; + baz(f2); + let f3: &Fat> = f2; + baz(f3); + let f4: &Fat> = &f1; + baz(f4); + let f5: &Fat> = &(5, "some str", (8, "deep str", Bar1 {f :42})); + baz(f5); +} diff --git a/src/test/run-pass/dst-tuple-sole.rs b/src/test/run-pass/dst-tuple-sole.rs new file mode 100644 index 00000000000..a788e25218e --- /dev/null +++ b/src/test/run-pass/dst-tuple-sole.rs @@ -0,0 +1,85 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// As dst-tuple.rs, but the unsized field is the only field in the tuple. + + +#![feature(unsized_tuple_coercion)] + +type Fat = (T,); + +// x is a fat pointer +fn foo(x: &Fat<[isize]>) { + let y = &x.0; + assert_eq!(x.0.len(), 3); + assert_eq!(y[0], 1); + assert_eq!(x.0[1], 2); +} + +fn foo2(x: &Fat<[T]>) { + let y = &x.0; + let bar = Bar; + assert_eq!(x.0.len(), 3); + assert_eq!(y[0].to_bar(), bar); + assert_eq!(x.0[1].to_bar(), bar); +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +struct Bar; + +trait ToBar { + fn to_bar(&self) -> Bar; +} + +impl ToBar for Bar { + fn to_bar(&self) -> Bar { + *self + } +} + +pub fn main() { + // With a vec of ints. + let f1 = ([1, 2, 3],); + foo(&f1); + let f2 = &f1; + foo(f2); + let f3: &Fat<[isize]> = f2; + foo(f3); + let f4: &Fat<[isize]> = &f1; + foo(f4); + let f5: &Fat<[isize]> = &([1, 2, 3],); + foo(f5); + + // With a vec of Bars. + let bar = Bar; + let f1 = ([bar, bar, bar],); + foo2(&f1); + let f2 = &f1; + foo2(f2); + let f3: &Fat<[Bar]> = f2; + foo2(f3); + let f4: &Fat<[Bar]> = &f1; + foo2(f4); + let f5: &Fat<[Bar]> = &([bar, bar, bar],); + foo2(f5); + + // Assignment. + let f5: &mut Fat<[isize]> = &mut ([1, 2, 3],); + f5.0[1] = 34; + assert_eq!(f5.0[0], 1); + assert_eq!(f5.0[1], 34); + assert_eq!(f5.0[2], 3); + + // Zero size vec. + let f5: &Fat<[isize]> = &([],); + assert!(f5.0.is_empty()); + let f5: &Fat<[Bar]> = &([],); + assert!(f5.0.is_empty()); +} diff --git a/src/test/run-pass/dst-tuple.rs b/src/test/run-pass/dst-tuple.rs new file mode 100644 index 00000000000..2f5b28495b8 --- /dev/null +++ b/src/test/run-pass/dst-tuple.rs @@ -0,0 +1,129 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +#![allow(unknown_features)] +#![feature(box_syntax)] +#![feature(unsized_tuple_coercion)] + +type Fat = (isize, &'static str, T); + +// x is a fat pointer +fn foo(x: &Fat<[isize]>) { + let y = &x.2; + assert_eq!(x.2.len(), 3); + assert_eq!(y[0], 1); + assert_eq!(x.2[1], 2); + assert_eq!(x.0, 5); + assert_eq!(x.1, "some str"); +} + +fn foo2(x: &Fat<[T]>) { + let y = &x.2; + let bar = Bar; + assert_eq!(x.2.len(), 3); + assert_eq!(y[0].to_bar(), bar); + assert_eq!(x.2[1].to_bar(), bar); + assert_eq!(x.0, 5); + assert_eq!(x.1, "some str"); +} + +fn foo3(x: &Fat>) { + let y = &(x.2).2; + assert_eq!(x.0, 5); + assert_eq!(x.1, "some str"); + assert_eq!((x.2).0, 8); + assert_eq!((x.2).1, "deep str"); + assert_eq!((x.2).2.len(), 3); + assert_eq!(y[0], 1); + assert_eq!((x.2).2[1], 2); +} + + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +struct Bar; + +trait ToBar { + fn to_bar(&self) -> Bar; +} + +impl ToBar for Bar { + fn to_bar(&self) -> Bar { + *self + } +} + +pub fn main() { + // With a vec of ints. + let f1 = (5, "some str", [1, 2, 3]); + foo(&f1); + let f2 = &f1; + foo(f2); + let f3: &Fat<[isize]> = f2; + foo(f3); + let f4: &Fat<[isize]> = &f1; + foo(f4); + let f5: &Fat<[isize]> = &(5, "some str", [1, 2, 3]); + foo(f5); + + // With a vec of Bars. + let bar = Bar; + let f1 = (5, "some str", [bar, bar, bar]); + foo2(&f1); + let f2 = &f1; + foo2(f2); + let f3: &Fat<[Bar]> = f2; + foo2(f3); + let f4: &Fat<[Bar]> = &f1; + foo2(f4); + let f5: &Fat<[Bar]> = &(5, "some str", [bar, bar, bar]); + foo2(f5); + + // Assignment. + let f5: &mut Fat<[isize]> = &mut (5, "some str", [1, 2, 3]); + f5.2[1] = 34; + assert_eq!(f5.2[0], 1); + assert_eq!(f5.2[1], 34); + assert_eq!(f5.2[2], 3); + + // Zero size vec. + let f5: &Fat<[isize]> = &(5, "some str", []); + assert!(f5.2.is_empty()); + let f5: &Fat<[Bar]> = &(5, "some str", []); + assert!(f5.2.is_empty()); + + // Deeply nested. + let f1 = (5, "some str", (8, "deep str", [1, 2, 3])); + foo3(&f1); + let f2 = &f1; + foo3(f2); + let f3: &Fat> = f2; + foo3(f3); + let f4: &Fat> = &f1; + foo3(f4); + let f5: &Fat> = &(5, "some str", (8, "deep str", [1, 2, 3])); + foo3(f5); + + // Box. + let f1 = Box::new([1, 2, 3]); + assert_eq!((*f1)[1], 2); + let f2: Box<[isize]> = f1; + assert_eq!((*f2)[1], 2); + + // Nested Box. + let f1 : Box> = box (5, "some str", [1, 2, 3]); + foo(&*f1); + let f2 : Box> = f1; + foo(&*f2); + + let f3 : Box> = + Box::>::new((5, "some str", [1, 2, 3])); + foo(&*f3); +} diff --git a/src/test/run-pass/dynamic-drop.rs b/src/test/run-pass/dynamic-drop.rs index 6725a0c547f..bdcd3eecc69 100644 --- a/src/test/run-pass/dynamic-drop.rs +++ b/src/test/run-pass/dynamic-drop.rs @@ -106,6 +106,18 @@ fn struct_dynamic_drop(a: &Allocator, c0: bool, c1: bool, c: bool) { } } +fn field_assignment(a: &Allocator, c0: bool) { + let mut x = (TwoPtrs(a.alloc(), a.alloc()), a.alloc()); + + x.1 = a.alloc(); + x.1 = a.alloc(); + + let f = (x.0).0; + if c0 { + (x.0).0 = f; + } +} + fn assignment2(a: &Allocator, c0: bool, c1: bool) { let mut _v = a.alloc(); let mut _w = a.alloc(); @@ -207,5 +219,8 @@ fn main() { run_test(|a| struct_dynamic_drop(a, true, true, false)); run_test(|a| struct_dynamic_drop(a, true, true, true)); + run_test(|a| field_assignment(a, false)); + run_test(|a| field_assignment(a, true)); + run_test_nopanic(|a| union1(a)); } diff --git a/src/test/run-pass/env.rs b/src/test/run-pass/env.rs new file mode 100644 index 00000000000..e602fb2d7d2 --- /dev/null +++ b/src/test/run-pass/env.rs @@ -0,0 +1,98 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: --test + +#![feature(rand, std_panic)] + +use std::env::*; +use std::__rand as rand; +use std::__rand::Rng; +use std::iter::repeat; +use std::ffi::{OsString, OsStr}; + + +fn make_rand_name() -> OsString { + let mut rng = rand::thread_rng(); + let n = format!("TEST{}", rng.gen_ascii_chars().take(10) + .collect::()); + let n = OsString::from(n); + assert!(var_os(&n).is_none()); + n +} + +fn eq(a: Option, b: Option<&str>) { + assert_eq!(a.as_ref().map(|s| &**s), b.map(OsStr::new).map(|s| &*s)); +} + +#[test] +fn test_set_var() { + let n = make_rand_name(); + set_var(&n, "VALUE"); + eq(var_os(&n), Some("VALUE")); +} + +#[test] +fn test_remove_var() { + let n = make_rand_name(); + set_var(&n, "VALUE"); + remove_var(&n); + eq(var_os(&n), None); +} + +#[test] +fn test_set_var_overwrite() { + let n = make_rand_name(); + set_var(&n, "1"); + set_var(&n, "2"); + eq(var_os(&n), Some("2")); + set_var(&n, ""); + eq(var_os(&n), Some("")); +} + +#[test] +#[cfg_attr(target_os = "emscripten", ignore)] +fn test_var_big() { + let mut s = "".to_string(); + let mut i = 0; + while i < 100 { + s.push_str("aaaaaaaaaa"); + i += 1; + } + let n = make_rand_name(); + set_var(&n, &s); + eq(var_os(&n), Some(&s)); +} + +#[test] +#[cfg_attr(target_os = "emscripten", ignore)] +fn test_env_set_get_huge() { + let n = make_rand_name(); + let s = repeat("x").take(10000).collect::(); + set_var(&n, &s); + eq(var_os(&n), Some(&s)); + remove_var(&n); + eq(var_os(&n), None); +} + +#[test] +fn test_env_set_var() { + let n = make_rand_name(); + + let mut e = vars_os(); + set_var(&n, "VALUE"); + assert!(!e.any(|(k, v)| { + &*k == &*n && &*v == "VALUE" + })); + + assert!(vars_os().any(|(k, v)| { + &*k == &*n && &*v == "VALUE" + })); +} diff --git a/src/test/run-pass/issue-31260.rs b/src/test/run-pass/issue-31260.rs index e771fc7464d..d21ffb96bef 100644 --- a/src/test/run-pass/issue-31260.rs +++ b/src/test/run-pass/issue-31260.rs @@ -12,9 +12,12 @@ pub struct Struct { pub field: K, } -// Partial fix for #31260, doesn't work without {...}. static STRUCT: Struct<&'static [u8]> = Struct { field: {&[1]} }; +static STRUCT2: Struct<&'static [u8]> = Struct { + field: &[1] +}; + fn main() {} diff --git a/src/test/run-pass/issue-37725.rs b/src/test/run-pass/issue-37725.rs new file mode 100644 index 00000000000..5ed1295c85c --- /dev/null +++ b/src/test/run-pass/issue-37725.rs @@ -0,0 +1,14 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub fn foo<'a>(s: &'a mut ()) where &'a mut (): Clone { + s.clone(); +} +fn main() {} diff --git a/src/test/run-pass/macro-pat-neg-lit.rs b/src/test/run-pass/macro-pat-neg-lit.rs new file mode 100644 index 00000000000..43ac697edce --- /dev/null +++ b/src/test/run-pass/macro-pat-neg-lit.rs @@ -0,0 +1,35 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +macro_rules! enum_number { + ($name:ident { $($variant:ident = $value:expr, )* }) => { + enum $name { + $($variant = $value,)* + } + + fn foo(value: i32) -> Option<$name> { + match value { + $( $value => Some($name::$variant), )* + _ => None + } + } + } +} + +enum_number!(Change { + Down = -1, + None = 0, + Up = 1, +}); + +fn main() { + if let Some(Change::Down) = foo(-1) {} else { panic!() } +} + diff --git a/src/test/run-pass/process-envs.rs b/src/test/run-pass/process-envs.rs index a131dcbe4dd..b3785d898ba 100644 --- a/src/test/run-pass/process-envs.rs +++ b/src/test/run-pass/process-envs.rs @@ -10,8 +10,6 @@ // ignore-emscripten -#![feature(command_envs)] - use std::process::Command; use std::env; use std::collections::HashMap; diff --git a/src/test/run-pass/range_inclusive.rs b/src/test/run-pass/range_inclusive.rs index 372d4a8b732..f6119e70999 100644 --- a/src/test/run-pass/range_inclusive.rs +++ b/src/test/run-pass/range_inclusive.rs @@ -10,7 +10,7 @@ // Test inclusive range syntax. -#![feature(inclusive_range_syntax, inclusive_range, step_by)] +#![feature(inclusive_range_syntax, inclusive_range, iterator_step_by)] use std::ops::{RangeInclusive, RangeToInclusive}; diff --git a/src/test/run-pass/sync-send-iterators-in-libcore.rs b/src/test/run-pass/sync-send-iterators-in-libcore.rs index d12bdf182fa..c11a0d391a4 100644 --- a/src/test/run-pass/sync-send-iterators-in-libcore.rs +++ b/src/test/run-pass/sync-send-iterators-in-libcore.rs @@ -14,7 +14,7 @@ #![feature(iter_empty)] #![feature(iter_once)] #![feature(iter_unfold)] -#![feature(step_by)] +#![feature(iterator_step_by)] #![feature(str_escape)] use std::iter::{empty, once, repeat}; diff --git a/src/test/run-pass/test-allow-fail-attr.rs b/src/test/run-pass/test-allow-fail-attr.rs new file mode 100644 index 00000000000..aa9cf76617f --- /dev/null +++ b/src/test/run-pass/test-allow-fail-attr.rs @@ -0,0 +1,24 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: --test +#![feature(allow_fail)] + +#[test] +#[allow_fail] +fn test1() { + panic!(); +} + +#[test] +#[allow_fail] +fn test2() { + assert!(true); +} diff --git a/src/test/run-pass/vector-sort-panic-safe.rs b/src/test/run-pass/vector-sort-panic-safe.rs index 8ad6ca0abb0..4387a43f03b 100644 --- a/src/test/run-pass/vector-sort-panic-safe.rs +++ b/src/test/run-pass/vector-sort-panic-safe.rs @@ -10,14 +10,17 @@ // ignore-emscripten no threads support -#![feature(rand)] #![feature(const_fn)] +#![feature(rand)] +#![feature(sort_unstable)] use std::__rand::{thread_rng, Rng}; -use std::panic; -use std::sync::atomic::{AtomicUsize, Ordering}; -use std::thread; use std::cell::Cell; +use std::cmp::Ordering; +use std::panic; +use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize}; +use std::sync::atomic::Ordering::Relaxed; +use std::thread; const MAX_LEN: usize = 80; @@ -45,54 +48,85 @@ static DROP_COUNTS: [AtomicUsize; MAX_LEN] = [ AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), ]; -#[derive(Clone, PartialEq, PartialOrd, Eq, Ord)] +static VERSIONS: AtomicUsize = ATOMIC_USIZE_INIT; + +#[derive(Clone, Eq)] struct DropCounter { x: u32, id: usize, + version: Cell, +} + +impl PartialEq for DropCounter { + fn eq(&self, other: &Self) -> bool { + self.partial_cmp(other) == Some(Ordering::Equal) + } +} + +impl PartialOrd for DropCounter { + fn partial_cmp(&self, other: &Self) -> Option { + self.version.set(self.version.get() + 1); + other.version.set(other.version.get() + 1); + VERSIONS.fetch_add(2, Relaxed); + self.x.partial_cmp(&other.x) + } +} + +impl Ord for DropCounter { + fn cmp(&self, other: &Self) -> Ordering { + self.partial_cmp(other).unwrap() + } } impl Drop for DropCounter { fn drop(&mut self) { - DROP_COUNTS[self.id].fetch_add(1, Ordering::Relaxed); + DROP_COUNTS[self.id].fetch_add(1, Relaxed); + VERSIONS.fetch_sub(self.version.get(), Relaxed); } } -fn test(input: &[DropCounter]) { - let len = input.len(); +macro_rules! test { + ($input:ident, $func:ident) => { + let len = $input.len(); - // Work out the total number of comparisons required to sort - // this array... - let mut count = 0usize; - input.to_owned().sort_by(|a, b| { count += 1; a.cmp(b) }); + // Work out the total number of comparisons required to sort + // this array... + let mut count = 0usize; + $input.to_owned().$func(|a, b| { count += 1; a.cmp(b) }); - // ... and then panic on each and every single one. - for panic_countdown in 0..count { - // Refresh the counters. - for i in 0..len { - DROP_COUNTS[i].store(0, Ordering::Relaxed); - } + // ... and then panic on each and every single one. + for panic_countdown in 0..count { + // Refresh the counters. + VERSIONS.store(0, Relaxed); + for i in 0..len { + DROP_COUNTS[i].store(0, Relaxed); + } - let v = input.to_owned(); - let _ = thread::spawn(move || { - let mut v = v; - let mut panic_countdown = panic_countdown; - v.sort_by(|a, b| { - if panic_countdown == 0 { - SILENCE_PANIC.with(|s| s.set(true)); - panic!(); - } - panic_countdown -= 1; - a.cmp(b) - }) - }).join(); + let v = $input.to_owned(); + let _ = thread::spawn(move || { + let mut v = v; + let mut panic_countdown = panic_countdown; + v.$func(|a, b| { + if panic_countdown == 0 { + SILENCE_PANIC.with(|s| s.set(true)); + panic!(); + } + panic_countdown -= 1; + a.cmp(b) + }) + }).join(); - // Check that the number of things dropped is exactly - // what we expect (i.e. the contents of `v`). - for (i, c) in DROP_COUNTS.iter().enumerate().take(len) { - let count = c.load(Ordering::Relaxed); - assert!(count == 1, - "found drop count == {} for i == {}, len == {}", - count, i, len); + // Check that the number of things dropped is exactly + // what we expect (i.e. the contents of `v`). + for (i, c) in DROP_COUNTS.iter().enumerate().take(len) { + let count = c.load(Relaxed); + assert!(count == 1, + "found drop count == {} for i == {}, len == {}", + count, i, len); + } + + // Check that the most recent versions of values were dropped. + assert_eq!(VERSIONS.load(Relaxed), 0); } } } @@ -106,33 +140,41 @@ fn main() { prev(info); } })); + + let mut rng = thread_rng(); + for len in (1..20).chain(70..MAX_LEN) { - // Test on a random array. - let mut rng = thread_rng(); - let input = (0..len).map(|id| { - DropCounter { - x: rng.next_u32(), - id: id, - } - }).collect::>(); - test(&input); + for &modulus in &[5, 20, 50] { + for &has_runs in &[false, true] { + let mut input = (0..len) + .map(|id| { + DropCounter { + x: rng.next_u32() % modulus, + id: id, + version: Cell::new(0), + } + }) + .collect::>(); - // Test on a sorted array with two elements randomly swapped, creating several natural - // runs of random lengths. Such arrays have very high chances of hitting all code paths in - // the merge procedure. - for _ in 0..5 { - let mut input = (0..len).map(|i| - DropCounter { - x: i as u32, - id: i, + if has_runs { + for c in &mut input { + c.x = c.id as u32; + } + + for _ in 0..5 { + let a = rng.gen::() % len; + let b = rng.gen::() % len; + if a < b { + input[a..b].reverse(); + } else { + input.swap(a, b); + } + } } - ).collect::>(); - let a = rng.gen::() % len; - let b = rng.gen::() % len; - input.swap(a, b); - - test(&input); + test!(input, sort_by); + test!(input, sort_unstable_by); + } } } } diff --git a/src/test/rustdoc/issue-42875.rs b/src/test/rustdoc/issue-42875.rs new file mode 100644 index 00000000000..ebf7056755e --- /dev/null +++ b/src/test/rustdoc/issue-42875.rs @@ -0,0 +1,23 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: --no-defaults + +#![crate_name = "foo"] + +// @has foo/a/index.html '//code' 'use *;' +mod a { + use *; +} + +// @has foo/b/index.html '//code' 'pub use *;' +pub mod b { + pub use *; +} diff --git a/src/test/compile-fail/block-must-not-have-result-do.rs b/src/test/ui/block-result/block-must-not-have-result-do.rs similarity index 100% rename from src/test/compile-fail/block-must-not-have-result-do.rs rename to src/test/ui/block-result/block-must-not-have-result-do.rs diff --git a/src/test/ui/block-result/block-must-not-have-result-do.stderr b/src/test/ui/block-result/block-must-not-have-result-do.stderr new file mode 100644 index 00000000000..d4024f41c26 --- /dev/null +++ b/src/test/ui/block-result/block-must-not-have-result-do.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/block-must-not-have-result-do.rs:13:9 + | +13 | true //~ ERROR mismatched types + | ^^^^ expected (), found bool + | + = note: expected type `()` + found type `bool` + +error: aborting due to previous error + diff --git a/src/test/compile-fail/block-must-not-have-result-res.rs b/src/test/ui/block-result/block-must-not-have-result-res.rs similarity index 100% rename from src/test/compile-fail/block-must-not-have-result-res.rs rename to src/test/ui/block-result/block-must-not-have-result-res.rs diff --git a/src/test/ui/block-result/block-must-not-have-result-res.stderr b/src/test/ui/block-result/block-must-not-have-result-res.stderr new file mode 100644 index 00000000000..f60a0c2e5f6 --- /dev/null +++ b/src/test/ui/block-result/block-must-not-have-result-res.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/block-must-not-have-result-res.rs:15:9 + | +15 | true //~ ERROR mismatched types + | ^^^^ expected (), found bool + | + = note: expected type `()` + found type `bool` + +error: aborting due to previous error + diff --git a/src/test/compile-fail/block-must-not-have-result-while.rs b/src/test/ui/block-result/block-must-not-have-result-while.rs similarity index 100% rename from src/test/compile-fail/block-must-not-have-result-while.rs rename to src/test/ui/block-result/block-must-not-have-result-while.rs diff --git a/src/test/ui/block-result/block-must-not-have-result-while.stderr b/src/test/ui/block-result/block-must-not-have-result-while.stderr new file mode 100644 index 00000000000..888a64c1bb1 --- /dev/null +++ b/src/test/ui/block-result/block-must-not-have-result-while.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/block-must-not-have-result-while.rs:13:9 + | +13 | true //~ ERROR mismatched types + | ^^^^ expected (), found bool + | + = note: expected type `()` + found type `bool` + +error: aborting due to previous error + diff --git a/src/test/compile-fail/consider-removing-last-semi.rs b/src/test/ui/block-result/consider-removing-last-semi.rs similarity index 100% rename from src/test/compile-fail/consider-removing-last-semi.rs rename to src/test/ui/block-result/consider-removing-last-semi.rs diff --git a/src/test/ui/block-result/consider-removing-last-semi.stderr b/src/test/ui/block-result/consider-removing-last-semi.stderr new file mode 100644 index 00000000000..5905cfa9322 --- /dev/null +++ b/src/test/ui/block-result/consider-removing-last-semi.stderr @@ -0,0 +1,30 @@ +error[E0308]: mismatched types + --> $DIR/consider-removing-last-semi.rs:11:18 + | +11 | fn f() -> String { //~ ERROR mismatched types + | __________________^ +12 | | 0u8; +13 | | "bla".to_string(); //~ HELP consider removing this semicolon + | | - help: consider removing this semicolon +14 | | } + | |_^ expected struct `std::string::String`, found () + | + = note: expected type `std::string::String` + found type `()` + +error[E0308]: mismatched types + --> $DIR/consider-removing-last-semi.rs:16:18 + | +16 | fn g() -> String { //~ ERROR mismatched types + | __________________^ +17 | | "this won't work".to_string(); +18 | | "removeme".to_string(); //~ HELP consider removing this semicolon + | | - help: consider removing this semicolon +19 | | } + | |_^ expected struct `std::string::String`, found () + | + = note: expected type `std::string::String` + found type `()` + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/issue-11714.rs b/src/test/ui/block-result/issue-11714.rs similarity index 100% rename from src/test/compile-fail/issue-11714.rs rename to src/test/ui/block-result/issue-11714.rs diff --git a/src/test/ui/block-result/issue-11714.stderr b/src/test/ui/block-result/issue-11714.stderr new file mode 100644 index 00000000000..376834beab0 --- /dev/null +++ b/src/test/ui/block-result/issue-11714.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/issue-11714.rs:11:18 + | +11 | fn blah() -> i32 { //~ ERROR mismatched types + | __________________^ +12 | | 1 +13 | | +14 | | ; //~ HELP consider removing this semicolon: + | | - help: consider removing this semicolon +15 | | } + | |_^ expected i32, found () + | + = note: expected type `i32` + found type `()` + +error: aborting due to previous error + diff --git a/src/test/compile-fail/issue-13428.rs b/src/test/ui/block-result/issue-13428.rs similarity index 100% rename from src/test/compile-fail/issue-13428.rs rename to src/test/ui/block-result/issue-13428.rs diff --git a/src/test/ui/block-result/issue-13428.stderr b/src/test/ui/block-result/issue-13428.stderr new file mode 100644 index 00000000000..7bd4529c463 --- /dev/null +++ b/src/test/ui/block-result/issue-13428.stderr @@ -0,0 +1,33 @@ +error[E0308]: mismatched types + --> $DIR/issue-13428.rs:13:20 + | +13 | fn foo() -> String { //~ ERROR mismatched types + | ____________________^ +14 | | format!("Hello {}", +15 | | "world") +16 | | // Put the trailing semicolon on its own line to test that the +17 | | // note message gets the offending semicolon exactly +18 | | ; //~ HELP consider removing this semicolon + | | - help: consider removing this semicolon +19 | | } + | |_^ expected struct `std::string::String`, found () + | + = note: expected type `std::string::String` + found type `()` + +error[E0308]: mismatched types + --> $DIR/issue-13428.rs:21:20 + | +21 | fn bar() -> String { //~ ERROR mismatched types + | ____________________^ +22 | | "foobar".to_string() +23 | | ; //~ HELP consider removing this semicolon + | | - help: consider removing this semicolon +24 | | } + | |_^ expected struct `std::string::String`, found () + | + = note: expected type `std::string::String` + found type `()` + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/issue-13624.rs b/src/test/ui/block-result/issue-13624.rs similarity index 100% rename from src/test/compile-fail/issue-13624.rs rename to src/test/ui/block-result/issue-13624.rs diff --git a/src/test/ui/block-result/issue-13624.stderr b/src/test/ui/block-result/issue-13624.stderr new file mode 100644 index 00000000000..41113eb7a57 --- /dev/null +++ b/src/test/ui/block-result/issue-13624.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/issue-13624.rs:17:5 + | +17 | Enum::EnumStructVariant { x: 1, y: 2, z: 3 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `a::Enum` + | + = note: expected type `()` + found type `a::Enum` + +error[E0308]: mismatched types + --> $DIR/issue-13624.rs:32:9 + | +32 | a::Enum::EnumStructVariant { x, y, z } => { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `a::Enum` + | + = note: expected type `()` + found type `a::Enum` + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/issue-20862.rs b/src/test/ui/block-result/issue-20862.rs similarity index 100% rename from src/test/compile-fail/issue-20862.rs rename to src/test/ui/block-result/issue-20862.rs diff --git a/src/test/ui/block-result/issue-20862.stderr b/src/test/ui/block-result/issue-20862.stderr new file mode 100644 index 00000000000..7c88d789fd3 --- /dev/null +++ b/src/test/ui/block-result/issue-20862.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/issue-20862.rs:12:5 + | +11 | fn foo(x: i32) { + | - possibly return type missing here? +12 | |y| x + y + | ^^^^^^^^^ expected (), found closure + | + = note: expected type `()` + found type `[closure@$DIR/issue-20862.rs:12:5: 12:14 x:_]` + +error[E0618]: expected function, found `()` + --> $DIR/issue-20862.rs:17:13 + | +17 | let x = foo(5)(2); + | ^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/issue-22645.rs b/src/test/ui/block-result/issue-22645.rs similarity index 100% rename from src/test/compile-fail/issue-22645.rs rename to src/test/ui/block-result/issue-22645.rs diff --git a/src/test/ui/block-result/issue-22645.stderr b/src/test/ui/block-result/issue-22645.stderr new file mode 100644 index 00000000000..a9bcc8bea94 --- /dev/null +++ b/src/test/ui/block-result/issue-22645.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `{integer}: Scalar` is not satisfied + --> $DIR/issue-22645.rs:25:5 + | +25 | b + 3 //~ ERROR E0277 + | ^ the trait `Scalar` is not implemented for `{integer}` + | + = help: the following implementations were found: + + = note: required because of the requirements on the impl of `std::ops::Add<{integer}>` for `Bob` + +error[E0308]: mismatched types + --> $DIR/issue-22645.rs:25:3 + | +25 | b + 3 //~ ERROR E0277 + | ^^^^^ expected (), found struct `Bob` + | + = note: expected type `()` + found type `Bob` + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/issue-3563.rs b/src/test/ui/block-result/issue-3563.rs similarity index 100% rename from src/test/compile-fail/issue-3563.rs rename to src/test/ui/block-result/issue-3563.rs diff --git a/src/test/ui/block-result/issue-3563.stderr b/src/test/ui/block-result/issue-3563.stderr new file mode 100644 index 00000000000..4b1f8b032b7 --- /dev/null +++ b/src/test/ui/block-result/issue-3563.stderr @@ -0,0 +1,19 @@ +error[E0599]: no method named `b` found for type `&Self` in the current scope + --> $DIR/issue-3563.rs:13:17 + | +13 | || self.b() + | ^ + +error[E0308]: mismatched types + --> $DIR/issue-3563.rs:13:9 + | +12 | fn a(&self) { + | - possibly return type missing here? +13 | || self.b() + | ^^^^^^^^^^^ expected (), found closure + | + = note: expected type `()` + found type `[closure@$DIR/issue-3563.rs:13:9: 13:20 self:_]` + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/issue-5500.rs b/src/test/ui/block-result/issue-5500.rs similarity index 100% rename from src/test/compile-fail/issue-5500.rs rename to src/test/ui/block-result/issue-5500.rs diff --git a/src/test/ui/block-result/issue-5500.stderr b/src/test/ui/block-result/issue-5500.stderr new file mode 100644 index 00000000000..bd670a14f24 --- /dev/null +++ b/src/test/ui/block-result/issue-5500.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/issue-5500.rs:12:5 + | +12 | &panic!() + | ^^^^^^^^^ expected (), found reference + | + = note: expected type `()` + found type `&_` + +error: aborting due to previous error + diff --git a/src/test/ui/block-result/unexpected-return-on-unit.rs b/src/test/ui/block-result/unexpected-return-on-unit.rs new file mode 100644 index 00000000000..291b7a16f14 --- /dev/null +++ b/src/test/ui/block-result/unexpected-return-on-unit.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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we do some basic error correcton in the tokeniser (and don't spew +// too many bogus errors). + +fn foo() -> usize { + 3 +} + +fn bar() { + foo() +} + +fn main() { + bar() +} diff --git a/src/test/ui/block-result/unexpected-return-on-unit.stderr b/src/test/ui/block-result/unexpected-return-on-unit.stderr new file mode 100644 index 00000000000..68afd2084f1 --- /dev/null +++ b/src/test/ui/block-result/unexpected-return-on-unit.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> $DIR/unexpected-return-on-unit.rs:19:5 + | +19 | foo() + | ^^^^^ expected (), found usize + | + = note: expected type `()` + found type `usize` +help: did you mean to add a semicolon here? + | foo(); +help: possibly return type missing here? + | fn bar() -> usize { + +error: aborting due to previous error + diff --git a/src/test/ui/borrowck/borrowck-in-static.stderr b/src/test/ui/borrowck/borrowck-in-static.stderr index a30d4cbd64c..6083a82b1b6 100644 --- a/src/test/ui/borrowck/borrowck-in-static.stderr +++ b/src/test/ui/borrowck/borrowck-in-static.stderr @@ -6,5 +6,5 @@ error[E0507]: cannot move out of captured outer variable in an `Fn` closure 15 | Box::new(|| x) //~ ERROR cannot move out of captured outer variable | ^ cannot move out of captured outer variable in an `Fn` closure -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr index a13971d32de..dbfcb2e0c2f 100644 --- a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr +++ b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr @@ -7,5 +7,5 @@ error[E0507]: cannot move out of captured outer variable in an `Fn` closure 21 | y.into_iter(); | ^ cannot move out of captured outer variable in an `Fn` closure -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/check_match/issue-35609.stderr b/src/test/ui/check_match/issue-35609.stderr index 0cb264ff35e..0aafe3f17b3 100644 --- a/src/test/ui/check_match/issue-35609.stderr +++ b/src/test/ui/check_match/issue-35609.stderr @@ -46,5 +46,5 @@ error[E0004]: non-exhaustive patterns: `Some(B)`, `Some(C)`, `Some(D)` and 2 mor 49 | match Some(A) { | ^^^^^^^ patterns `Some(B)`, `Some(C)`, `Some(D)` and 2 more not covered -error: aborting due to previous error(s) +error: aborting due to 8 previous errors diff --git a/src/test/ui/closure_context/issue-26046-fn-mut.stderr b/src/test/ui/closure_context/issue-26046-fn-mut.stderr index dbf702e4503..42fc2909dfb 100644 --- a/src/test/ui/closure_context/issue-26046-fn-mut.stderr +++ b/src/test/ui/closure_context/issue-26046-fn-mut.stderr @@ -16,5 +16,5 @@ note: closure is `FnMut` because it mutates the variable `num` here 15 | num += 1; | ^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/closure_context/issue-26046-fn-once.stderr b/src/test/ui/closure_context/issue-26046-fn-once.stderr index 3ec3f0cc9aa..7bfe72d3d6c 100644 --- a/src/test/ui/closure_context/issue-26046-fn-once.stderr +++ b/src/test/ui/closure_context/issue-26046-fn-once.stderr @@ -16,5 +16,5 @@ note: closure is `FnOnce` because it moves the variable `vec` out of its environ 15 | vec | ^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/closure_context/issue-42065.stderr b/src/test/ui/closure_context/issue-42065.stderr index 5bbd372adb6..c195940ade6 100644 --- a/src/test/ui/closure_context/issue-42065.stderr +++ b/src/test/ui/closure_context/issue-42065.stderr @@ -12,5 +12,5 @@ note: closure cannot be invoked more than once because it moves the variable `di 16 | for (key, value) in dict { | ^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/codemap_tests/bad-format-args.stderr b/src/test/ui/codemap_tests/bad-format-args.stderr index cddc7df85ae..87255dfe774 100644 --- a/src/test/ui/codemap_tests/bad-format-args.stderr +++ b/src/test/ui/codemap_tests/bad-format-args.stderr @@ -22,5 +22,5 @@ error: expected token: `,` | = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr b/src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr index 1c32ce44109..7f1ab929c6f 100644 --- a/src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr +++ b/src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr @@ -6,5 +6,5 @@ error[E0592]: duplicate definitions with name `f` 15 | impl C { fn f() {} } | --------- other definition for `f` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/codemap_tests/empty_span.stderr b/src/test/ui/codemap_tests/empty_span.stderr index 84e6e336b93..b33dee6b4a4 100644 --- a/src/test/ui/codemap_tests/empty_span.stderr +++ b/src/test/ui/codemap_tests/empty_span.stderr @@ -4,5 +4,5 @@ error[E0321]: cross-crate traits with a default impl, like `std::marker::Send`, 17 | unsafe impl Send for &'static Foo { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/codemap_tests/huge_multispan_highlight.stderr b/src/test/ui/codemap_tests/huge_multispan_highlight.stderr index 46b3db18e8a..914db98c784 100644 --- a/src/test/ui/codemap_tests/huge_multispan_highlight.stderr +++ b/src/test/ui/codemap_tests/huge_multispan_highlight.stderr @@ -7,5 +7,5 @@ error[E0596]: cannot borrow immutable local variable `x` as mutable 100 | let y = &mut x; | ^ cannot borrow mutably -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/codemap_tests/issue-11715.stderr b/src/test/ui/codemap_tests/issue-11715.stderr index dcc21672c56..4947cbedd20 100644 --- a/src/test/ui/codemap_tests/issue-11715.stderr +++ b/src/test/ui/codemap_tests/issue-11715.stderr @@ -8,5 +8,5 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time 101 | } | - first borrow ends here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/codemap_tests/issue-28308.stderr b/src/test/ui/codemap_tests/issue-28308.stderr index 43743b796d5..7a1478104fd 100644 --- a/src/test/ui/codemap_tests/issue-28308.stderr +++ b/src/test/ui/codemap_tests/issue-28308.stderr @@ -6,5 +6,5 @@ error[E0600]: cannot apply unary operator `!` to type `&'static str` | = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/codemap_tests/one_line.stderr b/src/test/ui/codemap_tests/one_line.stderr index e2e0537226a..a73575a8d57 100644 --- a/src/test/ui/codemap_tests/one_line.stderr +++ b/src/test/ui/codemap_tests/one_line.stderr @@ -7,5 +7,5 @@ error[E0499]: cannot borrow `v` as mutable more than once at a time | | second mutable borrow occurs here | first mutable borrow occurs here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr b/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr index 0af8c06cfda..de8a24cf33f 100644 --- a/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr +++ b/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr @@ -25,5 +25,5 @@ error[E0592]: duplicate definitions with name `baz` 43 | fn baz(&self) {} | ---------------- other definition for `baz` -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/codemap_tests/overlapping_spans.stderr b/src/test/ui/codemap_tests/overlapping_spans.stderr index 9778015766c..d32b18d6703 100644 --- a/src/test/ui/codemap_tests/overlapping_spans.stderr +++ b/src/test/ui/codemap_tests/overlapping_spans.stderr @@ -7,5 +7,5 @@ error[E0509]: cannot move out of type `S`, which implements the `Drop` trait | | hint: to prevent move, use `ref _s` or `ref mut _s` | cannot move out of here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/codemap_tests/tab.stderr b/src/test/ui/codemap_tests/tab.stderr index a3b76159b46..657deca4e6d 100644 --- a/src/test/ui/codemap_tests/tab.stderr +++ b/src/test/ui/codemap_tests/tab.stderr @@ -4,5 +4,5 @@ error[E0425]: cannot find value `bar` in this scope 14 | \tbar; | \t^^^ not found in this scope -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/codemap_tests/unicode.stderr b/src/test/ui/codemap_tests/unicode.stderr index 0f1e008d589..0828fd28b58 100644 --- a/src/test/ui/codemap_tests/unicode.stderr +++ b/src/test/ui/codemap_tests/unicode.stderr @@ -4,5 +4,5 @@ error: invalid ABI: expected one of [cdecl, stdcall, fastcall, vectorcall, thisc 11 | extern "路濫狼á́́" fn foo() {} | ^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/coercion-missing-tail-expected-type.stderr b/src/test/ui/coercion-missing-tail-expected-type.stderr index e96bc425e0b..0de0a25e68e 100644 --- a/src/test/ui/coercion-missing-tail-expected-type.stderr +++ b/src/test/ui/coercion-missing-tail-expected-type.stderr @@ -4,16 +4,12 @@ error[E0308]: mismatched types 13 | fn plus_one(x: i32) -> i32 { | ____________________________^ 14 | | x + 1; + | | - help: consider removing this semicolon 15 | | } | |_^ expected i32, found () | = note: expected type `i32` found type `()` -help: consider removing this semicolon: - --> $DIR/coercion-missing-tail-expected-type.rs:14:10 - | -14 | x + 1; - | ^ error[E0308]: mismatched types --> $DIR/coercion-missing-tail-expected-type.rs:17:29 @@ -21,16 +17,12 @@ error[E0308]: mismatched types 17 | fn foo() -> Result { | _____________________________^ 18 | | Ok(1); + | | - help: consider removing this semicolon 19 | | } | |_^ expected enum `std::result::Result`, found () | = note: expected type `std::result::Result` found type `()` -help: consider removing this semicolon: - --> $DIR/coercion-missing-tail-expected-type.rs:18:10 - | -18 | Ok(1); - | ^ -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/compare-method/proj-outlives-region.stderr b/src/test/ui/compare-method/proj-outlives-region.stderr index 63c48ffe26b..2a707c6eb8b 100644 --- a/src/test/ui/compare-method/proj-outlives-region.stderr +++ b/src/test/ui/compare-method/proj-outlives-region.stderr @@ -11,5 +11,5 @@ error[E0276]: impl has stricter requirements than trait = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #37166 -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/compare-method/region-extra-2.stderr b/src/test/ui/compare-method/region-extra-2.stderr index 7adcc66d75c..af974d50183 100644 --- a/src/test/ui/compare-method/region-extra-2.stderr +++ b/src/test/ui/compare-method/region-extra-2.stderr @@ -10,5 +10,5 @@ error[E0276]: impl has stricter requirements than trait 22 | | } | |_____^ impl has extra requirement `'a: 'b` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/compare-method/region-extra.stderr b/src/test/ui/compare-method/region-extra.stderr index a29a292ac65..e657813221a 100644 --- a/src/test/ui/compare-method/region-extra.stderr +++ b/src/test/ui/compare-method/region-extra.stderr @@ -7,5 +7,5 @@ error[E0276]: impl has stricter requirements than trait 22 | fn foo() where 'a: 'b { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `'a: 'b` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/compare-method/region-unrelated.stderr b/src/test/ui/compare-method/region-unrelated.stderr index 04de54cd05d..9e822bd8b07 100644 --- a/src/test/ui/compare-method/region-unrelated.stderr +++ b/src/test/ui/compare-method/region-unrelated.stderr @@ -11,5 +11,5 @@ error[E0276]: impl has stricter requirements than trait = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #37166 -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/compare-method/reordered-type-param.stderr b/src/test/ui/compare-method/reordered-type-param.stderr index b5e9c89f2f5..4620248e2ef 100644 --- a/src/test/ui/compare-method/reordered-type-param.stderr +++ b/src/test/ui/compare-method/reordered-type-param.stderr @@ -10,5 +10,5 @@ error[E0053]: method `b` has an incompatible type for trait = note: expected type `fn(&E, F) -> F` found type `fn(&E, G) -> G` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/compare-method/trait-bound-on-type-parameter.stderr b/src/test/ui/compare-method/trait-bound-on-type-parameter.stderr index c4a4921289b..7112a00c7b7 100644 --- a/src/test/ui/compare-method/trait-bound-on-type-parameter.stderr +++ b/src/test/ui/compare-method/trait-bound-on-type-parameter.stderr @@ -7,5 +7,5 @@ error[E0276]: impl has stricter requirements than trait 25 | fn b(&self, _x: F) -> F { panic!() } //~ ERROR E0276 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `F: std::marker::Sync` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/compare-method/traits-misc-mismatch-1.stderr b/src/test/ui/compare-method/traits-misc-mismatch-1.stderr index 6374b83e794..f221ebe3302 100644 --- a/src/test/ui/compare-method/traits-misc-mismatch-1.stderr +++ b/src/test/ui/compare-method/traits-misc-mismatch-1.stderr @@ -61,5 +61,5 @@ error[E0276]: impl has stricter requirements than trait 76 | fn method>(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `G: Getter` -error: aborting due to previous error(s) +error: aborting due to 7 previous errors diff --git a/src/test/ui/compare-method/traits-misc-mismatch-2.stderr b/src/test/ui/compare-method/traits-misc-mismatch-2.stderr index 7ff2d93d820..622e144c53a 100644 --- a/src/test/ui/compare-method/traits-misc-mismatch-2.stderr +++ b/src/test/ui/compare-method/traits-misc-mismatch-2.stderr @@ -10,5 +10,5 @@ error[E0276]: impl has stricter requirements than trait 26 | | } | |_____^ impl has extra requirement `U: Iterator` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/cross-crate-macro-backtrace/main.stderr b/src/test/ui/cross-crate-macro-backtrace/main.stderr index 3642a702a82..84db85ac092 100644 --- a/src/test/ui/cross-crate-macro-backtrace/main.stderr +++ b/src/test/ui/cross-crate-macro-backtrace/main.stderr @@ -6,5 +6,5 @@ error: invalid reference to argument `0` (no arguments given) | = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/E0178.stderr b/src/test/ui/did_you_mean/E0178.stderr index bcf00df9832..15e7131cfd3 100644 --- a/src/test/ui/did_you_mean/E0178.stderr +++ b/src/test/ui/did_you_mean/E0178.stderr @@ -22,5 +22,5 @@ error[E0178]: expected a path on the left-hand side of `+`, not `fn() -> Foo` 17 | z: fn() -> Foo + 'a, | ^^^^^^^^^^^^^^^^ perhaps you forgot parentheses? -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr index 73b8e06183b..9010de081da 100644 --- a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr +++ b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr @@ -8,5 +8,5 @@ error[E0277]: the trait bound `Bar: Foo` is not satisfied > > -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr index e1e4e14b215..e9591a64784 100644 --- a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr +++ b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr @@ -11,5 +11,5 @@ error[E0277]: the trait bound `Bar: Foo` is not satisfied > and 2 others -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-31424.stderr b/src/test/ui/did_you_mean/issue-31424.stderr index eecb164a83f..c7d43a0fc0b 100644 --- a/src/test/ui/did_you_mean/issue-31424.stderr +++ b/src/test/ui/did_you_mean/issue-31424.stderr @@ -15,5 +15,5 @@ error[E0596]: cannot borrow immutable argument `self` as mutable 23 | (&mut self).bar(); | ^^^^ cannot borrow mutably -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/did_you_mean/issue-34126.stderr b/src/test/ui/did_you_mean/issue-34126.stderr index d5d6ee133b8..63d59a59238 100644 --- a/src/test/ui/did_you_mean/issue-34126.stderr +++ b/src/test/ui/did_you_mean/issue-34126.stderr @@ -7,5 +7,5 @@ error[E0596]: cannot borrow immutable argument `self` as mutable | try removing `&mut` here | cannot reborrow mutably -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-34337.stderr b/src/test/ui/did_you_mean/issue-34337.stderr index 2769c74be5e..9eb88cdeddb 100644 --- a/src/test/ui/did_you_mean/issue-34337.stderr +++ b/src/test/ui/did_you_mean/issue-34337.stderr @@ -7,5 +7,5 @@ error[E0596]: cannot borrow immutable local variable `key` as mutable | try removing `&mut` here | cannot reborrow mutably -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-35937.stderr b/src/test/ui/did_you_mean/issue-35937.stderr index 4760d28566f..1cd1fb76aa3 100644 --- a/src/test/ui/did_you_mean/issue-35937.stderr +++ b/src/test/ui/did_you_mean/issue-35937.stderr @@ -22,5 +22,5 @@ error[E0594]: cannot assign to immutable field `s.x` 30 | s.x += 1; | ^^^^^^^^ cannot mutably borrow immutable field -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/did_you_mean/issue-36798.stderr b/src/test/ui/did_you_mean/issue-36798.stderr index a8d978d5514..72fd09c0357 100644 --- a/src/test/ui/did_you_mean/issue-36798.stderr +++ b/src/test/ui/did_you_mean/issue-36798.stderr @@ -4,5 +4,5 @@ error[E0609]: no field `baz` on type `Foo` 17 | f.baz; | ^^^ did you mean `bar`? -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-36798_unknown_field.stderr b/src/test/ui/did_you_mean/issue-36798_unknown_field.stderr index 8228f9f3fac..82e3eab0836 100644 --- a/src/test/ui/did_you_mean/issue-36798_unknown_field.stderr +++ b/src/test/ui/did_you_mean/issue-36798_unknown_field.stderr @@ -4,5 +4,5 @@ error[E0609]: no field `zz` on type `Foo` 17 | f.zz; | ^^ unknown field -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-37139.stderr b/src/test/ui/did_you_mean/issue-37139.stderr index 6debbaadb1a..4348b6fca63 100644 --- a/src/test/ui/did_you_mean/issue-37139.stderr +++ b/src/test/ui/did_you_mean/issue-37139.stderr @@ -7,5 +7,5 @@ error[E0596]: cannot borrow immutable local variable `x` as mutable | try removing `&mut` here | cannot reborrow mutably -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr b/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr index 10f5972e369..325f55e686c 100644 --- a/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr +++ b/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr @@ -10,5 +10,5 @@ error[E0432]: unresolved import `Foo1` 13 | use Foo1; | ^^^^ no `Foo1` in the root -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/did_you_mean/issue-38147-1.stderr b/src/test/ui/did_you_mean/issue-38147-1.stderr index 85eecd037dd..e9f2b1dad80 100644 --- a/src/test/ui/did_you_mean/issue-38147-1.stderr +++ b/src/test/ui/did_you_mean/issue-38147-1.stderr @@ -6,5 +6,5 @@ error[E0389]: cannot borrow data mutably in a `&` reference 27 | self.s.push('x'); | ^^^^^^ assignment into an immutable reference -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-38147-2.stderr b/src/test/ui/did_you_mean/issue-38147-2.stderr index 2834fc6262f..e81bc722fa0 100644 --- a/src/test/ui/did_you_mean/issue-38147-2.stderr +++ b/src/test/ui/did_you_mean/issue-38147-2.stderr @@ -7,5 +7,5 @@ error[E0596]: cannot borrow immutable borrowed content `*self.s` as mutable 17 | self.s.push('x'); | ^^^^^^ cannot borrow as mutable -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-38147-3.stderr b/src/test/ui/did_you_mean/issue-38147-3.stderr index d950e82003c..749795f4d8f 100644 --- a/src/test/ui/did_you_mean/issue-38147-3.stderr +++ b/src/test/ui/did_you_mean/issue-38147-3.stderr @@ -7,5 +7,5 @@ error[E0596]: cannot borrow immutable borrowed content `*self.s` as mutable 17 | self.s.push('x'); | ^^^^^^ cannot borrow as mutable -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-38147-4.stderr b/src/test/ui/did_you_mean/issue-38147-4.stderr index 6fa152c970b..9a8853f4fbb 100644 --- a/src/test/ui/did_you_mean/issue-38147-4.stderr +++ b/src/test/ui/did_you_mean/issue-38147-4.stderr @@ -6,5 +6,5 @@ error[E0389]: cannot borrow data mutably in a `&` reference 16 | f.s.push('x'); | ^^^ assignment into an immutable reference -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-39544.stderr b/src/test/ui/did_you_mean/issue-39544.stderr index 94afe896d5e..28aaab97bda 100644 --- a/src/test/ui/did_you_mean/issue-39544.stderr +++ b/src/test/ui/did_you_mean/issue-39544.stderr @@ -96,5 +96,5 @@ error[E0594]: cannot assign to immutable borrowed content `*x.0` 58 | *x.0 = 1; | ^^^^^^^^ cannot borrow as mutable -error: aborting due to previous error(s) +error: aborting due to 12 previous errors diff --git a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr index 6a0e94bf138..4ea4adfcfe0 100644 --- a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr +++ b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr @@ -39,5 +39,5 @@ error[E0277]: the trait bound `bool: Foo` is not satisfied and 2 others = note: required by `Foo::bar` -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr index b1dab01d81f..3b7f32cf890 100644 --- a/src/test/ui/did_you_mean/issue-40006.stderr +++ b/src/test/ui/did_you_mean/issue-40006.stderr @@ -64,5 +64,5 @@ error[E0038]: the trait `X` cannot be made into an object | = note: method `xxx` has no receiver -error: aborting due to previous error(s) +error: aborting due to 9 previous errors diff --git a/src/test/ui/did_you_mean/issue-40396.stderr b/src/test/ui/did_you_mean/issue-40396.stderr index daee8df7ed8..1a0c74dc01a 100644 --- a/src/test/ui/did_you_mean/issue-40396.stderr +++ b/src/test/ui/did_you_mean/issue-40396.stderr @@ -30,5 +30,5 @@ error: chained comparison operators require parentheses | = help: use `::<...>` instead of `<...>` if you meant to specify type arguments -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/did_you_mean/issue-40823.stderr b/src/test/ui/did_you_mean/issue-40823.stderr index a034ea80969..7daab09c09e 100644 --- a/src/test/ui/did_you_mean/issue-40823.stderr +++ b/src/test/ui/did_you_mean/issue-40823.stderr @@ -4,5 +4,5 @@ error[E0596]: cannot borrow immutable borrowed content `*buf` as mutable 13 | buf.iter_mut(); | ^^^ cannot borrow as mutable -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-41679.stderr b/src/test/ui/did_you_mean/issue-41679.stderr index 4f210bb0b11..2abbbf65ba9 100644 --- a/src/test/ui/did_you_mean/issue-41679.stderr +++ b/src/test/ui/did_you_mean/issue-41679.stderr @@ -6,5 +6,5 @@ error: `~` can not be used as a unary operator | = help: use `!` instead of `~` if you meant to perform bitwise negation -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/recursion_limit.stderr b/src/test/ui/did_you_mean/recursion_limit.stderr index 32f9d90ec2d..d157c5de6c7 100644 --- a/src/test/ui/did_you_mean/recursion_limit.stderr +++ b/src/test/ui/did_you_mean/recursion_limit.stderr @@ -17,5 +17,5 @@ error[E0275]: overflow evaluating the requirement `K: std::marker::Send` = note: required because it appears within the type `A` = note: required by `is_send` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/recursion_limit_deref.stderr b/src/test/ui/did_you_mean/recursion_limit_deref.stderr index ba8d3815181..57b28d03736 100644 --- a/src/test/ui/did_you_mean/recursion_limit_deref.stderr +++ b/src/test/ui/did_you_mean/recursion_limit_deref.stderr @@ -19,5 +19,5 @@ error[E0308]: mismatched types = note: expected type `&Bottom` found type `&Top` -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr b/src/test/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr index 50e296a1bc5..498255cb9ea 100644 --- a/src/test/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr +++ b/src/test/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr @@ -18,5 +18,5 @@ error[E0038]: the trait `std::marker::Copy` cannot be made into an object | = note: the trait cannot require that `Self : Sized` -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/dropck/dropck-eyepatch-extern-crate.stderr b/src/test/ui/dropck/dropck-eyepatch-extern-crate.stderr index a5a3c48ab97..62ce3209c91 100644 --- a/src/test/ui/dropck/dropck-eyepatch-extern-crate.stderr +++ b/src/test/ui/dropck/dropck-eyepatch-extern-crate.stderr @@ -42,5 +42,5 @@ error[E0597]: `c` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr b/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr index e1bfb4d8c1e..2c788e952ed 100644 --- a/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr +++ b/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr @@ -20,5 +20,5 @@ error[E0569]: requires an `unsafe impl` declaration due to `#[may_dangle]` attri 43 | | } | |_^ -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/dropck/dropck-eyepatch-reorder.stderr b/src/test/ui/dropck/dropck-eyepatch-reorder.stderr index de04a1c4283..d94808bbcb6 100644 --- a/src/test/ui/dropck/dropck-eyepatch-reorder.stderr +++ b/src/test/ui/dropck/dropck-eyepatch-reorder.stderr @@ -42,5 +42,5 @@ error[E0597]: `c` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/dropck/dropck-eyepatch.stderr b/src/test/ui/dropck/dropck-eyepatch.stderr index 26fee852fb2..811eee0e85f 100644 --- a/src/test/ui/dropck/dropck-eyepatch.stderr +++ b/src/test/ui/dropck/dropck-eyepatch.stderr @@ -42,5 +42,5 @@ error[E0597]: `c` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/fmt/format-string-error.stderr b/src/test/ui/fmt/format-string-error.stderr index 2466d2b43b6..58b392f0b8d 100644 --- a/src/test/ui/fmt/format-string-error.stderr +++ b/src/test/ui/fmt/format-string-error.stderr @@ -16,5 +16,5 @@ error: invalid format string: unmatched `}` found = note: if you intended to print `}`, you can escape it using `}}` = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr index 2206234b777..3fc08a0900f 100644 --- a/src/test/ui/impl-trait/equality.stderr +++ b/src/test/ui/impl-trait/equality.stderr @@ -51,5 +51,5 @@ error[E0308]: mismatched types = note: expected type `impl Foo` (i32) found type `impl Foo` (u32) -error: aborting due to previous error(s) +error: aborting due to 6 previous errors diff --git a/src/test/ui/impl-trait/issue-21659-show-relevant-trait-impls-3.stderr b/src/test/ui/impl-trait/issue-21659-show-relevant-trait-impls-3.stderr index 1b1e0eaf203..3bc281726ef 100644 --- a/src/test/ui/impl-trait/issue-21659-show-relevant-trait-impls-3.stderr +++ b/src/test/ui/impl-trait/issue-21659-show-relevant-trait-impls-3.stderr @@ -8,5 +8,5 @@ error[E0599]: no method named `foo` found for type `Bar` in the current scope = note: the following trait defines an item `foo`, perhaps you need to implement it: candidate #1: `Foo` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr b/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr index fa08c3bee9c..d3dbb77490b 100644 --- a/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr +++ b/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr @@ -10,5 +10,5 @@ error[E0599]: no method named `is_empty` found for type `Foo` in the current sco candidate #2: `core::slice::SliceExt` candidate #3: `core::str::StrExt` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.stderr b/src/test/ui/impl-trait/no-method-suggested-traits.stderr index 95d3007a4fb..fc441f94842 100644 --- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr +++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr @@ -226,5 +226,5 @@ error[E0599]: no method named `method3` found for type `std::rc::Rc<&mut std::bo 131 | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method3(); | ^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to 24 previous errors diff --git a/src/test/ui/impl-trait/trait_type.stderr b/src/test/ui/impl-trait/trait_type.stderr index cc7a7153a38..9216c6e2907 100644 --- a/src/test/ui/impl-trait/trait_type.stderr +++ b/src/test/ui/impl-trait/trait_type.stderr @@ -31,5 +31,5 @@ error[E0046]: not all trait items implemented, missing: `fmt` | = note: `fmt` from trait: `fn(&Self, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>` -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/interior-mutability/interior-mutability.stderr b/src/test/ui/interior-mutability/interior-mutability.stderr index a9535f1c830..76362f1f494 100644 --- a/src/test/ui/interior-mutability/interior-mutability.stderr +++ b/src/test/ui/interior-mutability/interior-mutability.stderr @@ -10,5 +10,5 @@ error[E0277]: the trait bound `std::cell::UnsafeCell: std::panic::RefUnwind = note: required because it appears within the type `[closure@$DIR/interior-mutability.rs:15:18: 15:35 x:&std::cell::Cell]` = note: required by `std::panic::catch_unwind` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr b/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr index a444d5f5a40..3e9b21cdb74 100644 --- a/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr +++ b/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr @@ -10,5 +10,5 @@ note: maybe move this module `$DIR/auxiliary/foo/bar.rs` to its own directory vi 11 | pub mod baz; | ^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/issue-22644.stderr b/src/test/ui/issue-22644.stderr index a22496357d9..22c16ada05d 100644 --- a/src/test/ui/issue-22644.stderr +++ b/src/test/ui/issue-22644.stderr @@ -20,5 +20,5 @@ error: `<` is interpreted as a start of generic arguments for `usize`, not a com help: if you want to compare the casted value then write: | println!("{}", (a as usize) < 4); -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/issue-26548.stderr b/src/test/ui/issue-26548.stderr index c27ad7680a5..8bfe4ac733b 100644 --- a/src/test/ui/issue-26548.stderr +++ b/src/test/ui/issue-26548.stderr @@ -5,5 +5,5 @@ note: ...which then requires computing layout of `std::option::Option<::It`... = note: ...which then again requires computing layout of `S`, completing the cycle. -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/issue-33525.rs b/src/test/ui/issue-33525.rs new file mode 100644 index 00000000000..0e777fe8a94 --- /dev/null +++ b/src/test/ui/issue-33525.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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + a; + "".lorem; + "".ipsum; +} diff --git a/src/test/ui/issue-33525.stderr b/src/test/ui/issue-33525.stderr new file mode 100644 index 00000000000..5de2d98f86a --- /dev/null +++ b/src/test/ui/issue-33525.stderr @@ -0,0 +1,20 @@ +error[E0425]: cannot find value `a` in this scope + --> $DIR/issue-33525.rs:12:5 + | +12 | a; + | ^ not found in this scope + +error[E0609]: no field `lorem` on type `&'static str` + --> $DIR/issue-33525.rs:13:8 + | +13 | "".lorem; + | ^^^^^ + +error[E0609]: no field `ipsum` on type `&'static str` + --> $DIR/issue-33525.rs:14:8 + | +14 | "".ipsum; + | ^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/issue-37311-type-length-limit/issue-37311.stderr b/src/test/ui/issue-37311-type-length-limit/issue-37311.stderr index 62223c553e3..b51b683a1ac 100644 --- a/src/test/ui/issue-37311-type-length-limit/issue-37311.stderr +++ b/src/test/ui/issue-37311-type-length-limit/issue-37311.stderr @@ -8,5 +8,5 @@ error: reached the type-length limit while instantiating `<(&(&(&(&(&( | = note: consider adding a `#![type_length_limit="2097152"]` attribute to your crate -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/issue-38875/issue_38875.stderr b/src/test/ui/issue-38875/issue_38875.stderr index ceed83d9313..10bb61ee22a 100644 --- a/src/test/ui/issue-38875/issue_38875.stderr +++ b/src/test/ui/issue-38875/issue_38875.stderr @@ -10,5 +10,5 @@ note: for repeat count here 16 | let test_x = [0; issue_38875_b::FOO]; | ^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr b/src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr index 80f608c1d37..de110ac12b7 100644 --- a/src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr +++ b/src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr @@ -7,5 +7,5 @@ error[E0507]: cannot move out of indexed content | help: consider using a reference instead `&f.v[0]` | cannot move out of indexed content -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/issue-40402-ref-hints/issue-40402-2.stderr b/src/test/ui/issue-40402-ref-hints/issue-40402-2.stderr index d35800ac1e7..0060b683bba 100644 --- a/src/test/ui/issue-40402-ref-hints/issue-40402-2.stderr +++ b/src/test/ui/issue-40402-ref-hints/issue-40402-2.stderr @@ -7,5 +7,5 @@ error[E0507]: cannot move out of indexed content | | ...and here (use `ref b` or `ref mut b`) | hint: to prevent move, use `ref a` or `ref mut a` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/issue-41652/issue_41652.stderr b/src/test/ui/issue-41652/issue_41652.stderr index b7b1ddb7b88..8a55c9989e1 100644 --- a/src/test/ui/issue-41652/issue_41652.stderr +++ b/src/test/ui/issue-41652/issue_41652.stderr @@ -13,5 +13,5 @@ note: candidate #1 is defined in the trait `issue_41652_b::Tr` | |__________________________^ = help: to disambiguate the method call, write `issue_41652_b::Tr::f(3)` instead -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.rs new file mode 100644 index 00000000000..a1716c4e797 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.rs @@ -0,0 +1,15 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { + if x > y { x } else { y } +} + +fn main() { } diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr new file mode 100644 index 00000000000..83716b7791d --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr @@ -0,0 +1,10 @@ +error[E0621]: explicit lifetime required in the type of `x` + --> $DIR/ex1-return-one-existing-name-if-else-2.rs:12:16 + | +11 | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { + | - consider changing the type of `x` to `&'a i32` +12 | if x > y { x } else { y } + | ^ lifetime `'a` required + +error: aborting due to previous error + diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.rs new file mode 100644 index 00000000000..7bd32d87617 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.rs @@ -0,0 +1,15 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn foo<'a>((x, y): (&'a i32, &i32)) -> &'a i32 { + if x > y { x } else { y } +} + +fn main () { } diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr new file mode 100644 index 00000000000..6d5e94a5e78 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr @@ -0,0 +1,10 @@ +error[E0621]: explicit lifetime required in parameter type + --> $DIR/ex1-return-one-existing-name-if-else-3.rs:12:27 + | +11 | fn foo<'a>((x, y): (&'a i32, &i32)) -> &'a i32 { + | ------ consider changing type to `(&'a i32, &'a i32)` +12 | if x > y { x } else { y } + | ^ lifetime `'a` required + +error: aborting due to previous error + diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.rs new file mode 100644 index 00000000000..8849f7084b3 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.rs @@ -0,0 +1,18 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Foo { + +fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { + if x > y { x } else { y } + } +} + +fn main() { } diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr new file mode 100644 index 00000000000..4288fdf89a4 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr @@ -0,0 +1,10 @@ +error[E0621]: explicit lifetime required in the type of `x` + --> $DIR/ex1-return-one-existing-name-if-else-using-impl-2.rs:14:15 + | +13 | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { + | - consider changing the type of `x` to `&'a i32` +14 | if x > y { x } else { y } + | ^ lifetime `'a` required + +error: aborting due to previous error + diff --git a/src/test/compile-fail/variance-region-bounds.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs similarity index 60% rename from src/test/compile-fail/variance-region-bounds.rs rename to src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs index 41d204a541b..362290ff3fa 100644 --- a/src/test/compile-fail/variance-region-bounds.rs +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,18 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Check that `T:'a` is contravariant in T. - -#![feature(rustc_attrs)] - -#[rustc_variance] -trait Foo: 'static { //~ ERROR [o] +struct Foo { + field: i32 } -#[rustc_variance] -trait Bar { //~ ERROR [o, o] - fn do_it(&self) - where T: 'static; +impl Foo { + fn foo<'a>(&'a self, x: &i32) -> &i32 { + + if true { &self.field } else { x } + + } + } fn main() { } diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr new file mode 100644 index 00000000000..95076bfbdc7 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr @@ -0,0 +1,11 @@ +error[E0621]: explicit lifetime required in the type of `x` + --> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:18:36 + | +16 | fn foo<'a>(&'a self, x: &i32) -> &i32 { + | - consider changing the type of `x` to `&'a i32` +17 | +18 | if true { &self.field } else { x } + | ^ lifetime `'a` required + +error: aborting due to previous error + diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.rs new file mode 100644 index 00000000000..36d956a3996 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Foo { + + fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32; + +} + +impl Foo for () { + + fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { + + if x > y { x } else { y } + + } + +} + +fn main() {} 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 new file mode 100644 index 00000000000..9e4f6c42179 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr @@ -0,0 +1,27 @@ +error[E0312]: lifetime of reference outlives lifetime of borrowed content... + --> $DIR/ex1-return-one-existing-name-if-else-using-impl.rs:21: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 | | } + | |_____^ + +error: aborting due to previous error + diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr index 0ab24b0b3e6..5d1336c7c3a 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr @@ -1,23 +1,10 @@ -error[E0312]: lifetime of reference outlives lifetime of borrowed content... +error[E0621]: explicit lifetime required in the type of `y` --> $DIR/ex1-return-one-existing-name-if-else.rs:12:27 | +11 | fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { + | - consider changing the type of `y` to `&'a i32` 12 | if x > y { x } else { y } - | ^ - | -note: ...the reference is valid for the lifetime 'a as defined on the function body at 11:1... - --> $DIR/ex1-return-one-existing-name-if-else.rs:11:1 - | -11 | / fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { -12 | | if x > y { x } else { y } -13 | | } - | |_^ -note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the function body at 11:1 - --> $DIR/ex1-return-one-existing-name-if-else.rs:11:1 - | -11 | / fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { -12 | | if x > y { x } else { y } -13 | | } - | |_^ + | ^ lifetime `'a` required -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.rs new file mode 100644 index 00000000000..96b733be9b4 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.rs @@ -0,0 +1,24 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Foo { + field: i32 +} + +impl Foo { + fn foo<'a>(&self, x: &'a i32) -> &i32 { + + x + + } + +} + +fn main() { } 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 new file mode 100644 index 00000000000..e3fd0192053 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr @@ -0,0 +1,27 @@ +error[E0312]: lifetime of reference outlives lifetime of borrowed content... + --> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:18:5 + | +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 | | } + | |___^ + +error: aborting due to previous error + diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.rs new file mode 100644 index 00000000000..a8ce60c47b6 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.rs @@ -0,0 +1,23 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Foo { + field: i32, +} + +impl Foo { + fn foo<'a>(&self, x: &'a Foo) -> &'a Foo { + + if true { x } else { self } + + } +} + +fn main() {} 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 new file mode 100644 index 00000000000..8551f015db5 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr @@ -0,0 +1,27 @@ +error[E0312]: lifetime of reference outlives lifetime of borrowed content... + --> $DIR/ex1-return-one-existing-name-self-is-anon.rs:18:30 + | +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 | | } + | |_____^ + +error: aborting due to previous error + diff --git a/src/test/ui/lifetime-errors/ex1b-return-no-names-if-else.stderr b/src/test/ui/lifetime-errors/ex1b-return-no-names-if-else.stderr index d005eeb4045..fccc44caac8 100644 --- a/src/test/ui/lifetime-errors/ex1b-return-no-names-if-else.stderr +++ b/src/test/ui/lifetime-errors/ex1b-return-no-names-if-else.stderr @@ -6,5 +6,5 @@ error[E0106]: missing lifetime specifier | = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.rs b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.rs new file mode 100644 index 00000000000..dd34e1aa6d9 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.rs @@ -0,0 +1,19 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Ref<'a, T: 'a> { + data: &'a T +} + +fn foo<'a>(x: Ref, y: &mut Vec>) { + y.push(x); +} + +fn main() { } diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.stderr b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.stderr new file mode 100644 index 00000000000..8dba0c33f20 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.stderr @@ -0,0 +1,10 @@ +error[E0621]: explicit lifetime required in the type of `x` + --> $DIR/ex2a-push-one-existing-name-2.rs:16:12 + | +15 | fn foo<'a>(x: Ref, y: &mut Vec>) { + | - consider changing the type of `x` to `Ref<'a, i32>` +16 | y.push(x); + | ^ lifetime `'a` required + +error: aborting due to previous error + diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr index 7d0947b364e..e529d6ffe46 100644 --- a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr +++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr @@ -1,25 +1,10 @@ -error[E0308]: mismatched types +error[E0621]: explicit lifetime required in the type of `y` --> $DIR/ex2a-push-one-existing-name.rs:16:12 | +15 | fn foo<'a>(x: &mut Vec>, y: Ref) { + | - consider changing the type of `y` to `Ref<'a, i32>` 16 | x.push(y); - | ^ lifetime mismatch - | - = note: expected type `Ref<'a, _>` - found type `Ref<'_, _>` -note: the anonymous lifetime #2 defined on the function body at 15:1... - --> $DIR/ex2a-push-one-existing-name.rs:15:1 - | -15 | / fn foo<'a>(x: &mut Vec>, y: Ref) { -16 | | x.push(y); -17 | | } - | |_^ -note: ...does not necessarily outlive the lifetime 'a as defined on the function body at 15:1 - --> $DIR/ex2a-push-one-existing-name.rs:15:1 - | -15 | / fn foo<'a>(x: &mut Vec>, y: Ref) { -16 | | x.push(y); -17 | | } - | |_^ + | ^ lifetime `'a` required -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr b/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr index 6380a885f44..6764c58f4bb 100644 --- a/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr +++ b/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr @@ -21,5 +21,5 @@ note: ...does not necessarily outlive the anonymous lifetime #2 defined on the f 17 | | } | |_^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr b/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr index b28a3c0c135..7356fc11862 100644 --- a/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr +++ b/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr @@ -31,5 +31,5 @@ note: ...so that expression is assignable (expected Ref<'b, _>, found Ref<'_, _> 17 | x.push(z); | ^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr b/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr index dd716bac513..38b0acf9339 100644 --- a/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr +++ b/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr @@ -33,5 +33,5 @@ note: ...so that expression is assignable (expected &mut std::vec::Vec> = x; | ^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr b/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr index 141f5a7c452..035e516e862 100644 --- a/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr +++ b/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr @@ -33,5 +33,5 @@ note: ...so that expression is assignable (expected &mut std::vec::Vec> = x; | ^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lifetimes/borrowck-let-suggestion.stderr b/src/test/ui/lifetimes/borrowck-let-suggestion.stderr index 2bc0acd626c..d1ba9246588 100644 --- a/src/test/ui/lifetimes/borrowck-let-suggestion.stderr +++ b/src/test/ui/lifetimes/borrowck-let-suggestion.stderr @@ -10,5 +10,5 @@ error[E0597]: borrowed value does not live long enough | = note: consider using a `let` binding to increase its lifetime -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lint/command-line-lint-group-deny.stderr b/src/test/ui/lint/command-line-lint-group-deny.stderr index d441702374b..23fac66cc6c 100644 --- a/src/test/ui/lint/command-line-lint-group-deny.stderr +++ b/src/test/ui/lint/command-line-lint-group-deny.stderr @@ -6,5 +6,5 @@ error: variable `_InappropriateCamelCasing` should have a snake case name such a | = note: `-D non-snake-case` implied by `-D bad-style` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lint/command-line-lint-group-forbid.stderr b/src/test/ui/lint/command-line-lint-group-forbid.stderr index 9d4d0b12b18..0babd7f6fe4 100644 --- a/src/test/ui/lint/command-line-lint-group-forbid.stderr +++ b/src/test/ui/lint/command-line-lint-group-forbid.stderr @@ -6,5 +6,5 @@ error: variable `_InappropriateCamelCasing` should have a snake case name such a | = note: `-F non-snake-case` implied by `-F bad-style` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lint/lint-group-style.stderr b/src/test/ui/lint/lint-group-style.stderr index dec44c317e4..862e94b873a 100644 --- a/src/test/ui/lint/lint-group-style.stderr +++ b/src/test/ui/lint/lint-group-style.stderr @@ -4,12 +4,12 @@ error: function `CamelCase` should have a snake case name such as `camel_case` 14 | fn CamelCase() {} | ^^^^^^^^^^^^^^^^^ | - = note: #[deny(non_snake_case)] implied by #[deny(bad_style)] note: lint level defined here --> $DIR/lint-group-style.rs:11:9 | 11 | #![deny(bad_style)] | ^^^^^^^^^ + = note: #[deny(non_snake_case)] implied by #[deny(bad_style)] error: function `CamelCase` should have a snake case name such as `camel_case` --> $DIR/lint-group-style.rs:22:9 @@ -17,12 +17,12 @@ error: function `CamelCase` should have a snake case name such as `camel_case` 22 | fn CamelCase() {} | ^^^^^^^^^^^^^^^^^ | - = note: #[forbid(non_snake_case)] implied by #[forbid(bad_style)] note: lint level defined here --> $DIR/lint-group-style.rs:20:14 | 20 | #[forbid(bad_style)] | ^^^^^^^^^ + = note: #[forbid(non_snake_case)] implied by #[forbid(bad_style)] error: static variable `bad` should have an upper case name such as `BAD` --> $DIR/lint-group-style.rs:24:9 @@ -30,12 +30,12 @@ error: static variable `bad` should have an upper case name such as `BAD` 24 | static bad: isize = 1; | ^^^^^^^^^^^^^^^^^^^^^^ | - = note: #[forbid(non_upper_case_globals)] implied by #[forbid(bad_style)] note: lint level defined here --> $DIR/lint-group-style.rs:20:14 | 20 | #[forbid(bad_style)] | ^^^^^^^^^ + = note: #[forbid(non_upper_case_globals)] implied by #[forbid(bad_style)] warning: function `CamelCase` should have a snake case name such as `camel_case` --> $DIR/lint-group-style.rs:30:9 @@ -43,12 +43,12 @@ warning: function `CamelCase` should have a snake case name such as `camel_case` 30 | fn CamelCase() {} | ^^^^^^^^^^^^^^^^^ | - = note: #[warn(non_snake_case)] implied by #[warn(bad_style)] note: lint level defined here --> $DIR/lint-group-style.rs:28:17 | 28 | #![warn(bad_style)] | ^^^^^^^^^ + = note: #[warn(non_snake_case)] implied by #[warn(bad_style)] warning: type `snake_case` should have a camel case name such as `SnakeCase` --> $DIR/lint-group-style.rs:32:9 @@ -56,12 +56,12 @@ warning: type `snake_case` should have a camel case name such as `SnakeCase` 32 | struct snake_case; | ^^^^^^^^^^^^^^^^^^ | - = note: #[warn(non_camel_case_types)] implied by #[warn(bad_style)] note: lint level defined here --> $DIR/lint-group-style.rs:28:17 | 28 | #![warn(bad_style)] | ^^^^^^^^^ + = note: #[warn(non_camel_case_types)] implied by #[warn(bad_style)] -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/lint/outer-forbid.rs b/src/test/ui/lint/outer-forbid.rs new file mode 100644 index 00000000000..d71da58829a --- /dev/null +++ b/src/test/ui/lint/outer-forbid.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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Forbidding a group (here, `unused`) overrules subsequent allowance of both +// the group, and an individual lint in the group (here, `unused_variables`); +// and, forbidding an individual lint (here, `non_snake_case`) overrules +// subsequent allowance of a lint group containing it (here, `bad_style`). See +// Issue #42873. + +#![forbid(unused, non_snake_case)] + +#[allow(unused, unused_variables, bad_style)] +fn main() { + println!("hello forbidden world") +} diff --git a/src/test/ui/lint/outer-forbid.stderr b/src/test/ui/lint/outer-forbid.stderr new file mode 100644 index 00000000000..df62f5acc00 --- /dev/null +++ b/src/test/ui/lint/outer-forbid.stderr @@ -0,0 +1,29 @@ +error[E0453]: allow(unused) overruled by outer forbid(unused) + --> $DIR/outer-forbid.rs:19:9 + | +17 | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +18 | +19 | #[allow(unused, unused_variables, bad_style)] + | ^^^^^^ overruled by previous forbid + +error[E0453]: allow(unused_variables) overruled by outer forbid(unused) + --> $DIR/outer-forbid.rs:19:17 + | +17 | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +18 | +19 | #[allow(unused, unused_variables, bad_style)] + | ^^^^^^^^^^^^^^^^ overruled by previous forbid + +error[E0453]: allow(bad_style) overruled by outer forbid(non_snake_case) + --> $DIR/outer-forbid.rs:19:35 + | +17 | #![forbid(unused, non_snake_case)] + | -------------- `forbid` level set here +18 | +19 | #[allow(unused, unused_variables, bad_style)] + | ^^^^^^^^^ overruled by previous forbid + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/loop-break-value-no-repeat.stderr b/src/test/ui/loop-break-value-no-repeat.stderr index 7a4a9c3f012..c154ea6f8c2 100644 --- a/src/test/ui/loop-break-value-no-repeat.stderr +++ b/src/test/ui/loop-break-value-no-repeat.stderr @@ -4,5 +4,5 @@ error[E0571]: `break` with value from a `for` loop 22 | break 22 | ^^^^^^^^ can only break with a value inside `loop` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/macros/bad_hello.stderr b/src/test/ui/macros/bad_hello.stderr index b8337c81834..bffb33f468f 100644 --- a/src/test/ui/macros/bad_hello.stderr +++ b/src/test/ui/macros/bad_hello.stderr @@ -4,5 +4,5 @@ error: expected a literal 12 | println!(3 + 4); | ^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/macros/format-foreign.stderr b/src/test/ui/macros/format-foreign.stderr index a964b92712d..0283052a89f 100644 --- a/src/test/ui/macros/format-foreign.stderr +++ b/src/test/ui/macros/format-foreign.stderr @@ -48,5 +48,5 @@ error: named argument never used = help: `$NAME` should be written as `{NAME}` = note: shell formatting not supported; see the documentation for `std::fmt` -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/macros/macro-backtrace-invalid-internals.stderr b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr index 5ed4ab4552a..0f0d6d8ded3 100644 --- a/src/test/ui/macros/macro-backtrace-invalid-internals.stderr +++ b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr @@ -52,5 +52,5 @@ error[E0613]: attempted to access tuple index `0` on type `{integer}`, but the t 56 | let _ = fake_anon_field_expr!(); | ----------------------- in this macro invocation -error: aborting due to previous error(s) +error: aborting due to 6 previous errors diff --git a/src/test/ui/macros/macro-backtrace-nested.stderr b/src/test/ui/macros/macro-backtrace-nested.stderr index 7835b85eafc..8b69d112d4d 100644 --- a/src/test/ui/macros/macro-backtrace-nested.stderr +++ b/src/test/ui/macros/macro-backtrace-nested.stderr @@ -16,5 +16,5 @@ error[E0425]: cannot find value `fake` in this scope 28 | call_nested_expr_sum!(); | ------------------------ in this macro invocation -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/macros/macro-backtrace-println.stderr b/src/test/ui/macros/macro-backtrace-println.stderr index 4177240d976..f21253bb67f 100644 --- a/src/test/ui/macros/macro-backtrace-println.stderr +++ b/src/test/ui/macros/macro-backtrace-println.stderr @@ -7,5 +7,5 @@ error: invalid reference to argument `0` (no arguments given) 28 | myprintln!("{}"); | ----------------- in this macro invocation -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/E0053.stderr b/src/test/ui/mismatched_types/E0053.stderr index 2ba2069677e..d9871b8970c 100644 --- a/src/test/ui/mismatched_types/E0053.stderr +++ b/src/test/ui/mismatched_types/E0053.stderr @@ -22,5 +22,5 @@ error[E0053]: method `bar` has an incompatible type for trait = note: expected type `fn(&Bar)` found type `fn(&mut Bar)` -error: aborting due to previous error(s) +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 index 3eb5c125789..887412d1be7 100644 --- a/src/test/ui/mismatched_types/E0281.stderr +++ b/src/test/ui/mismatched_types/E0281.stderr @@ -9,5 +9,5 @@ error[E0281]: type mismatch: `[closure@$DIR/E0281.rs:14:9: 14:24]` implements th | = note: required by `foo` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/E0409.stderr b/src/test/ui/mismatched_types/E0409.stderr index a5f63aca13e..cc7c0179070 100644 --- a/src/test/ui/mismatched_types/E0409.stderr +++ b/src/test/ui/mismatched_types/E0409.stderr @@ -15,5 +15,5 @@ error[E0308]: mismatched types = note: expected type `&{integer}` found type `{integer}` -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/mismatched_types/abridged.rs b/src/test/ui/mismatched_types/abridged.rs index c448ad955fa..03f889224be 100644 --- a/src/test/ui/mismatched_types/abridged.rs +++ b/src/test/ui/mismatched_types/abridged.rs @@ -39,23 +39,25 @@ fn c() -> Result { } fn d() -> X, String> { - X { + let x = X { x: X { x: "".to_string(), y: 2, }, y: 3, - } + }; + x } fn e() -> X, String> { - X { + let x = X { x: X { x: "".to_string(), y: 2, }, y: "".to_string(), - } + }; + x } fn main() {} diff --git a/src/test/ui/mismatched_types/abridged.stderr b/src/test/ui/mismatched_types/abridged.stderr index 78b5dcda1d9..d40bc3b3339 100644 --- a/src/test/ui/mismatched_types/abridged.stderr +++ b/src/test/ui/mismatched_types/abridged.stderr @@ -35,34 +35,22 @@ error[E0308]: mismatched types found type `Foo` error[E0308]: mismatched types - --> $DIR/abridged.rs:42:5 + --> $DIR/abridged.rs:49:5 | -42 | / X { -43 | | x: X { -44 | | x: "".to_string(), -45 | | y: 2, -46 | | }, -47 | | y: 3, -48 | | } - | |_____^ expected struct `std::string::String`, found integral variable +49 | x + | ^ expected struct `std::string::String`, found integral variable | = note: expected type `X, std::string::String>` found type `X, {integer}>` error[E0308]: mismatched types - --> $DIR/abridged.rs:52:5 + --> $DIR/abridged.rs:60:5 | -52 | / X { -53 | | x: X { -54 | | x: "".to_string(), -55 | | y: 2, -56 | | }, -57 | | y: "".to_string(), -58 | | } - | |_____^ expected struct `std::string::String`, found integral variable +60 | x + | ^ expected struct `std::string::String`, found integral variable | = note: expected type `X, _>` found type `X, _>` -error: aborting due to previous error(s) +error: aborting due to 6 previous errors diff --git a/src/test/ui/mismatched_types/binops.stderr b/src/test/ui/mismatched_types/binops.stderr index cebdc12f568..6d1a39e0d93 100644 --- a/src/test/ui/mismatched_types/binops.stderr +++ b/src/test/ui/mismatched_types/binops.stderr @@ -46,5 +46,5 @@ error[E0277]: the trait bound `{integer}: std::cmp::PartialEq>` is not implemented for `{integer}` -error: aborting due to previous error(s) +error: aborting due to 6 previous errors diff --git a/src/test/ui/mismatched_types/cast-rfc0401.stderr b/src/test/ui/mismatched_types/cast-rfc0401.stderr index 58cd130dcc2..fb363c388b6 100644 --- a/src/test/ui/mismatched_types/cast-rfc0401.stderr +++ b/src/test/ui/mismatched_types/cast-rfc0401.stderr @@ -1,4 +1,4 @@ -error: casting `*const U` as `*const V` is invalid +error[E0606]: casting `*const U` as `*const V` is invalid --> $DIR/cast-rfc0401.rs:13:5 | 13 | u as *const V @@ -6,7 +6,7 @@ error: casting `*const U` as `*const V` is invalid | = note: vtable kinds may not match -error: casting `*const U` as `*const str` is invalid +error[E0606]: casting `*const U` as `*const str` is invalid --> $DIR/cast-rfc0401.rs:18:5 | 18 | u as *const str @@ -20,49 +20,59 @@ error[E0609]: no field `f` on type `fn() {main}` 75 | let _ = main.f as *const u32; | ^ -error: non-scalar cast: `*const u8` as `&u8` +error[E0605]: non-primitive cast: `*const u8` as `&u8` --> $DIR/cast-rfc0401.rs:39:13 | 39 | let _ = v as &u8; | ^^^^^^^^ + | + = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait -error: non-scalar cast: `*const u8` as `E` +error[E0605]: non-primitive cast: `*const u8` as `E` --> $DIR/cast-rfc0401.rs:40:13 | 40 | let _ = v as E; | ^^^^^^ + | + = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait -error: non-scalar cast: `*const u8` as `fn()` +error[E0605]: non-primitive cast: `*const u8` as `fn()` --> $DIR/cast-rfc0401.rs:41:13 | 41 | let _ = v as fn(); | ^^^^^^^^^ + | + = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait -error: non-scalar cast: `*const u8` as `(u32,)` +error[E0605]: non-primitive cast: `*const u8` as `(u32,)` --> $DIR/cast-rfc0401.rs:42:13 | 42 | let _ = v as (u32,); | ^^^^^^^^^^^ + | + = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait -error: non-scalar cast: `std::option::Option<&*const u8>` as `*const u8` +error[E0605]: non-primitive cast: `std::option::Option<&*const u8>` as `*const u8` --> $DIR/cast-rfc0401.rs:43:13 | 43 | let _ = Some(&v) as *const u8; | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait -error: casting `*const u8` as `f32` is invalid +error[E0606]: casting `*const u8` as `f32` is invalid --> $DIR/cast-rfc0401.rs:45:13 | 45 | let _ = v as f32; | ^^^^^^^^ -error: casting `fn() {main}` as `f64` is invalid +error[E0606]: casting `fn() {main}` as `f64` is invalid --> $DIR/cast-rfc0401.rs:46:13 | 46 | let _ = main as f64; | ^^^^^^^^^^^ -error: casting `&*const u8` as `usize` is invalid +error[E0606]: casting `&*const u8` as `usize` is invalid --> $DIR/cast-rfc0401.rs:47:13 | 47 | let _ = &v as usize; @@ -70,7 +80,7 @@ error: casting `&*const u8` as `usize` is invalid | = help: cast through a raw pointer first -error: casting `f32` as `*const u8` is invalid +error[E0606]: casting `f32` as `*const u8` is invalid --> $DIR/cast-rfc0401.rs:48:13 | 48 | let _ = f as *const u8; @@ -92,13 +102,13 @@ error[E0054]: cannot cast as `bool` | = help: compare with zero instead -error: only `u8` can be cast as `char`, not `u32` +error[E0604]: only `u8` can be cast as `char`, not `u32` --> $DIR/cast-rfc0401.rs:51:13 | 51 | let _ = 0x61u32 as char; | ^^^^^^^^^^^^^^^ -error: casting `bool` as `f32` is invalid +error[E0606]: casting `bool` as `f32` is invalid --> $DIR/cast-rfc0401.rs:53:13 | 53 | let _ = false as f32; @@ -106,7 +116,7 @@ error: casting `bool` as `f32` is invalid | = help: cast through an integer first -error: casting `E` as `f32` is invalid +error[E0606]: casting `E` as `f32` is invalid --> $DIR/cast-rfc0401.rs:54:13 | 54 | let _ = E::A as f32; @@ -114,7 +124,7 @@ error: casting `E` as `f32` is invalid | = help: cast through an integer first -error: casting `char` as `f32` is invalid +error[E0606]: casting `char` as `f32` is invalid --> $DIR/cast-rfc0401.rs:55:13 | 55 | let _ = 'a' as f32; @@ -122,67 +132,67 @@ error: casting `char` as `f32` is invalid | = help: cast through an integer first -error: casting `bool` as `*const u8` is invalid +error[E0606]: casting `bool` as `*const u8` is invalid --> $DIR/cast-rfc0401.rs:57:13 | 57 | let _ = false as *const u8; | ^^^^^^^^^^^^^^^^^^ -error: casting `E` as `*const u8` is invalid +error[E0606]: casting `E` as `*const u8` is invalid --> $DIR/cast-rfc0401.rs:58:13 | 58 | let _ = E::A as *const u8; | ^^^^^^^^^^^^^^^^^ -error: casting `char` as `*const u8` is invalid +error[E0606]: casting `char` as `*const u8` is invalid --> $DIR/cast-rfc0401.rs:59:13 | 59 | let _ = 'a' as *const u8; | ^^^^^^^^^^^^^^^^ -error: casting `usize` as `*const [u8]` is invalid +error[E0606]: casting `usize` as `*const [u8]` is invalid --> $DIR/cast-rfc0401.rs:61:13 | 61 | let _ = 42usize as *const [u8]; | ^^^^^^^^^^^^^^^^^^^^^^ -error: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]` +error[E0607]: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]` --> $DIR/cast-rfc0401.rs:62:13 | 62 | let _ = v as *const [u8]; | ^^^^^^^^^^^^^^^^ -error: casting `&Foo` as `*const str` is invalid +error[E0606]: casting `&Foo` as `*const str` is invalid --> $DIR/cast-rfc0401.rs:64:13 | 64 | let _ = foo as *const str; | ^^^^^^^^^^^^^^^^^ -error: casting `&Foo` as `*mut str` is invalid +error[E0606]: casting `&Foo` as `*mut str` is invalid --> $DIR/cast-rfc0401.rs:65:13 | 65 | let _ = foo as *mut str; | ^^^^^^^^^^^^^^^ -error: casting `fn() {main}` as `*mut str` is invalid +error[E0606]: casting `fn() {main}` as `*mut str` is invalid --> $DIR/cast-rfc0401.rs:66:13 | 66 | let _ = main as *mut str; | ^^^^^^^^^^^^^^^^ -error: casting `&f32` as `*mut f32` is invalid +error[E0606]: casting `&f32` as `*mut f32` is invalid --> $DIR/cast-rfc0401.rs:67:13 | 67 | let _ = &f as *mut f32; | ^^^^^^^^^^^^^^ -error: casting `&f32` as `*const f64` is invalid +error[E0606]: casting `&f32` as `*const f64` is invalid --> $DIR/cast-rfc0401.rs:68:13 | 68 | let _ = &f as *const f64; | ^^^^^^^^^^^^^^^^ -error: casting `*const [i8]` as `usize` is invalid +error[E0606]: casting `*const [i8]` as `usize` is invalid --> $DIR/cast-rfc0401.rs:69:13 | 69 | let _ = fat_sv as usize; @@ -190,7 +200,7 @@ error: casting `*const [i8]` as `usize` is invalid | = help: cast through a thin pointer first -error: casting `*const Foo` as `*const [u16]` is invalid +error[E0606]: casting `*const Foo` as `*const [u16]` is invalid --> $DIR/cast-rfc0401.rs:78:13 | 78 | let _ = cf as *const [u16]; @@ -198,7 +208,7 @@ error: casting `*const Foo` as `*const [u16]` is invalid | = note: vtable kinds may not match -error: casting `*const Foo` as `*const Bar` is invalid +error[E0606]: casting `*const Foo` as `*const Bar` is invalid --> $DIR/cast-rfc0401.rs:79:13 | 79 | let _ = cf as *const Bar; @@ -224,7 +234,7 @@ error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied = help: the trait `std::marker::Sized` is not implemented for `str` = note: required for the cast to the object type `Foo` -error: casting `&{float}` as `f32` is invalid +error[E0606]: casting `&{float}` as `f32` is invalid --> $DIR/cast-rfc0401.rs:81:30 | 81 | vec![0.0].iter().map(|s| s as f32).collect::>(); @@ -236,5 +246,5 @@ help: did you mean `*s`? 81 | vec![0.0].iter().map(|s| s as f32).collect::>(); | ^ -error: aborting due to previous error(s) +error: aborting due to 34 previous errors diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr index 85734dfac70..ca71154e872 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.stderr +++ b/src/test/ui/mismatched_types/closure-arg-count.stderr @@ -31,5 +31,5 @@ error[E0593]: closure takes 1 argument but 2 arguments are required | | | expected closure that takes 2 arguments -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr index 2c9c918168d..5b3eb593189 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-mismatch.stderr @@ -20,5 +20,5 @@ error[E0281]: type mismatch: `[closure@$DIR/closure-mismatch.rs:18:9: 18:15]` im = 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: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/mismatched_types/const-fn-in-trait.stderr b/src/test/ui/mismatched_types/const-fn-in-trait.stderr index 5f67a66eb32..f7b7635e41a 100644 --- a/src/test/ui/mismatched_types/const-fn-in-trait.stderr +++ b/src/test/ui/mismatched_types/const-fn-in-trait.stderr @@ -10,5 +10,5 @@ error[E0379]: trait fns cannot be declared const 21 | const fn f() -> u32 { 22 } | ^^^^^ trait fns cannot be const -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/mismatched_types/fn-variance-1.stderr b/src/test/ui/mismatched_types/fn-variance-1.stderr index 2030ad6c13b..120fb87cdc8 100644 --- a/src/test/ui/mismatched_types/fn-variance-1.stderr +++ b/src/test/ui/mismatched_types/fn-variance-1.stderr @@ -14,5 +14,5 @@ error[E0281]: type mismatch: `fn(&isize) {takes_imm}` implements the trait `for< | = note: required by `apply` -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/compile-fail/for-loop-has-unit-body.rs b/src/test/ui/mismatched_types/for-loop-has-unit-body.rs similarity index 100% rename from src/test/compile-fail/for-loop-has-unit-body.rs rename to src/test/ui/mismatched_types/for-loop-has-unit-body.rs diff --git a/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr b/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr new file mode 100644 index 00000000000..4a619804a6c --- /dev/null +++ b/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/for-loop-has-unit-body.rs:13:9 + | +13 | x //~ ERROR mismatched types + | ^ expected (), found integral variable + | + = note: expected type `()` + found type `{integer}` + +error: aborting due to previous error + diff --git a/src/test/ui/mismatched_types/issue-19109.stderr b/src/test/ui/mismatched_types/issue-19109.stderr index cbce4f810c5..2b4b8242af6 100644 --- a/src/test/ui/mismatched_types/issue-19109.stderr +++ b/src/test/ui/mismatched_types/issue-19109.stderr @@ -1,11 +1,13 @@ error[E0308]: mismatched types --> $DIR/issue-19109.rs:14:5 | +13 | fn function(t: &mut Trait) { + | - help: possibly return type missing here? `-> *mut Trait ` 14 | t as *mut Trait | ^^^^^^^^^^^^^^^ expected (), found *-ptr | = note: expected type `()` found type `*mut Trait` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/issue-26480.stderr b/src/test/ui/mismatched_types/issue-26480.stderr index dc3764a376c..fae831ffb86 100644 --- a/src/test/ui/mismatched_types/issue-26480.stderr +++ b/src/test/ui/mismatched_types/issue-26480.stderr @@ -7,7 +7,7 @@ error[E0308]: mismatched types 37 | write!(hello); | -------------- in this macro invocation -error: non-scalar cast: `{integer}` as `()` +error[E0605]: non-primitive cast: `{integer}` as `()` --> $DIR/issue-26480.rs:32:19 | 32 | ($x:expr) => ($x as ()) @@ -15,6 +15,8 @@ error: non-scalar cast: `{integer}` as `()` ... 38 | cast!(2); | --------- in this macro invocation + | + = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/mismatched_types/issue-35030.stderr b/src/test/ui/mismatched_types/issue-35030.stderr index 463d9fdf171..46d690c5f03 100644 --- a/src/test/ui/mismatched_types/issue-35030.stderr +++ b/src/test/ui/mismatched_types/issue-35030.stderr @@ -7,5 +7,5 @@ error[E0308]: mismatched types = note: expected type `bool` (type parameter) found type `bool` (bool) -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index f818bd8bcb1..51acdb719b6 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -17,5 +17,5 @@ error[E0281]: type mismatch: `[closure@$DIR/issue-36053-2.rs:17:39: 17:53]` impl | requires `for<'r> std::ops::FnMut<(&'r &str,)>` | expected &str, found str -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/mismatched_types/issue-38371.stderr b/src/test/ui/mismatched_types/issue-38371.stderr index 76ffa6e50e1..9efee4cc559 100644 --- a/src/test/ui/mismatched_types/issue-38371.stderr +++ b/src/test/ui/mismatched_types/issue-38371.stderr @@ -32,5 +32,5 @@ error[E0529]: expected an array or slice, found `u32` 34 | fn ugh(&[bar]: &u32) { | ^^^^^ pattern cannot match with input type `u32` -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/mismatched_types/main.stderr b/src/test/ui/mismatched_types/main.stderr index b4e688e025e..c8941fbf950 100644 --- a/src/test/ui/mismatched_types/main.stderr +++ b/src/test/ui/mismatched_types/main.stderr @@ -9,5 +9,5 @@ error[E0308]: mismatched types = note: expected type `u32` found type `()` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr index 80f95da0bbe..ab5b3e17915 100644 --- a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr +++ b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr @@ -7,5 +7,5 @@ error[E0599]: no method named `unwrap` found for type `std::result::Result<(), F = note: the method `unwrap` exists but the following trait bounds were not satisfied: `Foo : std::fmt::Debug` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/overloaded-calls-bad.stderr b/src/test/ui/mismatched_types/overloaded-calls-bad.stderr index 7c644e3a72d..cd05684f15d 100644 --- a/src/test/ui/mismatched_types/overloaded-calls-bad.stderr +++ b/src/test/ui/mismatched_types/overloaded-calls-bad.stderr @@ -19,5 +19,5 @@ error[E0057]: this function takes 1 parameter but 2 parameters were supplied 45 | let ans = s("burma", "shave"); | ^^^^^^^^^^^^^^^^ expected 1 parameter -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/mismatched_types/trait-bounds-cant-coerce.stderr b/src/test/ui/mismatched_types/trait-bounds-cant-coerce.stderr index 9e7f79df35a..ccc9fb56772 100644 --- a/src/test/ui/mismatched_types/trait-bounds-cant-coerce.stderr +++ b/src/test/ui/mismatched_types/trait-bounds-cant-coerce.stderr @@ -7,5 +7,5 @@ error[E0308]: mismatched types = note: expected type `std::boxed::Box` found type `std::boxed::Box` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr b/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr index 8741589f846..349432f64bb 100644 --- a/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr +++ b/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr @@ -22,5 +22,5 @@ error[E0053]: method `bar` has an incompatible type for trait = note: expected type `fn(&mut Bar, &mut Bar)` found type `fn(&mut Bar, &Bar)` -error: aborting due to previous error(s) +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 643c9b36dbd..995a1258454 100644 --- a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr +++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr @@ -12,5 +12,5 @@ error[E0281]: type mismatch: `[closure@$DIR/unboxed-closures-vtable-mismatch.rs: | = note: required by `call_it` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/missing-items/issue-40221.stderr b/src/test/ui/missing-items/issue-40221.stderr index 87854493790..fc90c8a2b20 100644 --- a/src/test/ui/missing-items/issue-40221.stderr +++ b/src/test/ui/missing-items/issue-40221.stderr @@ -4,5 +4,5 @@ error[E0004]: non-exhaustive patterns: `C(QA)` not covered 21 | match proto { | ^^^^^ pattern `C(QA)` not covered -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/missing-items/m2.stderr b/src/test/ui/missing-items/m2.stderr index 2d699c66359..51afb95b896 100644 --- a/src/test/ui/missing-items/m2.stderr +++ b/src/test/ui/missing-items/m2.stderr @@ -11,5 +11,5 @@ error[E0046]: not all trait items implemented, missing: `CONSTANT`, `Type`, `met = note: `Type` from trait: `type Type;` = note: `method` from trait: `fn(&Self, std::string::String) -> ::Type` -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/missing-items/missing-type-parameter.stderr b/src/test/ui/missing-items/missing-type-parameter.stderr index ce38178bf87..a16ae5538bf 100644 --- a/src/test/ui/missing-items/missing-type-parameter.stderr +++ b/src/test/ui/missing-items/missing-type-parameter.stderr @@ -4,5 +4,5 @@ error[E0282]: type annotations needed 14 | foo(); | ^^^ cannot infer type for `X` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/path-lookahead.stderr b/src/test/ui/path-lookahead.stderr index 1e19977e84a..8fd1b8de687 100644 --- a/src/test/ui/path-lookahead.stderr +++ b/src/test/ui/path-lookahead.stderr @@ -23,6 +23,4 @@ warning: function is never used: `no_parens` 20 | | return ::to_string(&arg); 21 | | } | |_^ - | - = note: #[warn(dead_code)] on by default diff --git a/src/test/ui/pub/pub-restricted-error-fn.stderr b/src/test/ui/pub/pub-restricted-error-fn.stderr index 94fc8f15c2b..470e8331247 100644 --- a/src/test/ui/pub/pub-restricted-error-fn.stderr +++ b/src/test/ui/pub/pub-restricted-error-fn.stderr @@ -4,5 +4,5 @@ error: unmatched visibility `pub` 13 | pub(crate) () fn foo() {} | ^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/pub/pub-restricted-error.stderr b/src/test/ui/pub/pub-restricted-error.stderr index eebb2428ba3..b8b4c80778d 100644 --- a/src/test/ui/pub/pub-restricted-error.stderr +++ b/src/test/ui/pub/pub-restricted-error.stderr @@ -4,5 +4,5 @@ error: expected identifier, found `(` 16 | pub(crate) () foo: usize, | ^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/pub/pub-restricted-non-path.stderr b/src/test/ui/pub/pub-restricted-non-path.stderr index 865b1d409e1..ebfccc4d720 100644 --- a/src/test/ui/pub/pub-restricted-non-path.stderr +++ b/src/test/ui/pub/pub-restricted-non-path.stderr @@ -4,5 +4,5 @@ error: expected identifier, found `.` 13 | pub (.) fn afn() {} | ^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/pub/pub-restricted.stderr b/src/test/ui/pub/pub-restricted.stderr index 34cc80fcc75..ae283f1fb63 100644 --- a/src/test/ui/pub/pub-restricted.stderr +++ b/src/test/ui/pub/pub-restricted.stderr @@ -48,5 +48,5 @@ error: visibilities can only be restricted to ancestor modules 33 | pub (in x) non_parent_invalid: usize, | ^ -error: aborting due to previous error(s) +error: aborting due to 5 previous errors diff --git a/src/test/ui/reachable/expr_add.stderr b/src/test/ui/reachable/expr_add.stderr index cbcbf88d86e..1a2cc252051 100644 --- a/src/test/ui/reachable/expr_add.stderr +++ b/src/test/ui/reachable/expr_add.stderr @@ -10,5 +10,5 @@ note: lint level defined here 13 | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_again.stderr b/src/test/ui/reachable/expr_again.stderr index 20640c0a897..bf4e4dc4711 100644 --- a/src/test/ui/reachable/expr_again.stderr +++ b/src/test/ui/reachable/expr_again.stderr @@ -11,5 +11,5 @@ note: lint level defined here | ^^^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_array.stderr b/src/test/ui/reachable/expr_array.stderr index c778aec0810..f8dbdb5f8bb 100644 --- a/src/test/ui/reachable/expr_array.stderr +++ b/src/test/ui/reachable/expr_array.stderr @@ -16,5 +16,5 @@ error: unreachable expression 25 | let x: [usize; 2] = [22, return]; | ^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/reachable/expr_assign.stderr b/src/test/ui/reachable/expr_assign.stderr index 9310c000192..807f6a1c1d5 100644 --- a/src/test/ui/reachable/expr_assign.stderr +++ b/src/test/ui/reachable/expr_assign.stderr @@ -22,5 +22,5 @@ error: unreachable expression 36 | *{return; &mut i} = 22; | ^^^^^^ -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/reachable/expr_block.stderr b/src/test/ui/reachable/expr_block.stderr index ea7b962e190..542ce1c3fd9 100644 --- a/src/test/ui/reachable/expr_block.stderr +++ b/src/test/ui/reachable/expr_block.stderr @@ -18,5 +18,5 @@ error: unreachable statement | = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/reachable/expr_box.stderr b/src/test/ui/reachable/expr_box.stderr index ee89104df9e..78ba231cef9 100644 --- a/src/test/ui/reachable/expr_box.stderr +++ b/src/test/ui/reachable/expr_box.stderr @@ -10,5 +10,5 @@ note: lint level defined here 13 | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_call.stderr b/src/test/ui/reachable/expr_call.stderr index 5e072ed1dc7..5526827f59f 100644 --- a/src/test/ui/reachable/expr_call.stderr +++ b/src/test/ui/reachable/expr_call.stderr @@ -16,5 +16,5 @@ error: unreachable expression 28 | bar(return); | ^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/reachable/expr_cast.stderr b/src/test/ui/reachable/expr_cast.stderr index a8668dc7355..a22300dcc13 100644 --- a/src/test/ui/reachable/expr_cast.stderr +++ b/src/test/ui/reachable/expr_cast.stderr @@ -10,5 +10,5 @@ note: lint level defined here 14 | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_if.stderr b/src/test/ui/reachable/expr_if.stderr index 7f901511f72..2cf17474f6e 100644 --- a/src/test/ui/reachable/expr_if.stderr +++ b/src/test/ui/reachable/expr_if.stderr @@ -11,5 +11,5 @@ note: lint level defined here | ^^^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_loop.stderr b/src/test/ui/reachable/expr_loop.stderr index 4fb6392f405..6e98e754c54 100644 --- a/src/test/ui/reachable/expr_loop.stderr +++ b/src/test/ui/reachable/expr_loop.stderr @@ -27,5 +27,5 @@ error: unreachable statement | = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/reachable/expr_match.stderr b/src/test/ui/reachable/expr_match.stderr index 387f7900f49..f5857a5b345 100644 --- a/src/test/ui/reachable/expr_match.stderr +++ b/src/test/ui/reachable/expr_match.stderr @@ -26,5 +26,5 @@ error: unreachable statement | = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/reachable/expr_method.stderr b/src/test/ui/reachable/expr_method.stderr index 68fd4973414..177d4352a37 100644 --- a/src/test/ui/reachable/expr_method.stderr +++ b/src/test/ui/reachable/expr_method.stderr @@ -16,5 +16,5 @@ error: unreachable expression 31 | Foo.bar(return); | ^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/reachable/expr_repeat.stderr b/src/test/ui/reachable/expr_repeat.stderr index 01b2e1009ee..19afc5dd7b5 100644 --- a/src/test/ui/reachable/expr_repeat.stderr +++ b/src/test/ui/reachable/expr_repeat.stderr @@ -10,5 +10,5 @@ note: lint level defined here 14 | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_return.stderr b/src/test/ui/reachable/expr_return.stderr index ee958aa9089..3eb70a4dd7c 100644 --- a/src/test/ui/reachable/expr_return.stderr +++ b/src/test/ui/reachable/expr_return.stderr @@ -10,5 +10,5 @@ note: lint level defined here 14 | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_struct.stderr b/src/test/ui/reachable/expr_struct.stderr index 08866bf32b8..4b7ac660413 100644 --- a/src/test/ui/reachable/expr_struct.stderr +++ b/src/test/ui/reachable/expr_struct.stderr @@ -28,5 +28,5 @@ error: unreachable expression 40 | let x = Foo { a: 22, b: return }; | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/reachable/expr_tup.stderr b/src/test/ui/reachable/expr_tup.stderr index 780fb02f790..63f477fd0c3 100644 --- a/src/test/ui/reachable/expr_tup.stderr +++ b/src/test/ui/reachable/expr_tup.stderr @@ -16,5 +16,5 @@ error: unreachable expression 25 | let x: (usize, usize) = (2, return); | ^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/reachable/expr_type.stderr b/src/test/ui/reachable/expr_type.stderr index 1216ec2676e..6ed79974ccb 100644 --- a/src/test/ui/reachable/expr_type.stderr +++ b/src/test/ui/reachable/expr_type.stderr @@ -10,5 +10,5 @@ note: lint level defined here 14 | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_unary.stderr b/src/test/ui/reachable/expr_unary.stderr index f47791455af..328b75fd236 100644 --- a/src/test/ui/reachable/expr_unary.stderr +++ b/src/test/ui/reachable/expr_unary.stderr @@ -4,5 +4,5 @@ error[E0600]: cannot apply unary operator `!` to type `!` 18 | let x: ! = ! { return; 22 }; | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_while.stderr b/src/test/ui/reachable/expr_while.stderr index 3da057f4bbd..066cfc86c64 100644 --- a/src/test/ui/reachable/expr_while.stderr +++ b/src/test/ui/reachable/expr_while.stderr @@ -27,5 +27,5 @@ error: unreachable statement | = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/regions-fn-subtyping-return-static.stderr b/src/test/ui/regions-fn-subtyping-return-static.stderr index 121a50d0eda..0c7b44af949 100644 --- a/src/test/ui/regions-fn-subtyping-return-static.stderr +++ b/src/test/ui/regions-fn-subtyping-return-static.stderr @@ -9,5 +9,5 @@ error[E0308]: mismatched types = note: lifetime parameter `'b` declared on fn `bar` appears only in the return type, but here is required to be higher-ranked, which means that `'b` must appear in both argument and return types = note: this error is the result of a recent bug fix; for more information, see issue #33685 -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/enums-are-namespaced-xc.stderr b/src/test/ui/resolve/enums-are-namespaced-xc.stderr index 03e80046f67..17c5d5d15d4 100644 --- a/src/test/ui/resolve/enums-are-namespaced-xc.stderr +++ b/src/test/ui/resolve/enums-are-namespaced-xc.stderr @@ -25,5 +25,5 @@ error[E0422]: cannot find struct, variant or union type `C` in module `namespace help: possible candidate is found in another module, you can import it into scope | use namespaced_enums::Foo::C; -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/resolve/issue-14254.stderr b/src/test/ui/resolve/issue-14254.stderr index 009d969fc28..11268e593c4 100644 --- a/src/test/ui/resolve/issue-14254.stderr +++ b/src/test/ui/resolve/issue-14254.stderr @@ -144,5 +144,5 @@ error[E0425]: cannot find value `bah` in this scope error[E0601]: main function not found -error: aborting due to previous error(s) +error: aborting due to 25 previous errors diff --git a/src/test/ui/resolve/issue-16058.stderr b/src/test/ui/resolve/issue-16058.stderr index 2fbf7d7185d..63d2ce10914 100644 --- a/src/test/ui/resolve/issue-16058.stderr +++ b/src/test/ui/resolve/issue-16058.stderr @@ -9,5 +9,5 @@ help: possible better candidates are found in other modules, you can import them | use std::io::Result; | use std::thread::Result; -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-17518.stderr b/src/test/ui/resolve/issue-17518.stderr index 69eeb178dff..c0438abfe43 100644 --- a/src/test/ui/resolve/issue-17518.stderr +++ b/src/test/ui/resolve/issue-17518.stderr @@ -7,5 +7,5 @@ error[E0422]: cannot find struct, variant or union type `E` in this scope help: possible candidate is found in another module, you can import it into scope | use SomeEnum::E; -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-18252.stderr b/src/test/ui/resolve/issue-18252.stderr index 225e31010da..edc7196d846 100644 --- a/src/test/ui/resolve/issue-18252.stderr +++ b/src/test/ui/resolve/issue-18252.stderr @@ -4,5 +4,5 @@ error[E0423]: expected function, found struct variant `Foo::Variant` 16 | let f = Foo::Variant(42); | ^^^^^^^^^^^^ did you mean `Foo::Variant { /* fields */ }`? -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-19452.stderr b/src/test/ui/resolve/issue-19452.stderr index 25ee3a02146..7b14d49af51 100644 --- a/src/test/ui/resolve/issue-19452.stderr +++ b/src/test/ui/resolve/issue-19452.stderr @@ -10,5 +10,5 @@ error[E0423]: expected value, found struct variant `issue_19452_aux::Homura::Mad 22 | let homura = issue_19452_aux::Homura::Madoka; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ did you mean `issue_19452_aux::Homura::Madoka { /* fields */ }`? -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/resolve/issue-23305.stderr b/src/test/ui/resolve/issue-23305.stderr index 2ca541c161b..fda87de9b9c 100644 --- a/src/test/ui/resolve/issue-23305.stderr +++ b/src/test/ui/resolve/issue-23305.stderr @@ -11,5 +11,5 @@ note: the cycle begins when processing ``, completing the cycle. -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-2356.stderr b/src/test/ui/resolve/issue-2356.stderr index 559598dd38a..039887d8da6 100644 --- a/src/test/ui/resolve/issue-2356.stderr +++ b/src/test/ui/resolve/issue-2356.stderr @@ -106,5 +106,5 @@ error[E0424]: expected value, found module `self` 122 | self += 1; | ^^^^ `self` value is only available in methods with `self` parameter -error: aborting due to previous error(s) +error: aborting due to 17 previous errors diff --git a/src/test/ui/resolve/issue-24968.stderr b/src/test/ui/resolve/issue-24968.stderr index 14a2413feee..111710d515a 100644 --- a/src/test/ui/resolve/issue-24968.stderr +++ b/src/test/ui/resolve/issue-24968.stderr @@ -4,5 +4,5 @@ error[E0411]: cannot find type `Self` in this scope 11 | fn foo(_: Self) { | ^^^^ `Self` is only available in traits and impls -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-33876.stderr b/src/test/ui/resolve/issue-33876.stderr index a950075715a..5dbecc4f0c5 100644 --- a/src/test/ui/resolve/issue-33876.stderr +++ b/src/test/ui/resolve/issue-33876.stderr @@ -4,5 +4,5 @@ error[E0423]: expected value, found trait `Bar` 20 | let any: &Any = &Bar; //~ ERROR expected value, found trait `Bar` | ^^^ not a value -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-3907-2.stderr b/src/test/ui/resolve/issue-3907-2.stderr index 4e1ef25f803..2ef8c830eb2 100644 --- a/src/test/ui/resolve/issue-3907-2.stderr +++ b/src/test/ui/resolve/issue-3907-2.stderr @@ -6,5 +6,5 @@ error[E0038]: the trait `issue_3907::Foo` cannot be made into an object | = note: method `bar` has no receiver -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-39226.stderr b/src/test/ui/resolve/issue-39226.stderr index 134a4540a8d..f6ee0b025bb 100644 --- a/src/test/ui/resolve/issue-39226.stderr +++ b/src/test/ui/resolve/issue-39226.stderr @@ -7,5 +7,5 @@ error[E0423]: expected value, found struct `Handle` | did you mean `handle`? | did you mean `Handle { /* fields */ }`? -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-5035-2.stderr b/src/test/ui/resolve/issue-5035-2.stderr index 9bdd7ee4fd4..791b20725f3 100644 --- a/src/test/ui/resolve/issue-5035-2.stderr +++ b/src/test/ui/resolve/issue-5035-2.stderr @@ -7,5 +7,5 @@ error[E0277]: the trait bound `I + 'static: std::marker::Sized` is not satisfied = help: the trait `std::marker::Sized` is not implemented for `I + 'static` = note: all local variables must have a statically known size -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-6702.stderr b/src/test/ui/resolve/issue-6702.stderr index 620958190ca..b50295752f2 100644 --- a/src/test/ui/resolve/issue-6702.stderr +++ b/src/test/ui/resolve/issue-6702.stderr @@ -4,5 +4,5 @@ error[E0423]: expected function, found struct `Monster` 17 | let _m = Monster(); //~ ERROR expected function, found struct `Monster` | ^^^^^^^ did you mean `Monster { /* fields */ }`? -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/levenshtein.stderr b/src/test/ui/resolve/levenshtein.stderr index d25c52eeab3..4dff2620319 100644 --- a/src/test/ui/resolve/levenshtein.stderr +++ b/src/test/ui/resolve/levenshtein.stderr @@ -46,5 +46,5 @@ error[E0425]: cannot find value `second` in module `m` 32 | let b: m::first = m::second; // Misspelled item in module. | ^^^^^^ did you mean `Second`? -error: aborting due to previous error(s) +error: aborting due to 8 previous errors diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr index a1ec5f0b713..18efb17dd46 100644 --- a/src/test/ui/resolve/privacy-struct-ctor.stderr +++ b/src/test/ui/resolve/privacy-struct-ctor.stderr @@ -65,5 +65,5 @@ error[E0603]: tuple struct `Z` is private 45 | xcrate::m::n::Z; //~ ERROR tuple struct `Z` is private | ^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to 8 previous errors diff --git a/src/test/ui/resolve/resolve-assoc-suggestions.stderr b/src/test/ui/resolve/resolve-assoc-suggestions.stderr index c346612a68b..7975c168de7 100644 --- a/src/test/ui/resolve/resolve-assoc-suggestions.stderr +++ b/src/test/ui/resolve/resolve-assoc-suggestions.stderr @@ -52,5 +52,5 @@ error[E0425]: cannot find value `method` in this scope 52 | method; | ^^^^^^ did you mean `self.method(...)`? -error: aborting due to previous error(s) +error: aborting due to 9 previous errors diff --git a/src/test/ui/resolve/resolve-hint-macro.stderr b/src/test/ui/resolve/resolve-hint-macro.stderr index 92f13f705b0..ffb3f848430 100644 --- a/src/test/ui/resolve/resolve-hint-macro.stderr +++ b/src/test/ui/resolve/resolve-hint-macro.stderr @@ -4,5 +4,5 @@ error[E0423]: expected function, found macro `assert` 12 | assert(true); | ^^^^^^ did you mean `assert!(...)`? -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/resolve-speculative-adjustment.stderr b/src/test/ui/resolve/resolve-speculative-adjustment.stderr index 04c8087ace9..e7df8140bc5 100644 --- a/src/test/ui/resolve/resolve-speculative-adjustment.stderr +++ b/src/test/ui/resolve/resolve-speculative-adjustment.stderr @@ -22,5 +22,5 @@ error[E0425]: cannot find function `method` in this scope 38 | method(); | ^^^^^^ did you mean `self.method(...)`? -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr index a34c27a47da..d1794d19f6a 100644 --- a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr +++ b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr @@ -74,5 +74,5 @@ error[E0423]: expected function, found module `a::b` error[E0601]: main function not found -error: aborting due to previous error(s) +error: aborting due to 10 previous errors diff --git a/src/test/ui/resolve/token-error-correct-2.stderr b/src/test/ui/resolve/token-error-correct-2.stderr index 7307f19c74d..feb12612e66 100644 --- a/src/test/ui/resolve/token-error-correct-2.stderr +++ b/src/test/ui/resolve/token-error-correct-2.stderr @@ -16,5 +16,5 @@ error[E0425]: cannot find value `foo` in this scope 14 | if foo { | ^^^ not found in this scope -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/resolve/token-error-correct-3.stderr b/src/test/ui/resolve/token-error-correct-3.stderr index d234c8538fe..bd3bdf35da6 100644 --- a/src/test/ui/resolve/token-error-correct-3.stderr +++ b/src/test/ui/resolve/token-error-correct-3.stderr @@ -35,10 +35,12 @@ error[E0308]: mismatched types --> $DIR/token-error-correct-3.rs:25:13 | 25 | fs::create_dir_all(path.as_ref()).map(|()| true) //~ ERROR: mismatched types - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `std::result::Result` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: did you mean to add a semicolon here? `;` + | | + | expected (), found enum `std::result::Result` | = note: expected type `()` found type `std::result::Result` -error: aborting due to previous error(s) +error: aborting due to 5 previous errors diff --git a/src/test/ui/resolve/token-error-correct.stderr b/src/test/ui/resolve/token-error-correct.stderr index 1dd263affd4..226fa6469bc 100644 --- a/src/test/ui/resolve/token-error-correct.stderr +++ b/src/test/ui/resolve/token-error-correct.stderr @@ -52,5 +52,5 @@ error[E0425]: cannot find function `bar` in this scope 14 | foo(bar(; | ^^^ not found in this scope -error: aborting due to previous error(s) +error: aborting due to 7 previous errors diff --git a/src/test/ui/resolve/tuple-struct-alias.stderr b/src/test/ui/resolve/tuple-struct-alias.stderr index 2fc5979a606..e2ef8f0e568 100644 --- a/src/test/ui/resolve/tuple-struct-alias.stderr +++ b/src/test/ui/resolve/tuple-struct-alias.stderr @@ -28,5 +28,5 @@ error[E0532]: expected tuple struct/variant, found type alias `A` | did you mean `S`? | did you mean `A { /* fields */ }`? -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/resolve/unresolved_static_type_field.stderr b/src/test/ui/resolve/unresolved_static_type_field.stderr index ff6bcf2a532..5fbaf66e014 100644 --- a/src/test/ui/resolve/unresolved_static_type_field.stderr +++ b/src/test/ui/resolve/unresolved_static_type_field.stderr @@ -7,5 +7,5 @@ error[E0425]: cannot find value `cx` in this scope | did you mean `self.cx`? | `self` value is only available in methods with `self` parameter -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/compile-fail/shadowed-type-parameter.rs b/src/test/ui/shadowed-type-parameter.rs similarity index 100% rename from src/test/compile-fail/shadowed-type-parameter.rs rename to src/test/ui/shadowed-type-parameter.rs diff --git a/src/test/ui/shadowed-type-parameter.stderr b/src/test/ui/shadowed-type-parameter.stderr new file mode 100644 index 00000000000..a16a9c0244f --- /dev/null +++ b/src/test/ui/shadowed-type-parameter.stderr @@ -0,0 +1,28 @@ +error[E0194]: type parameter `T` shadows another type parameter of the same name + --> $DIR/shadowed-type-parameter.rs:30:27 + | +27 | trait Bar { + | - first `T` declared here +... +30 | fn shadow_in_required(&self); + | ^ shadows another type parameter + +error[E0194]: type parameter `T` shadows another type parameter of the same name + --> $DIR/shadowed-type-parameter.rs:33:27 + | +27 | trait Bar { + | - first `T` declared here +... +33 | fn shadow_in_provided(&self) {} + | ^ shadows another type parameter + +error[E0194]: type parameter `T` shadows another type parameter of the same name + --> $DIR/shadowed-type-parameter.rs:18:25 + | +17 | impl Foo { + | - first `T` declared here +18 | fn shadow_in_method(&self) {} + | ^ shadows another type parameter + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/span/E0046.stderr b/src/test/ui/span/E0046.stderr index f722908ec10..729a5156124 100644 --- a/src/test/ui/span/E0046.stderr +++ b/src/test/ui/span/E0046.stderr @@ -7,5 +7,5 @@ error[E0046]: not all trait items implemented, missing: `foo` 18 | impl Foo for Bar {} | ^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/E0057.stderr b/src/test/ui/span/E0057.stderr index bc3a3908dca..0d6b0a552e4 100644 --- a/src/test/ui/span/E0057.stderr +++ b/src/test/ui/span/E0057.stderr @@ -10,5 +10,5 @@ error[E0057]: this function takes 1 parameter but 2 parameters were supplied 15 | let c = f(2, 3); //~ ERROR E0057 | ^^^^ expected 1 parameter -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/E0072.stderr b/src/test/ui/span/E0072.stderr index 14e6bcb73b0..1f6dd6b1d16 100644 --- a/src/test/ui/span/E0072.stderr +++ b/src/test/ui/span/E0072.stderr @@ -9,5 +9,5 @@ error[E0072]: recursive type `ListNode` has infinite size | = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ListNode` representable -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/E0204.stderr b/src/test/ui/span/E0204.stderr index fab2436922d..4fe6afaca8e 100644 --- a/src/test/ui/span/E0204.stderr +++ b/src/test/ui/span/E0204.stderr @@ -34,5 +34,5 @@ error[E0204]: the trait `Copy` may not be implemented for this type 31 | Bar(&'a mut bool), | ------------- this field does not implement `Copy` -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/span/E0493.stderr b/src/test/ui/span/E0493.stderr index 5f8b57294d5..afcc9a240eb 100644 --- a/src/test/ui/span/E0493.stderr +++ b/src/test/ui/span/E0493.stderr @@ -7,5 +7,5 @@ error[E0493]: constants are not allowed to have destructors 27 | const F : Foo = Foo { a : 0 }; | ^^^^^^^^^^^^^ constants cannot have destructors -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/E0535.stderr b/src/test/ui/span/E0535.stderr index 64c0016085f..23070e1555b 100644 --- a/src/test/ui/span/E0535.stderr +++ b/src/test/ui/span/E0535.stderr @@ -4,5 +4,5 @@ error[E0535]: invalid argument 11 | #[inline(unknown)] //~ ERROR E0535 | ^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/E0536.stderr b/src/test/ui/span/E0536.stderr index 8a4cf34e565..b2da0c6a296 100644 --- a/src/test/ui/span/E0536.stderr +++ b/src/test/ui/span/E0536.stderr @@ -4,5 +4,5 @@ error[E0536]: expected 1 cfg-pattern 11 | #[cfg(not())] //~ ERROR E0536 | ^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/E0537.stderr b/src/test/ui/span/E0537.stderr index 1bd54a6a007..29873943f44 100644 --- a/src/test/ui/span/E0537.stderr +++ b/src/test/ui/span/E0537.stderr @@ -4,5 +4,5 @@ error[E0537]: invalid predicate `unknown` 11 | #[cfg(unknown())] //~ ERROR E0537 | ^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr index 4b01f5bea7c..2d580e7c20e 100644 --- a/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr +++ b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr @@ -82,5 +82,5 @@ error[E0596]: cannot borrow immutable borrowed content `*x` as mutable 143 | *x.y_mut() = 3; //~ ERROR cannot borrow | ^ cannot borrow as mutable -error: aborting due to previous error(s) +error: aborting due to 10 previous errors diff --git a/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr b/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr index 886cc142039..3d380a9a2e8 100644 --- a/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr +++ b/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr @@ -30,5 +30,5 @@ error[E0596]: cannot borrow immutable borrowed content `*x` as mutable 63 | **x = 3; //~ ERROR cannot borrow | ^^ cannot borrow as mutable -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr index a26ca490dd5..6e7d0c17f1d 100644 --- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr +++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr @@ -47,5 +47,5 @@ error[E0507]: cannot move out of captured outer variable in an `FnMut` closure 72 | foo(f); | ^ cannot move out of captured outer variable in an `FnMut` closure -error: aborting due to previous error(s) +error: aborting due to 5 previous errors diff --git a/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr b/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr index dea95d6bf6d..a57cc94b9ba 100644 --- a/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr +++ b/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr @@ -7,5 +7,5 @@ error[E0596]: cannot borrow immutable borrowed content `*x` as mutable 27 | x.h(); //~ ERROR cannot borrow | ^ cannot borrow as mutable -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/borrowck-fn-in-const-b.stderr b/src/test/ui/span/borrowck-fn-in-const-b.stderr index 3bf56881c54..45712d1a710 100644 --- a/src/test/ui/span/borrowck-fn-in-const-b.stderr +++ b/src/test/ui/span/borrowck-fn-in-const-b.stderr @@ -6,5 +6,5 @@ error[E0596]: cannot borrow immutable borrowed content `*x` as mutable 17 | x.push(format!("this is broken")); | ^ cannot borrow as mutable -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr b/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr index 04dbcd2ef49..6ed1b7c2622 100644 --- a/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr +++ b/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr @@ -48,5 +48,5 @@ error[E0597]: borrowed value does not live long enough | = note: consider using a `let` binding to increase its lifetime -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/span/borrowck-object-mutability.stderr b/src/test/ui/span/borrowck-object-mutability.stderr index 877b17dc27d..530993f399a 100644 --- a/src/test/ui/span/borrowck-object-mutability.stderr +++ b/src/test/ui/span/borrowck-object-mutability.stderr @@ -16,5 +16,5 @@ error[E0596]: cannot borrow immutable `Box` content `*x` as mutable 29 | x.borrowed_mut(); //~ ERROR cannot borrow | ^ cannot borrow as mutable -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/borrowck-ref-into-rvalue.stderr b/src/test/ui/span/borrowck-ref-into-rvalue.stderr index e0a484bcb37..ced1f762af4 100644 --- a/src/test/ui/span/borrowck-ref-into-rvalue.stderr +++ b/src/test/ui/span/borrowck-ref-into-rvalue.stderr @@ -12,5 +12,5 @@ error[E0597]: borrowed value does not live long enough | = note: consider using a `let` binding to increase its lifetime -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/coerce-suggestions.stderr b/src/test/ui/span/coerce-suggestions.stderr index e3bc64a2cfd..b703632bf90 100644 --- a/src/test/ui/span/coerce-suggestions.stderr +++ b/src/test/ui/span/coerce-suggestions.stderr @@ -58,5 +58,5 @@ error[E0308]: mismatched types = help: try with `&mut format!("foo")` = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to 6 previous errors diff --git a/src/test/ui/span/destructor-restrictions.stderr b/src/test/ui/span/destructor-restrictions.stderr index 1472a364863..ee885454169 100644 --- a/src/test/ui/span/destructor-restrictions.stderr +++ b/src/test/ui/span/destructor-restrictions.stderr @@ -8,5 +8,5 @@ error[E0597]: `*a` does not live long enough | | | `*a` dropped here while still borrowed -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/dropck-object-cycle.stderr b/src/test/ui/span/dropck-object-cycle.stderr index d0fceb2a03e..49115b244e6 100644 --- a/src/test/ui/span/dropck-object-cycle.stderr +++ b/src/test/ui/span/dropck-object-cycle.stderr @@ -9,5 +9,5 @@ error[E0597]: `*m` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/dropck_arr_cycle_checked.stderr b/src/test/ui/span/dropck_arr_cycle_checked.stderr index 2a9c2c8413f..4179ac1a946 100644 --- a/src/test/ui/span/dropck_arr_cycle_checked.stderr +++ b/src/test/ui/span/dropck_arr_cycle_checked.stderr @@ -63,5 +63,5 @@ error[E0597]: `b2` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 6 previous errors diff --git a/src/test/ui/span/dropck_direct_cycle_with_drop.stderr b/src/test/ui/span/dropck_direct_cycle_with_drop.stderr index e6421cd4785..597d42aabd2 100644 --- a/src/test/ui/span/dropck_direct_cycle_with_drop.stderr +++ b/src/test/ui/span/dropck_direct_cycle_with_drop.stderr @@ -19,5 +19,5 @@ error[E0597]: `d1` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/dropck_misc_variants.stderr b/src/test/ui/span/dropck_misc_variants.stderr index 7fbdcba7eb6..958f229f659 100644 --- a/src/test/ui/span/dropck_misc_variants.stderr +++ b/src/test/ui/span/dropck_misc_variants.stderr @@ -19,5 +19,5 @@ error[E0597]: `v` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/dropck_vec_cycle_checked.stderr b/src/test/ui/span/dropck_vec_cycle_checked.stderr index 3861b145c1b..d7d0fe5323b 100644 --- a/src/test/ui/span/dropck_vec_cycle_checked.stderr +++ b/src/test/ui/span/dropck_vec_cycle_checked.stderr @@ -63,5 +63,5 @@ error[E0597]: `c2` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 6 previous errors diff --git a/src/test/ui/span/impl-wrong-item-for-trait.stderr b/src/test/ui/span/impl-wrong-item-for-trait.stderr index ca7286f5027..2c4c6a148d7 100644 --- a/src/test/ui/span/impl-wrong-item-for-trait.stderr +++ b/src/test/ui/span/impl-wrong-item-for-trait.stderr @@ -85,5 +85,5 @@ error[E0046]: not all trait items implemented, missing: `fmt` | = note: `fmt` from trait: `fn(&Self, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>` -error: aborting due to previous error(s) +error: aborting due to 8 previous errors diff --git a/src/test/ui/span/issue-11925.stderr b/src/test/ui/span/issue-11925.stderr index 67d60fe085a..6b2942bc7a8 100644 --- a/src/test/ui/span/issue-11925.stderr +++ b/src/test/ui/span/issue-11925.stderr @@ -10,5 +10,5 @@ error[E0597]: `x` does not live long enough 23 | } | - borrowed value needs to live until here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-15480.stderr b/src/test/ui/span/issue-15480.stderr index f5f987c823f..ce1c6e81b96 100644 --- a/src/test/ui/span/issue-15480.stderr +++ b/src/test/ui/span/issue-15480.stderr @@ -11,5 +11,5 @@ error[E0597]: borrowed value does not live long enough | = note: consider using a `let` binding to increase its lifetime -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.stderr b/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.stderr index e564b7ccef2..02c03315372 100644 --- a/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.stderr +++ b/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.stderr @@ -18,5 +18,5 @@ error[E0597]: `y` does not live long enough | | | `y` dropped here while still borrowed -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue-23729.stderr b/src/test/ui/span/issue-23729.stderr index d6aed36c8f6..d9f4bacce35 100644 --- a/src/test/ui/span/issue-23729.stderr +++ b/src/test/ui/span/issue-23729.stderr @@ -12,5 +12,5 @@ error[E0046]: not all trait items implemented, missing: `Item` | = note: `Item` from trait: `type Item;` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-23827.stderr b/src/test/ui/span/issue-23827.stderr index a1d3f5c11df..3127af157a6 100644 --- a/src/test/ui/span/issue-23827.stderr +++ b/src/test/ui/span/issue-23827.stderr @@ -12,5 +12,5 @@ error[E0046]: not all trait items implemented, missing: `Output` | = note: `Output` from trait: `type Output;` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-24356.stderr b/src/test/ui/span/issue-24356.stderr index 771ea787304..71ab82d98b8 100644 --- a/src/test/ui/span/issue-24356.stderr +++ b/src/test/ui/span/issue-24356.stderr @@ -11,5 +11,5 @@ error[E0046]: not all trait items implemented, missing: `Target` | = note: `Target` from trait: `type Target;` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-24690.stderr b/src/test/ui/span/issue-24690.stderr index 598f9f51307..8332ba50a73 100644 --- a/src/test/ui/span/issue-24690.stderr +++ b/src/test/ui/span/issue-24690.stderr @@ -4,20 +4,18 @@ error: variable `theTwo` should have a snake case name such as `the_two` 19 | let theTwo = 2; | ^^^^^^ | - = note: #[deny(non_snake_case)] implied by #[deny(warnings)] note: lint level defined here --> $DIR/issue-24690.rs:16:9 | 16 | #![deny(warnings)] | ^^^^^^^^ + = note: #[deny(non_snake_case)] implied by #[deny(warnings)] error: variable `theOtherTwo` should have a snake case name such as `the_other_two` --> $DIR/issue-24690.rs:20:9 | 20 | let theOtherTwo = 2; | ^^^^^^^^^^^ - | - = note: #[deny(non_snake_case)] implied by #[deny(warnings)] error: unused variable: `theOtherTwo` --> $DIR/issue-24690.rs:20:9 @@ -25,12 +23,12 @@ error: unused variable: `theOtherTwo` 20 | let theOtherTwo = 2; | ^^^^^^^^^^^ | - = note: #[deny(unused_variables)] implied by #[deny(warnings)] note: lint level defined here --> $DIR/issue-24690.rs:16:9 | 16 | #![deny(warnings)] | ^^^^^^^^ + = note: #[deny(unused_variables)] implied by #[deny(warnings)] -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr b/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr index 314ef0ecbbc..29587b7fbde 100644 --- a/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr +++ b/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr @@ -9,5 +9,5 @@ error[E0597]: `d1` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-24805-dropck-trait-has-items.stderr b/src/test/ui/span/issue-24805-dropck-trait-has-items.stderr index 66f22d14578..c88d4a0202f 100644 --- a/src/test/ui/span/issue-24805-dropck-trait-has-items.stderr +++ b/src/test/ui/span/issue-24805-dropck-trait-has-items.stderr @@ -28,5 +28,5 @@ error[E0597]: `d1` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/span/issue-24895-copy-clone-dropck.stderr b/src/test/ui/span/issue-24895-copy-clone-dropck.stderr index cfa8359088a..7f80e6e115a 100644 --- a/src/test/ui/span/issue-24895-copy-clone-dropck.stderr +++ b/src/test/ui/span/issue-24895-copy-clone-dropck.stderr @@ -8,5 +8,5 @@ error[E0597]: `d1` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-25199.stderr b/src/test/ui/span/issue-25199.stderr index 999871db093..4f403b38f5a 100644 --- a/src/test/ui/span/issue-25199.stderr +++ b/src/test/ui/span/issue-25199.stderr @@ -19,5 +19,5 @@ error[E0597]: `container` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue-26656.stderr b/src/test/ui/span/issue-26656.stderr index b4f0195f6a8..748fcae48fc 100644 --- a/src/test/ui/span/issue-26656.stderr +++ b/src/test/ui/span/issue-26656.stderr @@ -8,5 +8,5 @@ error[E0597]: `ticking` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-27522.stderr b/src/test/ui/span/issue-27522.stderr index 443595c6d2c..117b109780b 100644 --- a/src/test/ui/span/issue-27522.stderr +++ b/src/test/ui/span/issue-27522.stderr @@ -7,5 +7,5 @@ error[E0308]: mismatched method receiver = note: expected type `&Self` found type `&SomeType` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-29106.stderr b/src/test/ui/span/issue-29106.stderr index b645cbf402d..f146028c2fc 100644 --- a/src/test/ui/span/issue-29106.stderr +++ b/src/test/ui/span/issue-29106.stderr @@ -18,5 +18,5 @@ error[E0597]: `x` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue-29595.stderr b/src/test/ui/span/issue-29595.stderr index 4065c4fb857..abbac245f89 100644 --- a/src/test/ui/span/issue-29595.stderr +++ b/src/test/ui/span/issue-29595.stderr @@ -6,5 +6,5 @@ error[E0277]: the trait bound `u8: Tr` is not satisfied | = note: required by `Tr::C` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-33884.stderr b/src/test/ui/span/issue-33884.stderr index 38256ec944b..2a874181c7a 100644 --- a/src/test/ui/span/issue-33884.stderr +++ b/src/test/ui/span/issue-33884.stderr @@ -8,5 +8,5 @@ error[E0308]: mismatched types found type `std::string::String` = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-34264.stderr b/src/test/ui/span/issue-34264.stderr index 48ed0b4ac89..e25caacac8f 100644 --- a/src/test/ui/span/issue-34264.stderr +++ b/src/test/ui/span/issue-34264.stderr @@ -45,5 +45,5 @@ error[E0061]: this function takes 2 parameters but 3 parameters were supplied 19 | bar(1, 2, 3); | ^^^^^^^ expected 2 parameters -error: aborting due to previous error(s) +error: aborting due to 6 previous errors diff --git a/src/test/ui/span/issue-36530.stderr b/src/test/ui/span/issue-36530.stderr index 5dc9bd8b79b..dc6190c2e76 100644 --- a/src/test/ui/span/issue-36530.stderr +++ b/src/test/ui/span/issue-36530.stderr @@ -14,5 +14,5 @@ error: The attribute `foo` is currently unknown to the compiler and may have mea | = help: add #![feature(custom_attribute)] to the crate attributes to enable -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue-36537.stderr b/src/test/ui/span/issue-36537.stderr index df06cd1d0ea..803e476b749 100644 --- a/src/test/ui/span/issue-36537.stderr +++ b/src/test/ui/span/issue-36537.stderr @@ -8,5 +8,5 @@ error[E0597]: `a` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-37767.stderr b/src/test/ui/span/issue-37767.stderr index bd271641e7e..7cf74eaab8d 100644 --- a/src/test/ui/span/issue-37767.stderr +++ b/src/test/ui/span/issue-37767.stderr @@ -55,5 +55,5 @@ note: candidate #2 is defined in the trait `F` | ^^^^^^^^^^^^^^^ = help: to disambiguate the method call, write `F::foo(a)` instead -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/span/issue-39018.stderr b/src/test/ui/span/issue-39018.stderr index f0b940cdf3f..cd3a41b037c 100644 --- a/src/test/ui/span/issue-39018.stderr +++ b/src/test/ui/span/issue-39018.stderr @@ -15,5 +15,5 @@ error[E0369]: binary operation `+` cannot be applied to type `World` | = note: an implementation of `std::ops::Add` might be missing for `World` -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue-39698.stderr b/src/test/ui/span/issue-39698.stderr index 0d0a07629c4..97d802f8398 100644 --- a/src/test/ui/span/issue-39698.stderr +++ b/src/test/ui/span/issue-39698.stderr @@ -38,5 +38,5 @@ error[E0408]: variable `c` is not bound in all patterns | | pattern doesn't bind `c` | pattern doesn't bind `c` -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/span/issue-40157.stderr b/src/test/ui/span/issue-40157.stderr index 50183aa3bde..b689bef63f1 100644 --- a/src/test/ui/span/issue-40157.stderr +++ b/src/test/ui/span/issue-40157.stderr @@ -10,5 +10,5 @@ error[E0597]: `foo` does not live long enough | = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-7575.stderr b/src/test/ui/span/issue-7575.stderr index 9bf00b1b574..858c099d374 100644 --- a/src/test/ui/span/issue-7575.stderr +++ b/src/test/ui/span/issue-7575.stderr @@ -63,5 +63,5 @@ note: candidate #1 is defined in the trait `ManyImplTrait` = note: the following trait defines an item `is_str`, perhaps you need to implement it: candidate #1: `ManyImplTrait` -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/span/issue28498-reject-ex1.stderr b/src/test/ui/span/issue28498-reject-ex1.stderr index a2ef99f9d76..6beb3109c75 100644 --- a/src/test/ui/span/issue28498-reject-ex1.stderr +++ b/src/test/ui/span/issue28498-reject-ex1.stderr @@ -19,5 +19,5 @@ error[E0597]: `foo.data` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue28498-reject-lifetime-param.stderr b/src/test/ui/span/issue28498-reject-lifetime-param.stderr index cb77cd3dc99..358fa9b7c45 100644 --- a/src/test/ui/span/issue28498-reject-lifetime-param.stderr +++ b/src/test/ui/span/issue28498-reject-lifetime-param.stderr @@ -20,5 +20,5 @@ error[E0597]: `first_dropped` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue28498-reject-passed-to-fn.stderr b/src/test/ui/span/issue28498-reject-passed-to-fn.stderr index 49116c340ec..0aaf2b27f60 100644 --- a/src/test/ui/span/issue28498-reject-passed-to-fn.stderr +++ b/src/test/ui/span/issue28498-reject-passed-to-fn.stderr @@ -20,5 +20,5 @@ error[E0597]: `first_dropped` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue28498-reject-trait-bound.stderr b/src/test/ui/span/issue28498-reject-trait-bound.stderr index bb4de82422a..27a4d2384ab 100644 --- a/src/test/ui/span/issue28498-reject-trait-bound.stderr +++ b/src/test/ui/span/issue28498-reject-trait-bound.stderr @@ -20,5 +20,5 @@ error[E0597]: `first_dropped` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/lint-unused-unsafe.stderr b/src/test/ui/span/lint-unused-unsafe.stderr index 2f5e60a1b3c..f4998e08907 100644 --- a/src/test/ui/span/lint-unused-unsafe.stderr +++ b/src/test/ui/span/lint-unused-unsafe.stderr @@ -106,5 +106,5 @@ note: because it's nested under this `unsafe` fn 44 | | } | |_^ -error: aborting due to previous error(s) +error: aborting due to 8 previous errors diff --git a/src/test/ui/span/loan-extend.stderr b/src/test/ui/span/loan-extend.stderr index 036c4bd6b8d..91bdd8a8cad 100644 --- a/src/test/ui/span/loan-extend.stderr +++ b/src/test/ui/span/loan-extend.stderr @@ -9,5 +9,5 @@ error[E0597]: `short` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/move-closure.stderr b/src/test/ui/span/move-closure.stderr index f76c5b049c4..2294e6476d6 100644 --- a/src/test/ui/span/move-closure.stderr +++ b/src/test/ui/span/move-closure.stderr @@ -7,5 +7,5 @@ error[E0308]: mismatched types = note: expected type `()` found type `[closure@$DIR/move-closure.rs:15:17: 15:27]` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/multiline-span-E0072.stderr b/src/test/ui/span/multiline-span-E0072.stderr index 881c2f5df45..a06cbd04deb 100644 --- a/src/test/ui/span/multiline-span-E0072.stderr +++ b/src/test/ui/span/multiline-span-E0072.stderr @@ -12,5 +12,5 @@ error[E0072]: recursive type `ListNode` has infinite size | = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ListNode` representable -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/multiline-span-simple.stderr b/src/test/ui/span/multiline-span-simple.stderr index 0224cef8da1..3915f1b655c 100644 --- a/src/test/ui/span/multiline-span-simple.stderr +++ b/src/test/ui/span/multiline-span-simple.stderr @@ -6,5 +6,5 @@ error[E0277]: the trait bound `u32: std::ops::Add<()>` is not satisfied | = help: the trait `std::ops::Add<()>` is not implemented for `u32` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/mut-arg-hint.stderr b/src/test/ui/span/mut-arg-hint.stderr index 754e96aa808..f8584c67390 100644 --- a/src/test/ui/span/mut-arg-hint.stderr +++ b/src/test/ui/span/mut-arg-hint.stderr @@ -22,5 +22,5 @@ error[E0596]: cannot borrow immutable borrowed content `*a` as mutable 25 | a.push_str("foo"); | ^ cannot borrow as mutable -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/span/mut-ptr-cant-outlive-ref.stderr b/src/test/ui/span/mut-ptr-cant-outlive-ref.stderr index 5bd6a786cfd..007a9fad830 100644 --- a/src/test/ui/span/mut-ptr-cant-outlive-ref.stderr +++ b/src/test/ui/span/mut-ptr-cant-outlive-ref.stderr @@ -8,5 +8,5 @@ error[E0597]: `b` does not live long enough 20 | } | - borrowed value needs to live until here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/pub-struct-field.stderr b/src/test/ui/span/pub-struct-field.stderr index 835b08f8907..c66361c8546 100644 --- a/src/test/ui/span/pub-struct-field.stderr +++ b/src/test/ui/span/pub-struct-field.stderr @@ -15,5 +15,5 @@ error[E0124]: field `bar` is already declared 17 | pub(crate) bar: u8, | ^^^^^^^^^^^^^^^^^^ field already declared -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/range-2.stderr b/src/test/ui/span/range-2.stderr index 465a663a741..285ab4aee4b 100644 --- a/src/test/ui/span/range-2.stderr +++ b/src/test/ui/span/range-2.stderr @@ -20,5 +20,5 @@ error[E0597]: `b` does not live long enough 21 | } | - borrowed value needs to live until here -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/recursive-type-field.stderr b/src/test/ui/span/recursive-type-field.stderr index 72177754681..b4d0b5a6a25 100644 --- a/src/test/ui/span/recursive-type-field.stderr +++ b/src/test/ui/span/recursive-type-field.stderr @@ -27,5 +27,5 @@ error[E0072]: recursive type `Bar` has infinite size | = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Bar` representable -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/regionck-unboxed-closure-lifetimes.stderr b/src/test/ui/span/regionck-unboxed-closure-lifetimes.stderr index 80dadd97a17..29848412e4e 100644 --- a/src/test/ui/span/regionck-unboxed-closure-lifetimes.stderr +++ b/src/test/ui/span/regionck-unboxed-closure-lifetimes.stderr @@ -9,5 +9,5 @@ error[E0597]: `c` does not live long enough 20 | } | - borrowed value needs to live until here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr b/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr index 25386cb30b1..e671f1daf61 100644 --- a/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr +++ b/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr @@ -9,5 +9,5 @@ error[E0597]: borrowed value does not live long enough 23 | } | - temporary value needs to live until here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/regions-close-over-type-parameter-2.stderr b/src/test/ui/span/regions-close-over-type-parameter-2.stderr index 9b5383877a0..a89127b1436 100644 --- a/src/test/ui/span/regions-close-over-type-parameter-2.stderr +++ b/src/test/ui/span/regions-close-over-type-parameter-2.stderr @@ -9,5 +9,5 @@ error[E0597]: `tmp0` does not live long enough | | | `tmp0` dropped here while still borrowed -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/regions-escape-loop-via-variable.stderr b/src/test/ui/span/regions-escape-loop-via-variable.stderr index 9f8c91cb9cd..cfdd1c8b153 100644 --- a/src/test/ui/span/regions-escape-loop-via-variable.stderr +++ b/src/test/ui/span/regions-escape-loop-via-variable.stderr @@ -8,5 +8,5 @@ error[E0597]: `x` does not live long enough 23 | } | - borrowed value needs to live until here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/regions-escape-loop-via-vec.stderr b/src/test/ui/span/regions-escape-loop-via-vec.stderr index 4f0e61f1133..b61df82e8a1 100644 --- a/src/test/ui/span/regions-escape-loop-via-vec.stderr +++ b/src/test/ui/span/regions-escape-loop-via-vec.stderr @@ -37,5 +37,5 @@ error[E0506]: cannot assign to `x` because it is borrowed 24 | x += 1; //~ ERROR cannot assign | ^^^^^^ assignment to borrowed `x` occurs here -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/span/regions-infer-borrow-scope-within-loop.stderr b/src/test/ui/span/regions-infer-borrow-scope-within-loop.stderr index 43103e619a5..0960f5e1b25 100644 --- a/src/test/ui/span/regions-infer-borrow-scope-within-loop.stderr +++ b/src/test/ui/span/regions-infer-borrow-scope-within-loop.stderr @@ -10,5 +10,5 @@ error[E0597]: `*x` does not live long enough 30 | } | - borrowed value needs to live until here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/send-is-not-static-ensures-scoping.stderr b/src/test/ui/span/send-is-not-static-ensures-scoping.stderr index b5e55adfb45..02fc9820495 100644 --- a/src/test/ui/span/send-is-not-static-ensures-scoping.stderr +++ b/src/test/ui/span/send-is-not-static-ensures-scoping.stderr @@ -24,5 +24,5 @@ error[E0597]: `y` does not live long enough 35 | } | - borrowed value needs to live until here -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/send-is-not-static-std-sync-2.stderr b/src/test/ui/span/send-is-not-static-std-sync-2.stderr index 2845c4f6bda..318dab599f5 100644 --- a/src/test/ui/span/send-is-not-static-std-sync-2.stderr +++ b/src/test/ui/span/send-is-not-static-std-sync-2.stderr @@ -32,5 +32,5 @@ error[E0597]: `x` does not live long enough 44 | } | - borrowed value needs to live until here -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/span/send-is-not-static-std-sync.stderr b/src/test/ui/span/send-is-not-static-std-sync.stderr index 3d75a1b717a..988ff228105 100644 --- a/src/test/ui/span/send-is-not-static-std-sync.stderr +++ b/src/test/ui/span/send-is-not-static-std-sync.stderr @@ -52,5 +52,5 @@ error[E0505]: cannot move out of `y` because it is borrowed 49 | drop(y); //~ ERROR cannot move out | ^ move out of `y` occurs here -error: aborting due to previous error(s) +error: aborting due to 6 previous errors diff --git a/src/test/ui/span/slice-borrow.stderr b/src/test/ui/span/slice-borrow.stderr index 0c07d068d28..b60ccd0fbf3 100644 --- a/src/test/ui/span/slice-borrow.stderr +++ b/src/test/ui/span/slice-borrow.stderr @@ -9,5 +9,5 @@ error[E0597]: borrowed value does not live long enough 19 | } | - temporary value needs to live until here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/suggestion-non-ascii.stderr b/src/test/ui/span/suggestion-non-ascii.stderr index 68d43d3f5cd..c2ab7542d8a 100644 --- a/src/test/ui/span/suggestion-non-ascii.stderr +++ b/src/test/ui/span/suggestion-non-ascii.stderr @@ -4,5 +4,5 @@ error[E0608]: cannot index into a value of type `({integer},)` 14 | println!("☃{}", tup[0]); | ^^^^^^ help: to access tuple elements, use `tup.0` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/type-binding.stderr b/src/test/ui/span/type-binding.stderr index afe069e7aa6..dc37acaf3f9 100644 --- a/src/test/ui/span/type-binding.stderr +++ b/src/test/ui/span/type-binding.stderr @@ -4,5 +4,5 @@ error[E0220]: associated type `Trget` not found for `std::ops::Deref` 16 | fn homura>(_: T) {} | ^^^^^^^^^^^ associated type `Trget` not found -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/typo-suggestion.stderr b/src/test/ui/span/typo-suggestion.stderr index 6556e5b4c00..dca0a93f897 100644 --- a/src/test/ui/span/typo-suggestion.stderr +++ b/src/test/ui/span/typo-suggestion.stderr @@ -10,5 +10,5 @@ error[E0425]: cannot find value `fob` in this scope 18 | println!("Hello {}", fob); | ^^^ did you mean `foo`? -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/vec-must-not-hide-type-from-dropck.stderr b/src/test/ui/span/vec-must-not-hide-type-from-dropck.stderr index 0efbd8472ae..f7c94ed9f73 100644 --- a/src/test/ui/span/vec-must-not-hide-type-from-dropck.stderr +++ b/src/test/ui/span/vec-must-not-hide-type-from-dropck.stderr @@ -19,5 +19,5 @@ error[E0597]: `c1` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/vec_refs_data_with_early_death.stderr b/src/test/ui/span/vec_refs_data_with_early_death.stderr index 0dee15b4231..282e5caf207 100644 --- a/src/test/ui/span/vec_refs_data_with_early_death.stderr +++ b/src/test/ui/span/vec_refs_data_with_early_death.stderr @@ -20,5 +20,5 @@ error[E0597]: `y` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/wf-method-late-bound-regions.stderr b/src/test/ui/span/wf-method-late-bound-regions.stderr index d5e663ff26d..a37b5d17aac 100644 --- a/src/test/ui/span/wf-method-late-bound-regions.stderr +++ b/src/test/ui/span/wf-method-late-bound-regions.stderr @@ -9,5 +9,5 @@ error[E0597]: `pointer` does not live long enough 33 | } | - borrowed value needs to live until here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/static-lifetime.stderr b/src/test/ui/static-lifetime.stderr index 89008828ac5..f73dff4f73d 100644 --- a/src/test/ui/static-lifetime.stderr +++ b/src/test/ui/static-lifetime.stderr @@ -6,5 +6,5 @@ error[E0477]: the type `std::borrow::Cow<'a, A>` does not fulfill the required l | = note: type must satisfy the static lifetime -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/suggestions/confuse-field-and-method/issue-18343.stderr b/src/test/ui/suggestions/confuse-field-and-method/issue-18343.stderr index b69d90cf8f7..0ca61127634 100644 --- a/src/test/ui/suggestions/confuse-field-and-method/issue-18343.stderr +++ b/src/test/ui/suggestions/confuse-field-and-method/issue-18343.stderr @@ -6,5 +6,5 @@ error[E0599]: no method named `closure` found for type `Obj<[closure@$DIR/issue- | = help: use `(o.closure)(...)` if you meant to call the function stored in the `closure` field -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/suggestions/confuse-field-and-method/issue-2392.stderr b/src/test/ui/suggestions/confuse-field-and-method/issue-2392.stderr index 21865323908..c6f134f118d 100644 --- a/src/test/ui/suggestions/confuse-field-and-method/issue-2392.stderr +++ b/src/test/ui/suggestions/confuse-field-and-method/issue-2392.stderr @@ -86,5 +86,5 @@ error[E0599]: no method named `f3` found for type `FuncContainer` in the current | = help: use `((*self.container).f3)(...)` if you meant to call the function stored in the `f3` field -error: aborting due to previous error(s) +error: aborting due to 11 previous errors diff --git a/src/test/ui/suggestions/confuse-field-and-method/issue-32128.stderr b/src/test/ui/suggestions/confuse-field-and-method/issue-32128.stderr index f1d8df81639..a45e70d48c9 100644 --- a/src/test/ui/suggestions/confuse-field-and-method/issue-32128.stderr +++ b/src/test/ui/suggestions/confuse-field-and-method/issue-32128.stderr @@ -6,5 +6,5 @@ error[E0599]: no method named `example` found for type `Example` in the current | = help: use `(demo.example)(...)` if you meant to call the function stored in the `example` field -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/suggestions/confuse-field-and-method/issue-33784.stderr b/src/test/ui/suggestions/confuse-field-and-method/issue-33784.stderr index 7918fc1e89d..d41f7cbdf56 100644 --- a/src/test/ui/suggestions/confuse-field-and-method/issue-33784.stderr +++ b/src/test/ui/suggestions/confuse-field-and-method/issue-33784.stderr @@ -22,5 +22,5 @@ error[E0599]: no method named `c_fn_ptr` found for type `&D` in the current scop | = help: use `(s.c_fn_ptr)(...)` if you meant to call the function stored in the `c_fn_ptr` field -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/suggestions/confuse-field-and-method/private-field.stderr b/src/test/ui/suggestions/confuse-field-and-method/private-field.stderr index 5b1c63822f9..94519266260 100644 --- a/src/test/ui/suggestions/confuse-field-and-method/private-field.stderr +++ b/src/test/ui/suggestions/confuse-field-and-method/private-field.stderr @@ -4,5 +4,5 @@ error[E0599]: no method named `dog_age` found for type `animal::Dog` in the curr 26 | let dog_age = dog.dog_age(); | ^^^^^^^ private field, not a method -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/suggestions/tuple-float-index.stderr b/src/test/ui/suggestions/tuple-float-index.stderr index 47a1b53cc60..8a121b14536 100644 --- a/src/test/ui/suggestions/tuple-float-index.stderr +++ b/src/test/ui/suggestions/tuple-float-index.stderr @@ -7,5 +7,5 @@ error: unexpected token: `1.1` | | unexpected token | help: try parenthesizing the first index `((1, (2, 3)).1).1` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/token/bounds-obj-parens.stderr b/src/test/ui/token/bounds-obj-parens.stderr index 15e4d4c72bc..4d60be15eca 100644 --- a/src/test/ui/token/bounds-obj-parens.stderr +++ b/src/test/ui/token/bounds-obj-parens.stderr @@ -4,5 +4,5 @@ error: expected one of `!` or `::`, found `` 15 | FAIL | ^^^^ expected one of `!` or `::` here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/token/issue-10636-2.stderr b/src/test/ui/token/issue-10636-2.stderr index 4b0b05ca65a..48bbeac75d3 100644 --- a/src/test/ui/token/issue-10636-2.stderr +++ b/src/test/ui/token/issue-10636-2.stderr @@ -24,5 +24,5 @@ error: expected expression, found `)` error[E0601]: main function not found -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/token/issue-41155.stderr b/src/test/ui/token/issue-41155.stderr index 56f71a29953..50a38da9d8c 100644 --- a/src/test/ui/token/issue-41155.stderr +++ b/src/test/ui/token/issue-41155.stderr @@ -14,5 +14,5 @@ error[E0412]: cannot find type `S` in this scope error[E0601]: main function not found -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/token/macro-incomplete-parse.stderr b/src/test/ui/token/macro-incomplete-parse.stderr index 054364b0048..6bce09af052 100644 --- a/src/test/ui/token/macro-incomplete-parse.stderr +++ b/src/test/ui/token/macro-incomplete-parse.stderr @@ -31,5 +31,5 @@ note: caused by the macro expansion here; the usage of `ignored_pat!` is likely 37 | ignored_pat!() => (), //~ NOTE caused by the macro expansion here | ^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/token/trailing-plus-in-bounds.stderr b/src/test/ui/token/trailing-plus-in-bounds.stderr index 5fe0b3594f6..c765a434b8a 100644 --- a/src/test/ui/token/trailing-plus-in-bounds.stderr +++ b/src/test/ui/token/trailing-plus-in-bounds.stderr @@ -4,5 +4,5 @@ error: expected one of `!` or `::`, found `` 19 | FAIL | ^^^^ expected one of `!` or `::` here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/transmute/main.stderr b/src/test/ui/transmute/main.stderr index c5d5a4ed8a6..a7fc0808e18 100644 --- a/src/test/ui/transmute/main.stderr +++ b/src/test/ui/transmute/main.stderr @@ -34,5 +34,5 @@ error[E0512]: transmute called with types of different sizes = note: source type: i32 (32 bits) = note: target type: Foo (0 bits) -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr b/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr index 61ee5cf6128..7f1929050bb 100644 --- a/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr +++ b/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr @@ -104,5 +104,5 @@ error[E0512]: transmute called with types of different sizes = note: source type: std::option::Option (64 bits) = note: target type: u32 (32 bits) -error: aborting due to previous error(s) +error: aborting due to 11 previous errors diff --git a/src/test/ui/transmute/transmute-type-parameters.stderr b/src/test/ui/transmute/transmute-type-parameters.stderr index bb21cfd3e4c..816c62812f3 100644 --- a/src/test/ui/transmute/transmute-type-parameters.stderr +++ b/src/test/ui/transmute/transmute-type-parameters.stderr @@ -52,5 +52,5 @@ error[E0512]: transmute called with types of different sizes = note: source type: std::option::Option (size can vary because of T) = note: target type: i32 (32 bits) -error: aborting due to previous error(s) +error: aborting due to 6 previous errors diff --git a/src/test/ui/type-check/assignment-in-if.stderr b/src/test/ui/type-check/assignment-in-if.stderr index 29439999273..a077f37eae6 100644 --- a/src/test/ui/type-check/assignment-in-if.stderr +++ b/src/test/ui/type-check/assignment-in-if.stderr @@ -55,5 +55,5 @@ error[E0308]: mismatched types = note: expected type `bool` found type `()` -error: aborting due to previous error(s) +error: aborting due to 5 previous errors diff --git a/src/test/ui/type-check/cannot_infer_local_or_array.stderr b/src/test/ui/type-check/cannot_infer_local_or_array.stderr index 007480dc44f..8c52bb5a1d3 100644 --- a/src/test/ui/type-check/cannot_infer_local_or_array.stderr +++ b/src/test/ui/type-check/cannot_infer_local_or_array.stderr @@ -6,5 +6,5 @@ error[E0282]: type annotations needed | | | consider giving `x` a type -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/type-check/cannot_infer_local_or_vec.stderr b/src/test/ui/type-check/cannot_infer_local_or_vec.stderr index 4650df5411b..4788fad2088 100644 --- a/src/test/ui/type-check/cannot_infer_local_or_vec.stderr +++ b/src/test/ui/type-check/cannot_infer_local_or_vec.stderr @@ -8,5 +8,5 @@ error[E0282]: type annotations needed | = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.stderr b/src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.stderr index 08b5ae4bbb6..ccffadebe9e 100644 --- a/src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.stderr +++ b/src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.stderr @@ -8,5 +8,5 @@ error[E0282]: type annotations needed | = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/type-check/issue-22897.stderr b/src/test/ui/type-check/issue-22897.stderr index b3c736c3b68..95684118851 100644 --- a/src/test/ui/type-check/issue-22897.stderr +++ b/src/test/ui/type-check/issue-22897.stderr @@ -4,5 +4,5 @@ error[E0282]: type annotations needed 14 | []; | ^^ cannot infer type for `[_; 0]` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/type-check/issue-40294.stderr b/src/test/ui/type-check/issue-40294.stderr index cd474b14193..bb3a371b26e 100644 --- a/src/test/ui/type-check/issue-40294.stderr +++ b/src/test/ui/type-check/issue-40294.stderr @@ -12,5 +12,5 @@ error[E0283]: type annotations required: cannot resolve `&'a T: Foo` | = note: required by `Foo` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/type-check/unknown_type_for_closure.stderr b/src/test/ui/type-check/unknown_type_for_closure.stderr index 200864dfbf7..afbd15ca486 100644 --- a/src/test/ui/type-check/unknown_type_for_closure.stderr +++ b/src/test/ui/type-check/unknown_type_for_closure.stderr @@ -4,5 +4,5 @@ error[E0282]: type annotations needed 12 | let x = |_| { }; | ^ consider giving this closure parameter a type -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/tools/cargo b/src/tools/cargo index 534ce68621c..eb6cf012a6c 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 534ce68621ce4feec0b7e8627cfd3b077d4f3900 +Subproject commit eb6cf012a6cc23c9c89c4009564de9fccc38b9cb diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs index 29ca54fda8d..0b9b9599be6 100644 --- a/src/tools/compiletest/src/errors.rs +++ b/src/tools/compiletest/src/errors.rs @@ -35,7 +35,7 @@ impl FromStr for ErrorKind { "ERROR" => Ok(ErrorKind::Error), "NOTE" => Ok(ErrorKind::Note), "SUGGESTION" => Ok(ErrorKind::Suggestion), - "WARN" => Ok(ErrorKind::Warning), + "WARN" | "WARNING" => Ok(ErrorKind::Warning), _ => Err(()), } @@ -95,7 +95,7 @@ pub fn load_errors(testfile: &Path, cfg: Option<&str>) -> Vec { let tag = match cfg { Some(rev) => format!("//[{}]~", rev), - None => format!("//~"), + None => "//~".to_string(), }; rdr.lines() @@ -153,7 +153,7 @@ fn parse_expected(last_nonfollow_error: Option, let msg = msg.trim().to_owned(); let (which, line_num) = if follow { - assert!(adjusts == 0, "use either //~| or //~^, not both."); + assert_eq!(adjusts, 0, "use either //~| or //~^, not both."); let line_num = last_nonfollow_error.expect("encountered //~| without \ preceding //~^ line."); (FollowPrevious(line_num), line_num) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index aa33580b337..5ac60d8f2c8 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -258,7 +258,7 @@ impl TestProps { check_stdout: false, no_prefer_dynamic: false, pretty_expanded: false, - pretty_mode: format!("normal"), + pretty_mode: "normal".to_string(), pretty_compare_only: false, forbid_output: vec![], incremental_dir: None, @@ -381,14 +381,11 @@ impl TestProps { } }); - for key in vec!["RUST_TEST_NOCAPTURE", "RUST_TEST_THREADS"] { - match env::var(key) { - Ok(val) => { - if self.exec_env.iter().find(|&&(ref x, _)| *x == key).is_none() { - self.exec_env.push((key.to_owned(), val)) - } + for key in &["RUST_TEST_NOCAPTURE", "RUST_TEST_THREADS"] { + if let Ok(val) = env::var(key) { + if self.exec_env.iter().find(|&&(ref x, _)| x == key).is_none() { + self.exec_env.push(((*key).to_owned(), val)) } - Err(..) => {} } } } @@ -409,7 +406,7 @@ fn iter_header(testfile: &Path, cfg: Option<&str>, it: &mut FnMut(&str)) { return; } else if ln.starts_with("//[") { // A comment like `//[foo]` is specific to revision `foo` - if let Some(close_brace) = ln.find("]") { + if let Some(close_brace) = ln.find(']') { let lncfg = &ln[3..close_brace]; let matches = match cfg { Some(s) => s == &lncfg[..], @@ -521,12 +518,10 @@ impl Config { fn parse_pp_exact(&self, line: &str, testfile: &Path) -> Option { if let Some(s) = self.parse_name_value_directive(line, "pp-exact") { Some(PathBuf::from(&s)) + } else if self.parse_name_directive(line, "pp-exact") { + testfile.file_name().map(PathBuf::from) } else { - if self.parse_name_directive(line, "pp-exact") { - testfile.file_name().map(PathBuf::from) - } else { - None - } + None } } @@ -554,9 +549,7 @@ impl Config { pub fn lldb_version_to_int(version_string: &str) -> isize { let error_string = format!("Encountered LLDB version string with unexpected format: {}", version_string); - let error_string = error_string; - let major: isize = version_string.parse().ok().expect(&error_string); - return major; + version_string.parse().expect(&error_string) } fn expand_variables(mut value: String, config: &Config) -> String { diff --git a/src/tools/compiletest/src/json.rs b/src/tools/compiletest/src/json.rs index 06cbd9a3df4..23782c3ccc9 100644 --- a/src/tools/compiletest/src/json.rs +++ b/src/tools/compiletest/src/json.rs @@ -65,7 +65,7 @@ pub fn parse_output(file_name: &str, output: &str, proc_res: &ProcRes) -> Vec Vec { // The compiler sometimes intermingles non-JSON stuff into the // output. This hack just skips over such lines. Yuck. - if line.chars().next() == Some('{') { + if line.starts_with('{') { match json::decode::(line) { Ok(diagnostic) => { let mut expected_errors = vec![]; diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index c88ffba357a..cc42544ef02 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -168,7 +168,7 @@ pub fn parse_config(args: Vec ) -> Config { src_base: opt_path(matches, "src-base"), build_base: opt_path(matches, "build-base"), stage_id: matches.opt_str("stage-id").unwrap(), - mode: matches.opt_str("mode").unwrap().parse().ok().expect("invalid mode"), + mode: matches.opt_str("mode").unwrap().parse().expect("invalid mode"), run_ignored: matches.opt_present("ignored"), filter: matches.free.first().cloned(), filter_exact: matches.opt_present("exact"), @@ -208,7 +208,7 @@ pub fn parse_config(args: Vec ) -> Config { pub fn log_config(config: &Config) { let c = config; - logv(c, format!("configuration:")); + logv(c, "configuration:".to_string()); logv(c, format!("compile_lib_path: {:?}", config.compile_lib_path)); logv(c, format!("run_lib_path: {:?}", config.run_lib_path)); logv(c, format!("rustc_path: {:?}", config.rustc_path.display())); @@ -238,10 +238,10 @@ pub fn log_config(config: &Config) { config.adb_device_status)); logv(c, format!("verbose: {}", config.verbose)); logv(c, format!("quiet: {}", config.quiet)); - logv(c, format!("\n")); + logv(c, "\n".to_string()); } -pub fn opt_str<'a>(maybestr: &'a Option) -> &'a str { +pub fn opt_str(maybestr: &Option) -> &str { match *maybestr { None => "(none)", Some(ref s) => s, @@ -465,17 +465,16 @@ pub fn make_test(config: &Config, testpaths: &TestPaths) -> test::TestDescAndFn }; // Debugging emscripten code doesn't make sense today - let mut ignore = early_props.ignore || !up_to_date(config, testpaths, &early_props); - if (config.mode == DebugInfoGdb || config.mode == DebugInfoLldb) && - config.target.contains("emscripten") { - ignore = true; - } + let ignore = early_props.ignore || !up_to_date(config, testpaths, &early_props) || + (config.mode == DebugInfoGdb || config.mode == DebugInfoLldb) && + config.target.contains("emscripten"); test::TestDescAndFn { desc: test::TestDesc { name: make_test_name(config, testpaths), ignore: ignore, should_panic: should_panic, + allow_fail: false, }, testfn: make_test_closure(config, testpaths), } @@ -487,7 +486,7 @@ fn stamp(config: &Config, testpaths: &TestPaths) -> PathBuf { .to_str().unwrap(), config.stage_id); config.build_base.canonicalize() - .unwrap_or(config.build_base.clone()) + .unwrap_or_else(|_| config.build_base.clone()) .join(stamp_name) } @@ -512,7 +511,7 @@ fn up_to_date(config: &Config, testpaths: &TestPaths, props: &EarlyProps) -> boo fn mtime(path: &Path) -> FileTime { fs::metadata(path).map(|f| { FileTime::from_last_modification_time(&f) - }).unwrap_or(FileTime::zero()) + }).unwrap_or_else(|_| FileTime::zero()) } pub fn make_test_name(config: &Config, testpaths: &TestPaths) -> test::TestName { @@ -560,7 +559,7 @@ fn analyze_gdb(gdb: Option) -> (Option, Option, bool) { let gdb_native_rust = version.map_or(false, |v| v >= MIN_GDB_WITH_RUST); - return (Some(gdb.to_owned()), version, gdb_native_rust); + (Some(gdb.to_owned()), version, gdb_native_rust) } fn extract_gdb_version(full_version_line: &str) -> Option { @@ -600,7 +599,8 @@ fn extract_gdb_version(full_version_line: &str) -> Option { Some(idx) => if line.as_bytes()[idx] == b'.' { let patch = &line[idx + 1..]; - let patch_len = patch.find(|c: char| !c.is_digit(10)).unwrap_or(patch.len()); + let patch_len = patch.find(|c: char| !c.is_digit(10)) + .unwrap_or_else(|| patch.len()); let patch = &patch[..patch_len]; let patch = if patch_len > 3 || patch_len == 0 { None } else { Some(patch) }; diff --git a/src/tools/compiletest/src/procsrv.rs b/src/tools/compiletest/src/procsrv.rs index dbda8f4d802..35f6ed243fe 100644 --- a/src/tools/compiletest/src/procsrv.rs +++ b/src/tools/compiletest/src/procsrv.rs @@ -9,7 +9,6 @@ // except according to those terms. use std::env; -use std::ffi::OsString; use std::io::prelude::*; use std::io; use std::path::PathBuf; @@ -31,7 +30,7 @@ fn add_target_env(cmd: &mut Command, lib_path: &str, aux_path: Option<&str>) { // Need to be sure to put both the lib_path and the aux path in the dylib // search path for the child. let var = dylib_env_var(); - let mut path = env::split_paths(&env::var_os(var).unwrap_or(OsString::new())) + let mut path = env::split_paths(&env::var_os(var).unwrap_or_default()) .collect::>(); if let Some(p) = aux_path { path.insert(0, PathBuf::from(p)) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 0692e07253f..2254d6d23a8 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -68,7 +68,7 @@ pub fn run(config: Config, testpaths: &TestPaths) { } else { for revision in &base_props.revisions { let mut revision_props = base_props.clone(); - revision_props.load_from(&testpaths.file, Some(&revision), &config); + revision_props.load_from(&testpaths.file, Some(revision), &config); let rev_cx = TestCx { config: &config, props: &revision_props, @@ -81,7 +81,7 @@ pub fn run(config: Config, testpaths: &TestPaths) { base_cx.complete_all(); - File::create(::stamp(&config, &testpaths)).unwrap(); + File::create(::stamp(&config, testpaths)).unwrap(); } struct TestCx<'test> { @@ -101,9 +101,8 @@ impl<'test> TestCx<'test> { /// invoked once before any revisions have been processed fn init_all(&self) { assert!(self.revision.is_none(), "init_all invoked for a revision"); - match self.config.mode { - Incremental => self.init_incremental_test(), - _ => { } + if let Incremental = self.config.mode { + self.init_incremental_test() } } @@ -111,7 +110,7 @@ impl<'test> TestCx<'test> { /// revisions, exactly once, with revision == None). fn run_revision(&self) { match self.config.mode { - CompileFail => self.run_cfail_test(), + CompileFail | ParseFail => self.run_cfail_test(), RunFail => self.run_rfail_test(), RunPass => self.run_rpass_test(), @@ -352,10 +351,10 @@ impl<'test> TestCx<'test> { aux_dir.to_str().unwrap().to_owned()]; args.extend(self.split_maybe_args(&self.config.target_rustcflags)); args.extend(self.props.compile_flags.iter().cloned()); - return ProcArgs { + ProcArgs { prog: self.config.rustc_path.to_str().unwrap().to_owned(), args: args, - }; + } } fn compare_source(&self, @@ -407,17 +406,17 @@ actual:\n\ aux_dir.to_str().unwrap().to_owned()]; if let Some(revision) = self.revision { args.extend(vec![ - format!("--cfg"), - format!("{}", revision), + "--cfg".to_string(), + revision.to_string(), ]); } args.extend(self.split_maybe_args(&self.config.target_rustcflags)); args.extend(self.props.compile_flags.iter().cloned()); // FIXME (#9639): This needs to handle non-utf8 paths - return ProcArgs { + ProcArgs { prog: self.config.rustc_path.to_str().unwrap().to_owned(), args: args, - }; + } } fn run_debuginfo_gdb_test(&self) { @@ -692,7 +691,7 @@ actual:\n\ } if !debugger_run_result.status.success() { - self.fatal("gdb failed to execute"); + self.fatal_proc_rec("gdb failed to execute", &debugger_run_result); } self.check_debugger_output(&debugger_run_result, &check_lines); @@ -708,7 +707,7 @@ actual:\n\ } } - return None; + None } fn run_debuginfo_lldb_test(&self) { @@ -875,13 +874,13 @@ actual:\n\ for &(ref command_directive, ref check_directive) in &directives { self.config.parse_name_value_directive( &line, - &command_directive).map(|cmd| { + command_directive).map(|cmd| { commands.push(cmd) }); self.config.parse_name_value_directive( &line, - &check_directive).map(|cmd| { + check_directive).map(|cmd| { check_lines.push(cmd) }); } @@ -962,8 +961,7 @@ actual:\n\ (line, 0) }; - for fragment_index in first_fragment .. check_fragments.len() { - let current_fragment = check_fragments[fragment_index]; + for current_fragment in &check_fragments[first_fragment..] { match rest.find(current_fragment) { Some(pos) => { rest = &rest[pos + current_fragment.len() .. ]; @@ -976,7 +974,7 @@ actual:\n\ return false; } - return true; + true } } @@ -1059,7 +1057,7 @@ actual:\n\ let expect_note = expected_errors.iter().any(|ee| ee.kind == Some(ErrorKind::Note)); // Parse the JSON output from the compiler and extract out the messages. - let actual_errors = json::parse_output(&file_name, &proc_res.stderr, &proc_res); + let actual_errors = json::parse_output(&file_name, &proc_res.stderr, proc_res); let mut unexpected = Vec::new(); let mut found = vec![false; expected_errors.len()]; for actual_error in &actual_errors { @@ -1092,7 +1090,7 @@ actual:\n\ .map_or(String::from("message"), |k| k.to_string()), actual_error.msg)); - unexpected.push(actual_error.clone()); + unexpected.push(actual_error); } } } @@ -1110,20 +1108,20 @@ actual:\n\ .map_or("message".into(), |k| k.to_string()), expected_error.msg)); - not_found.push(expected_error.clone()); + not_found.push(expected_error); } } - if unexpected.len() > 0 || not_found.len() > 0 { + if !unexpected.is_empty() || !not_found.is_empty() { self.error( &format!("{} unexpected errors found, {} expected errors not found", unexpected.len(), not_found.len())); - print!("status: {}\ncommand: {}\n", + println!("status: {}\ncommand: {}", proc_res.status, proc_res.cmdline); - if unexpected.len() > 0 { + if !unexpected.is_empty() { println!("unexpected errors (from JSON output): {:#?}\n", unexpected); } - if not_found.len() > 0 { + if !not_found.is_empty() { println!("not found errors (from test file): {:#?}\n", not_found); } panic!(); @@ -1142,9 +1140,9 @@ actual:\n\ match actual_error.kind { Some(ErrorKind::Help) => expect_help, Some(ErrorKind::Note) => expect_note, - Some(ErrorKind::Error) => true, + Some(ErrorKind::Error) | Some(ErrorKind::Warning) => true, - Some(ErrorKind::Suggestion) => false, + Some(ErrorKind::Suggestion) | None => false } } @@ -1287,7 +1285,8 @@ actual:\n\ self.config); let mut crate_type = if aux_props.no_prefer_dynamic { Vec::new() - } else { + } else if (self.config.target.contains("musl") && !aux_props.force_host) || + self.config.target.contains("emscripten") { // We primarily compile all auxiliary libraries as dynamic libraries // to avoid code size bloat and large binaries as much as possible // for the test suite (otherwise including libstd statically in all @@ -1297,13 +1296,9 @@ actual:\n\ // dynamic libraries so we just go back to building a normal library. Note, // however, that for MUSL if the library is built with `force_host` then // it's ok to be a dylib as the host should always support dylibs. - if (self.config.target.contains("musl") && !aux_props.force_host) || - self.config.target.contains("emscripten") - { - vec!["--crate-type=lib".to_owned()] - } else { - vec!["--crate-type=dylib".to_owned()] - } + vec!["--crate-type=lib".to_owned()] + } else { + vec!["--crate-type=dylib".to_owned()] }; crate_type.extend(extra_link_args.clone()); let aux_output = { @@ -1344,7 +1339,7 @@ actual:\n\ lib_path: &str, aux_path: Option<&str>, input: Option) -> ProcRes { - return self.program_output(lib_path, prog, aux_path, args, procenv, input); + self.program_output(lib_path, prog, aux_path, args, procenv, input) } fn make_compile_args(&self, @@ -1367,7 +1362,7 @@ actual:\n\ // Optionally prevent default --target if specified in test compile-flags. let custom_target = self.props.compile_flags .iter() - .fold(false, |acc, ref x| acc || x.starts_with("--target")); + .fold(false, |acc, x| acc || x.starts_with("--target")); if !custom_target { args.extend(vec![ @@ -1377,14 +1372,14 @@ actual:\n\ if let Some(revision) = self.revision { args.extend(vec![ - format!("--cfg"), - format!("{}", revision), + "--cfg".to_string(), + revision.to_string(), ]); } if let Some(ref incremental_dir) = self.props.incremental_dir { args.extend(vec![ - format!("-Z"), + "-Z".to_string(), format!("incremental={}", incremental_dir.display()), ]); } @@ -1457,10 +1452,10 @@ actual:\n\ args.extend(self.split_maybe_args(&self.config.target_rustcflags)); } args.extend(self.props.compile_flags.iter().cloned()); - return ProcArgs { + ProcArgs { prog: self.config.rustc_path.to_str().unwrap().to_owned(), args: args, - }; + } } fn make_lib_name(&self, auxfile: &Path) -> PathBuf { @@ -1508,10 +1503,10 @@ actual:\n\ args.extend(self.split_maybe_args(&self.props.run_flags)); let prog = args.remove(0); - return ProcArgs { + ProcArgs { prog: prog, args: args, - }; + } } fn split_maybe_args(&self, argstr: &Option) -> Vec { @@ -1558,12 +1553,12 @@ actual:\n\ env, input).expect(&format!("failed to exec `{}`", prog)); self.dump_output(&out, &err); - return ProcRes { + ProcRes { status: status, stdout: out, stderr: err, cmdline: cmdline, - }; + } } fn make_cmdline(&self, libpath: &str, prog: &str, args: &[String]) -> String { @@ -1764,7 +1759,7 @@ actual:\n\ self.fatal_proc_rec("rustdoc failed!", &proc_res); } - if self.props.check_test_line_numbers_match == true { + if self.props.check_test_line_numbers_match { self.check_rustdoc_test_option(proc_res); } else { let root = self.find_rust_src_root().unwrap(); @@ -1791,7 +1786,7 @@ actual:\n\ .filter_map(|(line_nb, line)| { if (line.trim_left().starts_with("pub mod ") || line.trim_left().starts_with("mod ")) && - line.ends_with(";") { + line.ends_with(';') { if let Some(ref mut other_files) = other_files { other_files.push(line.rsplit("mod ") .next() @@ -1840,7 +1835,7 @@ actual:\n\ } let mut tested = 0; - for _ in res.stdout.split("\n") + for _ in res.stdout.split('\n') .filter(|s| s.starts_with("test ")) .inspect(|s| { let tmp: Vec<&str> = s.split(" - ").collect(); @@ -1853,7 +1848,7 @@ actual:\n\ iter.next(); let line = iter.next() .unwrap_or(")") - .split(")") + .split(')') .next() .unwrap_or("0") .parse() @@ -1873,7 +1868,7 @@ actual:\n\ self.fatal_proc_rec(&format!("No test has been found... {:?}", files), &res); } else { for (entry, v) in &files { - if v.len() != 0 { + if !v.is_empty() { self.fatal_proc_rec(&format!("Not found test at line{} \"{}\":{:?}", if v.len() > 1 { "s" } else { "" }, entry, v), &res); @@ -1916,11 +1911,10 @@ actual:\n\ .find(|ti| ti.name == expected_item.name); if let Some(actual_item) = actual_item_with_same_name { - if !expected_item.codegen_units.is_empty() { - // Also check for codegen units - if expected_item.codegen_units != actual_item.codegen_units { - wrong_cgus.push((expected_item.clone(), actual_item.clone())); - } + if !expected_item.codegen_units.is_empty() && + // Also check for codegen units + expected_item.codegen_units != actual_item.codegen_units { + wrong_cgus.push((expected_item.clone(), actual_item.clone())); } } else { missing.push(expected_item.string.clone()); @@ -2005,7 +1999,7 @@ actual:\n\ let cgus = if parts.len() > 1 { let cgus_str = parts[1]; - cgus_str.split(" ") + cgus_str.split(' ') .map(str::trim) .filter(|s| !s.is_empty()) .map(str::to_owned) @@ -2323,7 +2317,7 @@ actual:\n\ } } - fn compare_mir_test_output(&self, test_name: &str, expected_content: &Vec<&str>) { + fn compare_mir_test_output(&self, test_name: &str, expected_content: &[&str]) { let mut output_file = PathBuf::new(); output_file.push(self.get_mir_dump_dir()); output_file.push(test_name); diff --git a/src/tools/rls b/src/tools/rls index d26fd6f089a..4c0a8b63d61 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit d26fd6f089a4e7f1216a03a6d604bee33b2301dc +Subproject commit 4c0a8b63d61942349c18727409b2a600446e02d6