diff options
Diffstat (limited to 'src')
503 files changed, 8943 insertions, 6602 deletions
diff --git a/src/Cargo.lock b/src/Cargo.lock index 4f979b7e9f4..b265ee5765a 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -19,9 +19,8 @@ dependencies = [ name = "alloc_jemalloc" version = "0.0.0" dependencies = [ - "alloc_system 0.0.0", "build_helper 0.1.0", - "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "compiler_builtins 0.0.0", "core 0.0.0", "libc 0.0.0", @@ -79,6 +78,19 @@ dependencies = [ ] [[package]] +name = "assert_cli" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "skeptic 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "atty" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -90,7 +102,7 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", @@ -105,7 +117,7 @@ name = "backtrace-sys" version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -133,8 +145,8 @@ name = "bootstrap" version = "0.0.0" dependencies = [ "build_helper 0.1.0", - "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -142,11 +154,11 @@ dependencies = [ "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "petgraph 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -162,9 +174,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "build-manifest" version = "0.1.0" dependencies = [ - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -172,13 +184,18 @@ name = "build_helper" version = "0.1.0" [[package]] +name = "bytecount" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "byteorder" version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cargo" -version = "0.27.0" +version = "0.28.0" dependencies = [ "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -187,10 +204,10 @@ dependencies = [ "crates-io 0.16.0", "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "curl 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "curl 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "filetime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "git2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -210,27 +227,29 @@ dependencies = [ "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tar 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tar 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cargo_metadata" -version = "0.2.3" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -240,9 +259,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -251,7 +270,7 @@ version = "0.1.0" [[package]] name = "cc" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -286,18 +305,18 @@ dependencies = [ [[package]] name = "clippy" -version = "0.0.193" +version = "0.0.195" dependencies = [ "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "clippy-mini-macro-test 0.2.0", - "clippy_lints 0.0.193", + "clippy_lints 0.0.195", "compiletest_rs 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "derive-new 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -306,7 +325,7 @@ version = "0.2.0" [[package]] name = "clippy_lints" -version = "0.0.193" +version = "0.0.195" dependencies = [ "if_chain 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -314,21 +333,29 @@ dependencies = [ "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cmake" -version = "0.1.29" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "colored" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -351,7 +378,7 @@ dependencies = [ name = "compiler_builtins" version = "0.0.0" dependencies = [ - "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -360,16 +387,16 @@ name = "compiletest" version = "0.0.0" dependencies = [ "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -384,10 +411,10 @@ dependencies = [ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -423,11 +450,11 @@ dependencies = [ name = "crates-io" version = "0.16.0" dependencies = [ - "curl 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "curl 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -474,36 +501,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "commoncrypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.6 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "curl" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "curl-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "curl-sys 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.27 (registry+https://github.com/rust-lang/crates.io-index)", - "schannel 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "socket2 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.28 (registry+https://github.com/rust-lang/crates.io-index)", + "schannel 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "curl-sys" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.27 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.28 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -536,6 +563,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "difference" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "difference" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -559,16 +591,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "elasticlunr-rs" -version = "1.0.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "strum 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "strum_macros 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -594,7 +626,7 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.5.6" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -605,11 +637,16 @@ dependencies = [ ] [[package]] +name = "environment" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "error-chain" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -624,7 +661,7 @@ name = "failure" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -653,6 +690,16 @@ dependencies = [ ] [[package]] +name = "filetime" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "find_all_refs_no_cfg_test" version = "0.1.0" @@ -748,7 +795,7 @@ dependencies = [ "libgit2-sys 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.27 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.28 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -757,7 +804,7 @@ name = "git2-curl" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "curl 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "curl 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "git2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -795,8 +842,8 @@ dependencies = [ "pest_derive 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -887,7 +934,7 @@ dependencies = [ "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tar 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)", + "tar 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "xz2 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -933,9 +980,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -949,13 +996,13 @@ dependencies = [ [[package]] name = "languageserver-types" -version = "0.35.0" +version = "0.36.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.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -993,13 +1040,13 @@ name = "libgit2-sys" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "curl-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", + "curl-sys 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.27 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.28 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1008,10 +1055,10 @@ name = "libssh2-sys" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.27 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.28 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1020,10 +1067,10 @@ name = "libz-sys" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1059,7 +1106,7 @@ name = "lzma-sys" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1082,9 +1129,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1097,14 +1144,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "mdbook" -version = "0.1.5" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ammonia 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", - "elasticlunr-rs 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "elasticlunr-rs 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "handlebars 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1114,12 +1161,12 @@ dependencies = [ "open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "toml-query 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1141,7 +1188,7 @@ name = "miniz-sys" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1150,7 +1197,7 @@ name = "miow" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "socket2 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1159,9 +1206,11 @@ name = "miri" version = "0.1.0" dependencies = [ "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "compiletest_rs 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1215,14 +1264,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl" -version = "0.10.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.27 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.28 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1232,13 +1281,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl-sys" -version = "0.9.27" +version = "0.9.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1386,7 +1435,7 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "0.3.1" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1406,7 +1455,7 @@ dependencies = [ name = "profiler_builtins" version = "0.0.0" dependencies = [ - "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "compiler_builtins 0.0.0", "core 0.0.0", ] @@ -1448,7 +1497,7 @@ name = "quote" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1457,7 +1506,7 @@ version = "2.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1543,14 +1592,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.5.3" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1566,7 +1615,7 @@ version = "0.1.0" [[package]] name = "remove_dir_all" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1576,39 +1625,39 @@ dependencies = [ name = "rls" version = "0.126.0" dependencies = [ - "cargo 0.27.0", + "cargo 0.28.0", "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "clippy_lints 0.0.193", - "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "clippy_lints 0.0.195", + "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "json 0.11.13 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "languageserver-types 0.35.0 (registry+https://github.com/rust-lang/crates.io-index)", + "languageserver-types 0.36.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "racer 2.0.13 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-analysis 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-blacklist 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-analysis 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-blacklist 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rls-data 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-rustc 0.2.2 (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.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustfmt-nightly 0.4.2", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "rustfmt-nightly 0.6.0", + "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rls-analysis" -version = "0.11.3" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "derive-new 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "radix_trie 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rls-data 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1617,7 +1666,7 @@ dependencies = [ [[package]] name = "rls-blacklist" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1627,8 +1676,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1642,8 +1691,8 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1660,7 +1709,7 @@ name = "rustbook" version = "0.1.0" dependencies = [ "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", - "mdbook 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "mdbook 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1668,7 +1717,7 @@ name = "rustc" version = "0.0.0" dependencies = [ "arena 0.0.0", - "backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1691,7 +1740,7 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_cratesio_shim" -version = "103.0.0" +version = "110.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1700,7 +1749,7 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_data_structures" -version = "103.0.0" +version = "110.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1708,20 +1757,20 @@ dependencies = [ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_errors" -version = "103.0.0" +version = "110.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1729,32 +1778,32 @@ dependencies = [ [[package]] name = "rustc-ap-serialize" -version = "103.0.0" +version = "110.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-syntax" -version = "103.0.0" +version = "110.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "103.0.0" +version = "110.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1803,7 +1852,7 @@ dependencies = [ "alloc 0.0.0", "alloc_system 0.0.0", "build_helper 0.1.0", - "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", "compiler_builtins 0.0.0", "core 0.0.0", ] @@ -1867,7 +1916,7 @@ version = "0.0.0" dependencies = [ "ar 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "arena 0.0.0", - "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "graphviz 0.0.0", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", @@ -1937,7 +1986,7 @@ version = "0.0.0" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "build_helper 0.1.0", - "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_cratesio_shim 0.0.0", ] @@ -1949,7 +1998,7 @@ dependencies = [ "alloc 0.0.0", "alloc_system 0.0.0", "build_helper 0.1.0", - "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", "compiler_builtins 0.0.0", "core 0.0.0", ] @@ -1999,7 +2048,7 @@ dependencies = [ "alloc 0.0.0", "alloc_system 0.0.0", "build_helper 0.1.0", - "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", "compiler_builtins 0.0.0", "core 0.0.0", ] @@ -2090,8 +2139,8 @@ name = "rustc_trans" version = "0.0.0" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2139,7 +2188,7 @@ dependencies = [ "alloc 0.0.0", "alloc_system 0.0.0", "build_helper 0.1.0", - "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", "compiler_builtins 0.0.0", "core 0.0.0", ] @@ -2181,30 +2230,40 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "0.4.2" +version = "0.6.0" dependencies = [ + "assert_cli 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "derive-new 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.6 (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.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "same-file" +version = "0.1.3" +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)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "same-file" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ @@ -2213,7 +2272,7 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2232,11 +2291,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "semver" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2246,26 +2314,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.37" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.37" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive_internals 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive_internals 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive_internals" -version = "0.23.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2274,18 +2342,18 @@ name = "serde_ignored" version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.13" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2308,13 +2376,28 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "skeptic" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytecount 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "smallvec" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "socket2" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2367,7 +2450,7 @@ dependencies = [ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2394,6 +2477,20 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "strum" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "strum_macros" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "syn" version = "0.11.11" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2418,7 +2515,7 @@ name = "syn" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2514,13 +2611,13 @@ dependencies = [ [[package]] name = "tar" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "filetime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "xattr 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2529,18 +2626,18 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "remove_dir_all 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tempfile" -version = "3.0.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "remove_dir_all 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2623,9 +2720,9 @@ dependencies = [ name = "tidy" version = "0.1.0" dependencies = [ - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2648,10 +2745,10 @@ dependencies = [ [[package]] name = "toml" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2663,7 +2760,7 @@ dependencies = [ "is-match 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2757,7 +2854,7 @@ name = "url_serde" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2782,7 +2879,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "vcpkg" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2797,6 +2894,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "walkdir" +version = "1.0.7" +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)", + "same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "walkdir" version = "2.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ @@ -2847,7 +2954,7 @@ version = "0.1.0" [[package]] name = "xattr" -version = "0.1.11" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2872,21 +2979,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum ar 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "35c7a5669cb64f085739387e1308b74e6d44022464b7f1b63bbd4ceb6379ec31" "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" +"checksum assert_cli 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "72342c21057a3cb5f7c2d849bf7999a83795434dd36d74fa8c24680581bd1930" "checksum atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "af80143d6f7608d746df1520709e5d141c96f240b0e62b0aa41bdfb53374d9d4" -"checksum backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbbf59b1c43eefa8c3ede390fcc36820b4999f7914104015be25025e0d62af2" +"checksum backtrace 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbe525f66f42d207968308ee86bc2dd60aa5fab535b22e616323a173d097d8e" "checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" "checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32" +"checksum bytecount 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "af27422163679dea46a1a7239dffff64d3dcdc3ba5fe9c49c789fbfe0eb949de" "checksum byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "73b5bdfe7ee3ad0b99c9801d58807a9dbc9e09196365b0203853b99889ab3c87" -"checksum cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "be1057b8462184f634c3a208ee35b0f935cfd94b694b26deadccd98732088d7b" +"checksum cargo_metadata 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1f56ec3e469bca7c276f2eea015aa05c5e381356febdbb0683c2580189604537" "checksum cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ebd6272a2ca4fd39dbabbd6611eb03df45c2259b3b80b39a9ff8fbdcf42a4b3" -"checksum cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "2b4911e4bdcb4100c7680e7e854ff38e23f1b34d4d9e079efae3da2801341ffc" +"checksum cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "8b9d2900f78631a5876dc5d6c9033ede027253efcd33dd36b1309fc6cab97ee0" "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" "checksum chrono 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ba5f60682a4c264e7f8d77b82e7788938a76befdf949d4a98026d19099c9d873" "checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536" -"checksum cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "56d741ea7a69e577f6d06b36b7dff4738f680593dc27a701ffa8506b73ce28bb" +"checksum cmake 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "5cf678ceebedde428000cb3a34465cf3606d1a48da17014948a916deac39da7c" +"checksum colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0aa3473e85a3161b59845d6096b289bb577874cafeaf75ea1b1beaa6572c7fc" "checksum commoncrypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d056a8586ba25a1e4d61cb090900e495952c7886786fc55f909ab2f819b69007" "checksum commoncrypto-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fed34f46747aa73dfaa578069fd8279d2818ade2b55f38f22a9401c7f4083e2" "checksum compiletest_rs 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "608d9d3ccc45b63bf337d2ff5e65def5a5a52c187122232509f6b72707f61b1b" @@ -2897,23 +3007,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" "checksum crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "09de9ee0fc255ace04c7fa0763c9395a945c37c8292bb554f8d48361d1dcf1b4" -"checksum curl 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b70fd6394677d3c0e239ff4be6f2b3176e171ffd1c23ffdc541e78dea2b8bb5e" -"checksum curl-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46e49c7125131f5afaded06944d6888b55cbdf8eba05dae73c954019b907961" +"checksum curl 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "aaf20bbe084f285f215eef2165feed70d6b75ba29cad24469badb853a4a287d0" +"checksum curl-sys 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f3f7738d877ec81040305d5bb91976ac594f564f5e455dc02a29a23c1d00fe6f" "checksum debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3" "checksum derive-new 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6fcb923bab47a948f1b01cec2f758fdebba95c9ebc255458654b2b88efe59d71" "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" +"checksum difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3304d19798a8e067e48d8e69b2c37f0b5e9b4e462504ad9e27e9f3fce02bba8" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" -"checksum elasticlunr-rs 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "19ab5f8db0ffb76b5d87454566ceb502c3650e29057c053f93e884d3b884e344" +"checksum elasticlunr-rs 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4511b63d69dd5d31e8e29aed2c132c413f87acea8035d0584801feaab9dd1f0f" "checksum ena 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f8b449f3b18c89d2dbe40548d2ee4fa58ea0a08b761992da6ecb9788e4688834" "checksum endian-type 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" "checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180" -"checksum env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0561146661ae44c579e993456bc76d11ce1e0c7d745e57b2fa7146b6e49fa2ad" +"checksum env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "be27f8ea102a7182093a80d98f0b78623b580eda8791cbe8e2345fe6e57567a6" +"checksum environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f4b14e20978669064c33b4c1e0fb4083412e40fe56cbea2eae80fd7591503ee" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" "checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82" "checksum failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7cdda555bb90c9bb67a3b670a0f42de8e73f5981524123ad8578aafec8ddb8b" "checksum filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "714653f3e34871534de23771ac7b26e999651a0a228f47beb324dfdf1dd4b10f" +"checksum filetime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08530a39af0bd442c40aabb9e854f442a83bd2403feb1ed58fbe982dec2385f3" "checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" "checksum flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fac2277e84e5e858483756647a9d0aa8d9a2b7cba517fd84325a0aaa69a0909" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" @@ -2944,7 +3057,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum json 0.11.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9ad0485404155f45cce53a40d4b2d6ac356418300daed05273d9e26f91c390be" "checksum jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ddf83704f4e79979a424d1082dd2c1e52683058056c9280efa19ac5f6bc9033c" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum languageserver-types 0.35.0 (registry+https://github.com/rust-lang/crates.io-index)" = "36e264ab825353617bbc80844717555be6e9e1d403474b1d0a3b8e190440b13e" +"checksum languageserver-types 0.36.0 (registry+https://github.com/rust-lang/crates.io-index)" = "174cdfb8bed13225bb419bec66ee1c970099c875688645f9c4a82e3af43ba69d" "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" "checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" "checksum lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6f08839bc70ef4a3fe1d566d5350f519c5912ea86be0df1740a7d247c7fc0ef" @@ -2960,7 +3073,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43" "checksum markup5ever 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfedc97d5a503e96816d10fedcd5b42f760b2e525ce2f7ec71f6a41780548475" "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" -"checksum mdbook 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "326d0861da5681a13c19a00952a56c254dd04f00eb944e506fdb36e93ae6f1ca" +"checksum mdbook 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "90b5a8d7e341ceee5db3882a06078d42661ddcfa2b3687319cc5da76ec4e782f" "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4" @@ -2972,9 +3085,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dee092fcdf725aee04dd7da1d21debff559237d49ef1cb3e69bcb8ece44c7364" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" "checksum open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c281318d992e4432cfa799969467003d05921582a7489a8325e37f8a450d5113" -"checksum openssl 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1636c9f1d78af9cbcc50e523bfff4a30274108aad5e86761afd4d31e4e184fa7" +"checksum openssl 0.10.6 (registry+https://github.com/rust-lang/crates.io-index)" = "63246f69962e8d5ef865f82a65241d6483c8a2905a1801e2f7feb5d187d51320" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-sys 0.9.27 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdc5c4a02e69ce65046f1763a0181107038e02176233acb0b3351d7cc588f9" +"checksum openssl-sys 0.9.28 (registry+https://github.com/rust-lang/crates.io-index)" = "0bbd90640b148b46305c1691eed6039b5c8509bed16991e3562a01eeb76902a3" "checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" "checksum parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd9d732f2de194336fb02fe11f9eed13d9e76f13f4315b4d88a14ca411750cd" @@ -2991,7 +3104,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" "checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6" "checksum proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cd07deb3c6d1d9ff827999c7f9b04cdfd66b1b17ae508e14fe47b620f2282ae0" -"checksum proc-macro2 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "388d7ea47318c5ccdeb9ba6312cee7d3f65dd2804be8580a170fce410d50b786" +"checksum proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "49b6a521dc81b643e9a51e0d1cf05df46d5a2f3c0280ea72bcb68276ba64a118" "checksum pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32" "checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4" "checksum quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45" @@ -3007,43 +3120,48 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "aec3f58d903a7d2a9dc2bf0e41a746f4530e0cab6b615494e058f67a3ef947fb" -"checksum regex-syntax 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b2550876c31dc914696a6c2e01cbce8afba79a93c8ae979d2fe051c0230b3756" -"checksum remove_dir_all 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dfc5b3ce5d5ea144bb04ebd093a9e14e9765bcfec866aecda9b6dec43b3d1e24" -"checksum rls-analysis 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fd4b9a3a3f2345854e39768e6425d1c893855da217183d1c0b3ff6f1664b6b6d" -"checksum rls-blacklist 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "156cee9c1750b2e97d404dd0506c4780b7a2d615164f49874013807fb3cbfe5e" +"checksum regex-syntax 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "bd90079345f4a4c3409214734ae220fd773c6f2e8a543d07370c6c1c369cfbfb" +"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" +"checksum rls-analysis 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b339561571efd8d2d4ae1b16eb27f760cad46907d49e9726242844dbbde14e79" +"checksum rls-blacklist 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e4a9cc2545ccb7e05b355bfe047b8039a6ec12270d5f3c996b766b340a50f7d2" "checksum rls-data 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bea04462e94b5512a78499837eecb7db182ff082144cd1b4bc32ef5d43de6510" "checksum rls-rustc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "885f66b92757420572cbb02e033d4a9558c7413ca9b7ac206f28fd58ffdb44ea" "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a" "checksum rls-vfs 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "be231e1e559c315bc60ced5ad2cc2d7a9c208ed7d4e2c126500149836fda19bb" -"checksum rustc-ap-rustc_cratesio_shim 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "463834ac5ea777cb56c073586675fac37292f8425aafb3757efca7e6a76545aa" -"checksum rustc-ap-rustc_data_structures 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d256eeab1b8639c2a1fd341e54f3613f8150bc262e4ec9361a29bbcb162906d" -"checksum rustc-ap-rustc_errors 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf6dd73033bb512845a6df347174c65ad430c92ecd35527e24d8bb186f5664ee" -"checksum rustc-ap-serialize 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "356d338dbe538c7d6428296872d5d68da8f091e34eb89bca3b3f245ed0785e5e" -"checksum rustc-ap-syntax 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0f02edede4ba70963a7dac2308876f03f76f9edd48a035e5abc8fa37c57a77c8" -"checksum rustc-ap-syntax_pos 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad8e50d4c38121fa8ded3ffbf94926ec74c95f24316c3b80de84fbfb42c005cf" +"checksum rustc-ap-rustc_cratesio_shim 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0256e318ad99c467d24bd7188f2d4a3028360621bb92d769b4b65fc44717d514" +"checksum rustc-ap-rustc_data_structures 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83430df7f76ea85c1f70fe145041576eee8fd5d77053bf426df24b480918d185" +"checksum rustc-ap-rustc_errors 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2b03f874277103039816f6467b1ff30a81b1d6a29d4de6efccefe4c488f6535a" +"checksum rustc-ap-serialize 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2e47cf949f06b0c7ab7566c2f69d49f28cb3ecf1bb8bf0bda48b1ba5b7945ae" +"checksum rustc-ap-syntax 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "625e6fb41fde299082cda3bceb08f81c9ba56b14a2ec737b4366f9c3c9be07d8" +"checksum rustc-ap-syntax_pos 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "474a23ef1a1245ae02c5fd6a1e9a0725ce6fd25ca2294703c03bddce041f867b" "checksum rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11fb43a206a04116ffd7cfcf9bcb941f8eb6cc7ff667272246b0a1c74259a3cb" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" +"checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7" "checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637" -"checksum schannel 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "fbaffce35eb61c5b00846e73128b0cd62717e7c0ec46abbec132370d013975b4" +"checksum schannel 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "85fd9df495640643ad2d00443b3d78aae69802ad488debab4f1dd52fc1806ade" "checksum scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8674d439c964889e2476f474a3bf198cc9e199e77499960893bac5de7e9218a4" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" +"checksum semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bee2bc909ab2d8d60dab26e8cad85b25d795b14603a0dcb627b78b9d30b6454b" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "d3bcee660dcde8f52c3765dd9ca5ee36b4bf35470a738eb0bd5a8752b0389645" -"checksum serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "f1711ab8b208541fa8de00425f6a577d90f27bb60724d2bb5fd911314af9668f" -"checksum serde_derive_internals 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "89b340a48245bc03ddba31d0ff1709c118df90edc6adabaca4aac77aea181cce" +"checksum serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "29465552c9b767d0cb44be3ddf4c3214be15d34975a7750f6cf4f409835f0248" +"checksum serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "fb88f3c93214390ed9ef3ad15ce303c36684a915a97a30883ac6ca261bf67dc7" +"checksum serde_derive_internals 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9d30c4596450fd7bbda79ef15559683f9a79ac0193ea819db90000d7e1cae794" "checksum serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "190e9765dcedb56be63b6e0993a006c7e3b071a016a304736e4a315dc01fb142" -"checksum serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "5c508584d9913df116b91505eec55610a2f5b16e9ed793c46e4d0152872b3e74" +"checksum serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7bf1cbb1387028a13739cb018ee0d9b3db534f22ca3c84a5904f7eadfde14e75" "checksum shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "170a13e64f2a51b77a45702ba77287f5c6829375b04a69cf2222acd17d0cfab9" "checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" +"checksum skeptic 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c8431f8fca168e2db4be547bd8329eac70d095dff1444fee4b0fa0fabc7df75a" "checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9" -"checksum socket2 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "71ebbe82fcdd697244ba7fe6e05e63b5c45910c3927e28469a04947494ff48d8" +"checksum socket2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ff606e0486e88f5fc6cfeb3966e434fb409abbc7a3ab495238f70a1ca97f789d" "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b" "checksum string_cache 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39cb4173bcbd1319da31faa5468a7e3870683d7a237150b0b0aaafd546f6ad12" "checksum string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "479cde50c3539481f33906a387f2bd17c8e87cb848c35b6021d41fb81ff9b4d7" "checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" +"checksum strum 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "099e21b5dd6dd07b5adcf8c4b723a7c0b7efd7a9359bf963d58c0caae8532545" +"checksum strum_macros 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0dd9bd569e88028750e3ae5c25616b8278ac16a8e61aba4339195c72396d49e1" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum syn 0.12.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97c05b8ebc34ddd6b967994d5c6e9852fa92f8b82b3858c39451f97346dcce5" "checksum syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "91b52877572087400e83d24b9178488541e3d535259e04ff17a63df1e5ceff59" @@ -3052,9 +3170,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e52bffe6202cfb67587784cf23e0ec5bf26d331eef4922a16d5c42e12aa1e9b" "checksum syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "955ef4b16af4c468e4680d1497f873ff288f557d338180649e18f915af5e15ac" "checksum syntex_syntax 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "76a302e717e348aa372ff577791c3832395650073b8d8432f8b3cb170b34afde" -"checksum tar 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)" = "1605d3388ceb50252952ffebab4b5dc43017ead7e4481b175961c283bb951195" +"checksum tar 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)" = "6af6b94659f9a571bf769a5b71f54079393585ee0bfdd71b691be22d7d6b1d18" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" -"checksum tempfile 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "439d9a7c00f98b1b5ee730039bf5b1f9203d508690e3c76b509e7ad59f8f7c99" +"checksum tempfile 3.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8cddbd26c5686ece823b507f304c8f188daef548b4cb753512d929ce478a093c" "checksum tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9de21546595a0873061940d994bbbc5c35f024ae4fd61ec5c5b159115684f508" "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" "checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561" @@ -3064,7 +3182,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" "checksum time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "a15375f1df02096fb3317256ce2cee6a1f42fc84ea5ad5fc8c421cfe40c73098" "checksum toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4" -"checksum toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7540f4ffc193e0d3c94121edb19b055670d369f77d5804db11ae053a45b6e7e" +"checksum toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a0263c6c02c4db6c8f7681f9fd35e90de799ebd4cfdeab77a38f4ff6b3d8c0d9" "checksum toml-query 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6854664bfc6df0360c695480836ee90e2d0c965f06db291d10be9344792d43e8" "checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" @@ -3081,9 +3199,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum userenv-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d28ea36bbd9192d75bd9fa9b39f96ddb986eaee824adae5d53b6e51919b2f3" "checksum utf-8 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1262dfab4c30d5cb7c07026be00ee343a6cf5027fdc0104a9160f354e5db75c" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" -"checksum vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0a7d8bed3178a8fb112199d466eeca9ed09a14ba8ad67718179b4fd5487d0b" +"checksum vcpkg 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7ed0f6789c8a85ca41bbc1c9d175422116a9869bd1cf31bb08e1493ecce60380" "checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +"checksum walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bb08f9e670fab86099470b97cd2b252d6527f0b3cc1401acdb595ffc9dd288ff" "checksum walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "63636bd0eb3d00ccb8b9036381b526efac53caf112b7783b730ab3f8e44da369" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3" @@ -3091,6 +3210,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb06499a3a4d44302791052df005d5232b927ed1a9658146d842165c4de7767" -"checksum xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "5f04de8a1346489a2f9e9bd8526b73d135ec554227b17568456e86aa35b6f3fc" +"checksum xattr 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "abb373b92de38a4301d66bec009929b4fb83120ea1c4a401be89dbe0b9777443" "checksum xz2 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "98df591c3504d014dd791d998123ed00a476c7e26dc6b2e873cb55c6ac9e59fa" "checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992" diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index d55627ffc18..b9c82127342 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -310,7 +310,8 @@ impl<'a> Builder<'a> { tool::Compiletest, tool::RemoteTestServer, tool::RemoteTestClient, tool::RustInstaller, tool::Cargo, tool::Rls, tool::Rustdoc, tool::Clippy, native::Llvm, tool::Rustfmt, tool::Miri, native::Lld), - Kind::Check => describe!(check::Std, check::Test, check::Rustc), + Kind::Check => describe!(check::Std, check::Test, check::Rustc, check::CodegenBackend, + check::Rustdoc), Kind::Test => describe!(test::Tidy, test::Bootstrap, test::Ui, test::RunPass, test::CompileFail, test::ParseFail, test::RunFail, test::RunPassValgrind, test::MirOpt, test::Codegen, test::CodegenUnits, test::Incremental, test::Debuginfo, @@ -552,6 +553,12 @@ impl<'a> Builder<'a> { .arg("--target") .arg(target); + // Set a flag for `check` so that certain build scripts can do less work + // (e.g. not building/requiring LLVM). + if cmd == "check" { + cargo.env("RUST_CHECK", "1"); + } + // If we were invoked from `make` then that's already got a jobserver // set up for us so no need to tell Cargo about jobs all over again. if env::var_os("MAKEFLAGS").is_none() && env::var_os("MFLAGS").is_none() { @@ -836,7 +843,7 @@ impl<'a> Builder<'a> { cargo } - /// Ensure that a given step is built, returning it's output. This will + /// Ensure that a given step is built, returning its output. This will /// cache the step, so it is safe (and good!) to call this as often as /// needed to ensure that all dependencies are built. pub fn ensure<S: Step>(&'a self, step: S) -> S::Output { diff --git a/src/bootstrap/cc_detect.rs b/src/bootstrap/cc_detect.rs index 8f393a4c573..698903f128d 100644 --- a/src/bootstrap/cc_detect.rs +++ b/src/bootstrap/cc_detect.rs @@ -79,8 +79,16 @@ pub fn find(build: &mut Build) { let mut cfg = cc::Build::new(); cfg.cargo_metadata(false).opt_level(2).warnings(false).debug(false) .target(&target).host(&build.build); - if target.contains("msvc") { - cfg.static_crt(true); + match build.crt_static(target) { + Some(a) => { cfg.static_crt(a); } + None => { + if target.contains("msvc") { + cfg.static_crt(true); + } + if target.contains("musl") { + cfg.static_flag(true); + } + } } let config = build.config.target_config.get(&target); @@ -97,8 +105,9 @@ pub fn find(build: &mut Build) { cc2ar(compiler.path(), &target) }; - build.verbose(&format!("CC_{} = {:?}", &target, compiler.path())); build.cc.insert(target, compiler); + build.verbose(&format!("CC_{} = {:?}", &target, build.cc(target))); + build.verbose(&format!("CFLAGS_{} = {:?}", &target, build.cflags(target))); if let Some(ar) = ar { build.verbose(&format!("AR_{} = {:?}", &target, ar)); build.ar.insert(target, ar); diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index adebd424d7e..64354ae29aa 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -10,10 +10,11 @@ //! Implementation of compiling the compiler and standard library, in "check" mode. -use compile::{run_cargo, std_cargo, test_cargo, rustc_cargo, add_to_sysroot}; +use compile::{run_cargo, std_cargo, test_cargo, rustc_cargo, rustc_cargo_env, add_to_sysroot}; use builder::{RunConfig, Builder, ShouldRun, Step}; +use tool::{self, prepare_tool_cargo}; use {Compiler, Mode}; -use cache::Interned; +use cache::{INTERNER, Interned}; use std::path::PathBuf; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -41,6 +42,7 @@ impl Step for Std { let out_dir = builder.stage_out(compiler, Mode::Libstd); builder.clear_if_dirty(&out_dir, &builder.rustc(compiler)); + let mut cargo = builder.cargo(compiler, Mode::Libstd, target, "check"); std_cargo(builder, &compiler, target, &mut cargo); @@ -105,6 +107,52 @@ impl Step for Rustc { } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct CodegenBackend { + pub target: Interned<String>, + pub backend: Interned<String>, +} + +impl Step for CodegenBackend { + type Output = (); + const ONLY_HOSTS: bool = true; + const DEFAULT: bool = true; + + fn should_run(run: ShouldRun) -> ShouldRun { + run.all_krates("rustc_trans") + } + + fn make_run(run: RunConfig) { + let backend = run.builder.config.rust_codegen_backends.get(0); + let backend = backend.cloned().unwrap_or_else(|| { + INTERNER.intern_str("llvm") + }); + run.builder.ensure(CodegenBackend { + target: run.target, + backend, + }); + } + + fn run(self, builder: &Builder) { + let compiler = builder.compiler(0, builder.config.build); + let target = self.target; + let backend = self.backend; + + let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "check"); + let features = builder.rustc_features().to_string(); + cargo.arg("--manifest-path").arg(builder.src.join("src/librustc_trans/Cargo.toml")); + rustc_cargo_env(builder, &mut cargo); + + // We won't build LLVM if it's not available, as it shouldn't affect `check`. + + let _folder = builder.fold_output(|| format!("stage{}-rustc_trans", compiler.stage)); + run_cargo(builder, + cargo.arg("--features").arg(features), + &codegen_backend_stamp(builder, compiler, target, backend), + true); + } +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Test { pub target: Interned<String>, } @@ -124,11 +172,12 @@ impl Step for Test { } fn run(self, builder: &Builder) { - let target = self.target; let compiler = builder.compiler(0, builder.config.build); + let target = self.target; let out_dir = builder.stage_out(compiler, Mode::Libtest); builder.clear_if_dirty(&out_dir, &libstd_stamp(builder, compiler, target)); + let mut cargo = builder.cargo(compiler, Mode::Libtest, target, "check"); test_cargo(builder, &compiler, target, &mut cargo); @@ -144,6 +193,54 @@ impl Step for Test { } } +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct Rustdoc { + pub target: Interned<String>, +} + +impl Step for Rustdoc { + type Output = (); + const ONLY_HOSTS: bool = true; + const DEFAULT: bool = true; + + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/tools/rustdoc") + } + + fn make_run(run: RunConfig) { + run.builder.ensure(Rustdoc { + target: run.target, + }); + } + + fn run(self, builder: &Builder) { + let compiler = builder.compiler(0, builder.config.build); + let target = self.target; + + let mut cargo = prepare_tool_cargo(builder, + compiler, + target, + "check", + "src/tools/rustdoc"); + + let _folder = builder.fold_output(|| format!("stage{}-rustdoc", compiler.stage)); + println!("Checking rustdoc artifacts ({} -> {})", &compiler.host, target); + run_cargo(builder, + &mut cargo, + &rustdoc_stamp(builder, compiler, target), + true); + + let libdir = builder.sysroot_libdir(compiler, target); + add_to_sysroot(&builder, &libdir, &rustdoc_stamp(builder, compiler, target)); + + builder.ensure(tool::CleanTools { + compiler, + target, + mode: Mode::Tool, + }); + } +} + /// Cargo's output path for the standard library in a given stage, compiled /// by a particular compiler for the specified target. pub fn libstd_stamp(builder: &Builder, compiler: Compiler, target: Interned<String>) -> PathBuf { @@ -161,3 +258,19 @@ pub fn libtest_stamp(builder: &Builder, compiler: Compiler, target: Interned<Str pub fn librustc_stamp(builder: &Builder, compiler: Compiler, target: Interned<String>) -> PathBuf { builder.cargo_out(compiler, Mode::Librustc, target).join(".librustc-check.stamp") } + +/// Cargo's output path for librustc_trans in a given stage, compiled by a particular +/// compiler for the specified target and backend. +fn codegen_backend_stamp(builder: &Builder, + compiler: Compiler, + target: Interned<String>, + backend: Interned<String>) -> PathBuf { + builder.cargo_out(compiler, Mode::Librustc, target) + .join(format!(".librustc_trans-{}-check.stamp", backend)) +} + +/// Cargo's output path for rustdoc in a given stage, compiled by a particular +/// compiler for the specified target. +pub fn rustdoc_stamp(builder: &Builder, compiler: Compiler, target: Interned<String>) -> PathBuf { + builder.cargo_out(compiler, Mode::Tool, target).join(".rustdoc-check.stamp") +} diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 07bce77af8d..1248c2b50be 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -519,7 +519,7 @@ pub fn rustc_cargo(builder: &Builder, cargo: &mut Command) { rustc_cargo_env(builder, cargo); } -fn rustc_cargo_env(builder: &Builder, cargo: &mut Command) { +pub fn rustc_cargo_env(builder: &Builder, cargo: &mut Command) { // Set some configuration variables picked up by build scripts and // the compiler alike cargo.env("CFG_RELEASE", builder.rust_release()) @@ -614,13 +614,14 @@ impl Step for CodegenBackend { run.builder.ensure(CodegenBackend { compiler: run.builder.compiler(run.builder.top_stage, run.host), target: run.target, - backend + backend, }); } fn run(self, builder: &Builder) { let compiler = self.compiler; let target = self.target; + let backend = self.backend; builder.ensure(Rustc { compiler, target }); @@ -628,7 +629,7 @@ impl Step for CodegenBackend { builder.ensure(CodegenBackend { compiler: builder.compiler(1, builder.config.build), target, - backend: self.backend, + backend, }); return; } @@ -639,52 +640,7 @@ impl Step for CodegenBackend { .arg(builder.src.join("src/librustc_trans/Cargo.toml")); rustc_cargo_env(builder, &mut cargo); - match &*self.backend { - "llvm" | "emscripten" => { - // Build LLVM for our target. This will implicitly build the - // host LLVM if necessary. - let llvm_config = builder.ensure(native::Llvm { - target, - emscripten: self.backend == "emscripten", - }); - - if self.backend == "emscripten" { - features.push_str(" emscripten"); - } - - builder.info(&format!("Building stage{} codegen artifacts ({} -> {}, {})", - compiler.stage, &compiler.host, target, self.backend)); - - // Pass down configuration from the LLVM build into the build of - // librustc_llvm and librustc_trans. - if builder.is_rust_llvm(target) { - cargo.env("LLVM_RUSTLLVM", "1"); - } - cargo.env("LLVM_CONFIG", &llvm_config); - if self.backend != "emscripten" { - let target_config = builder.config.target_config.get(&target); - if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) { - cargo.env("CFG_LLVM_ROOT", s); - } - } - // Building with a static libstdc++ is only supported on linux right now, - // not for MSVC or macOS - if builder.config.llvm_static_stdcpp && - !target.contains("freebsd") && - !target.contains("windows") && - !target.contains("apple") { - let file = compiler_file(builder, - builder.cxx(target).unwrap(), - target, - "libstdc++.a"); - cargo.env("LLVM_STATIC_STDCPP", file); - } - if builder.config.llvm_link_shared { - cargo.env("LLVM_LINK_SHARED", "1"); - } - } - _ => panic!("unknown backend: {}", self.backend), - } + features += &build_codegen_backend(&builder, &mut cargo, &compiler, target, backend); let tmp_stamp = builder.cargo_out(compiler, Mode::Librustc, target) .join(".tmp.stamp"); @@ -711,12 +667,69 @@ impl Step for CodegenBackend { codegen_backend.display(), f.display()); } - let stamp = codegen_backend_stamp(builder, compiler, target, self.backend); + let stamp = codegen_backend_stamp(builder, compiler, target, backend); let codegen_backend = codegen_backend.to_str().unwrap(); t!(t!(File::create(&stamp)).write_all(codegen_backend.as_bytes())); } } +pub fn build_codegen_backend(builder: &Builder, + cargo: &mut Command, + compiler: &Compiler, + target: Interned<String>, + backend: Interned<String>) -> String { + let mut features = String::new(); + + match &*backend { + "llvm" | "emscripten" => { + // Build LLVM for our target. This will implicitly build the + // host LLVM if necessary. + let llvm_config = builder.ensure(native::Llvm { + target, + emscripten: backend == "emscripten", + }); + + if backend == "emscripten" { + features.push_str(" emscripten"); + } + + builder.info(&format!("Building stage{} codegen artifacts ({} -> {}, {})", + compiler.stage, &compiler.host, target, backend)); + + // Pass down configuration from the LLVM build into the build of + // librustc_llvm and librustc_trans. + if builder.is_rust_llvm(target) { + cargo.env("LLVM_RUSTLLVM", "1"); + } + cargo.env("LLVM_CONFIG", &llvm_config); + if backend != "emscripten" { + let target_config = builder.config.target_config.get(&target); + if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) { + cargo.env("CFG_LLVM_ROOT", s); + } + } + // Building with a static libstdc++ is only supported on linux right now, + // not for MSVC or macOS + if builder.config.llvm_static_stdcpp && + !target.contains("freebsd") && + !target.contains("windows") && + !target.contains("apple") { + let file = compiler_file(builder, + builder.cxx(target).unwrap(), + target, + "libstdc++.a"); + cargo.env("LLVM_STATIC_STDCPP", file); + } + if builder.config.llvm_link_shared { + cargo.env("LLVM_LINK_SHARED", "1"); + } + } + _ => panic!("unknown backend: {}", backend), + } + + features +} + /// Creates the `codegen-backends` folder for a compiler that's about to be /// assembled as a complete compiler. /// @@ -795,6 +808,8 @@ pub fn librustc_stamp(builder: &Builder, compiler: Compiler, target: Interned<St builder.cargo_out(compiler, Mode::Librustc, target).join(".librustc.stamp") } +/// Cargo's output path for librustc_trans in a given stage, compiled by a particular +/// compiler for the specified target and backend. fn codegen_backend_stamp(builder: &Builder, compiler: Compiler, target: Interned<String>, @@ -803,7 +818,7 @@ fn codegen_backend_stamp(builder: &Builder, .join(format!(".librustc_trans-{}.stamp", backend)) } -fn compiler_file(builder: &Builder, +pub fn compiler_file(builder: &Builder, compiler: &Path, target: Interned<String>, file: &str) -> PathBuf { diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 2c2cf74d979..d952cb5bfc4 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -149,6 +149,7 @@ impl Step for Llvm { .define("WITH_POLLY", "OFF") .define("LLVM_ENABLE_TERMINFO", "OFF") .define("LLVM_ENABLE_LIBEDIT", "OFF") + .define("LLVM_ENABLE_LIBXML2", "OFF") .define("LLVM_PARALLEL_COMPILE_JOBS", builder.jobs().to_string()) .define("LLVM_TARGET_ARCH", target.split('-').next().unwrap()) .define("LLVM_DEFAULT_TARGET_TRIPLE", target); diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 3d954cd5d84..08bbd68c756 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -241,7 +241,16 @@ impl Step for Rls { let host = self.host; let compiler = builder.compiler(stage, host); - builder.ensure(tool::Rls { compiler, target: self.host, extra_features: Vec::new() }); + let build_result = builder.ensure(tool::Rls { + compiler, + target: self.host, + extra_features: Vec::new(), + }); + if build_result.is_none() { + eprintln!("failed to test rls: could not build"); + return; + } + let mut cargo = tool::prepare_tool_cargo(builder, compiler, host, @@ -286,7 +295,16 @@ impl Step for Rustfmt { let host = self.host; let compiler = builder.compiler(stage, host); - builder.ensure(tool::Rustfmt { compiler, target: self.host, extra_features: Vec::new() }); + let build_result = builder.ensure(tool::Rustfmt { + compiler, + target: self.host, + extra_features: Vec::new(), + }); + if build_result.is_none() { + eprintln!("failed to test rustfmt: could not build"); + return; + } + let mut cargo = tool::prepare_tool_cargo(builder, compiler, host, @@ -538,6 +556,7 @@ impl Step for RustdocUi { target: self.target, mode: "ui", suite: "rustdoc-ui", + compare_mode: None, }) } } @@ -590,6 +609,14 @@ macro_rules! default_test { } } +macro_rules! default_test_with_compare_mode { + ($name:ident { path: $path:expr, mode: $mode:expr, suite: $suite:expr, + compare_mode: $compare_mode:expr }) => { + test_with_compare_mode!($name { path: $path, mode: $mode, suite: $suite, default: true, + host: false, compare_mode: $compare_mode }); + } +} + macro_rules! host_test { ($name:ident { path: $path:expr, mode: $mode:expr, suite: $suite:expr }) => { test!($name { path: $path, mode: $mode, suite: $suite, default: true, host: true }); @@ -597,12 +624,29 @@ macro_rules! host_test { } macro_rules! test { + ($name:ident { path: $path:expr, mode: $mode:expr, suite: $suite:expr, default: $default:expr, + host: $host:expr }) => { + test_definitions!($name { path: $path, mode: $mode, suite: $suite, default: $default, + host: $host, compare_mode: None }); + } +} + +macro_rules! test_with_compare_mode { + ($name:ident { path: $path:expr, mode: $mode:expr, suite: $suite:expr, default: $default:expr, + host: $host:expr, compare_mode: $compare_mode:expr }) => { + test_definitions!($name { path: $path, mode: $mode, suite: $suite, default: $default, + host: $host, compare_mode: Some($compare_mode) }); + } +} + +macro_rules! test_definitions { ($name:ident { path: $path:expr, mode: $mode:expr, suite: $suite:expr, default: $default:expr, - host: $host:expr + host: $host:expr, + compare_mode: $compare_mode:expr }) => { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct $name { @@ -634,16 +678,18 @@ macro_rules! test { target: self.target, mode: $mode, suite: $suite, + compare_mode: $compare_mode, }) } } } } -default_test!(Ui { +default_test_with_compare_mode!(Ui { path: "src/test/ui", mode: "ui", - suite: "ui" + suite: "ui", + compare_mode: "nll" }); default_test!(RunPass { @@ -804,6 +850,7 @@ struct Compiletest { target: Interned<String>, mode: &'static str, suite: &'static str, + compare_mode: Option<&'static str>, } impl Step for Compiletest { @@ -823,6 +870,7 @@ impl Step for Compiletest { let target = self.target; let mode = self.mode; let suite = self.suite; + let compare_mode = self.compare_mode; // Skip codegen tests if they aren't enabled in configuration. if !builder.config.codegen_tests && suite == "codegen" { @@ -1044,6 +1092,15 @@ impl Step for Compiletest { suite, mode, &compiler.host, target)); let _time = util::timeit(&builder); try_run(builder, &mut cmd); + + if let Some(compare_mode) = compare_mode { + cmd.arg("--compare-mode").arg(compare_mode); + let _folder = builder.fold_output(|| format!("test_{}_{}", suite, compare_mode)); + builder.info(&format!("Check compiletest suite={} mode={} compare_mode={} ({} -> {})", + suite, mode, compare_mode, &compiler.host, target)); + let _time = util::timeit(&builder); + try_run(builder, &mut cmd); + } } } diff --git a/src/ci/docker/x86_64-gnu-tools/checktools.sh b/src/ci/docker/x86_64-gnu-tools/checktools.sh index da89aa9423b..3fed0175371 100755 --- a/src/ci/docker/x86_64-gnu-tools/checktools.sh +++ b/src/ci/docker/x86_64-gnu-tools/checktools.sh @@ -67,7 +67,7 @@ verify_status rust-by-example src/doc/rust-by-example verify_status rls src/tool/rls verify_status rustfmt src/tool/rustfmt verify_status clippy-driver src/tool/clippy -#verify_status miri src/tool/miri +verify_status miri src/tool/miri if [ "$RUST_RELEASE_CHANNEL" = nightly -a -n "${TOOLSTATE_REPO_ACCESS_TOKEN+is_set}" ]; then . "$(dirname $0)/repo.sh" diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index bf97fb46861..7f110d6a3d2 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -373,3 +373,19 @@ This is an internal flag intended for the standard library and compiler that app `#[unstable]` attribute to any dependent crate that doesn't have another stability attribute. This allows `rustdoc` to be able to generate documentation for the compiler crates and the standard library, as an equivalent command-line argument is provided to `rustc` when building those crates. + +### `doc_alias` feature + +This feature allows you to add alias(es) to an item when using the `rustdoc` search through the +`doc(alias)` attribute. Example: + +```rust,no_run +#![feature(doc_alias)] + +#[doc(alias = "x")] +#[doc(alias = "big")] +pub struct BigX; +``` + +Then, when looking for it through the `rustdoc` search, if you enter "x" or +"big", search will show the `BigX` struct first. diff --git a/src/doc/unstable-book/src/language-features/doc-alias.md b/src/doc/unstable-book/src/language-features/doc-alias.md new file mode 100644 index 00000000000..647ac0cf663 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/doc-alias.md @@ -0,0 +1,23 @@ +# `doc_alias` + +The tracking issue for this feature is: [#50146] + +[#50146]: https://github.com/rust-lang/rust/issues/50146 + +------------------------ + +You can add alias(es) to an item when using the `rustdoc` search through the +`doc(alias)` attribute. Example: + +```rust,no_run +#![feature(doc_alias)] + +#[doc(alias = "x")] +#[doc(alias = "big")] +pub struct BigX; +``` + +Then, when looking for it through the `rustdoc` search, if you enter "x" or +"big", search will show the `BigX` struct first. + +Note that this feature is currently hidden behind the `feature(doc_alias)` gate. diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs index 68a617e0ffe..c0372d24ed5 100644 --- a/src/liballoc/alloc.rs +++ b/src/liballoc/alloc.rs @@ -48,9 +48,6 @@ extern "Rust" { #[allocator] #[rustc_allocator_nounwind] fn __rust_alloc(size: usize, align: usize) -> *mut u8; - #[cold] - #[rustc_allocator_nounwind] - fn __rust_oom() -> !; #[rustc_allocator_nounwind] fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize); #[rustc_allocator_nounwind] @@ -107,16 +104,6 @@ unsafe impl GlobalAlloc for Global { let ptr = __rust_alloc_zeroed(layout.size(), layout.align(), &mut 0); ptr as *mut Opaque } - - #[inline] - fn oom(&self) -> ! { - unsafe { - #[cfg(not(stage0))] - __rust_oom(); - #[cfg(stage0)] - __rust_oom(&mut 0); - } - } } unsafe impl Alloc for Global { @@ -144,11 +131,6 @@ unsafe impl Alloc for Global { unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<Opaque>, AllocErr> { NonNull::new(GlobalAlloc::alloc_zeroed(self, layout)).ok_or(AllocErr) } - - #[inline] - fn oom(&mut self) -> ! { - GlobalAlloc::oom(self) - } } /// The allocator for unique pointers. @@ -165,7 +147,7 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { if !ptr.is_null() { ptr as *mut u8 } else { - Global.oom() + oom() } } } @@ -182,19 +164,33 @@ pub(crate) unsafe fn box_free<T: ?Sized>(ptr: *mut T) { } } +#[cfg(stage0)] +pub fn oom() -> ! { + unsafe { ::core::intrinsics::abort() } +} + +#[cfg(not(stage0))] +pub fn oom() -> ! { + extern { + #[lang = "oom"] + fn oom_impl() -> !; + } + unsafe { oom_impl() } +} + #[cfg(test)] mod tests { extern crate test; use self::test::Bencher; use boxed::Box; - use alloc::{Global, Alloc, Layout}; + use alloc::{Global, Alloc, Layout, oom}; #[test] fn allocate_zeroed() { unsafe { let layout = Layout::from_size_align(1024, 1).unwrap(); let ptr = Global.alloc_zeroed(layout.clone()) - .unwrap_or_else(|_| Global.oom()); + .unwrap_or_else(|_| oom()); let mut i = ptr.cast::<u8>().as_ptr(); let end = i.offset(layout.size() as isize); diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 225b055d8ee..f5980f4599e 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -31,7 +31,7 @@ use core::hash::{Hash, Hasher}; use core::{isize, usize}; use core::convert::From; -use alloc::{Global, Alloc, Layout, box_free}; +use alloc::{Global, Alloc, Layout, box_free, oom}; use boxed::Box; use string::String; use vec::Vec; @@ -553,7 +553,7 @@ impl<T: ?Sized> Arc<T> { let layout = Layout::for_value(&*fake_ptr); let mem = Global.alloc(layout) - .unwrap_or_else(|_| Global.oom()); + .unwrap_or_else(|_| oom()); // Initialize the real ArcInner let inner = set_data_ptr(ptr as *mut T, mem.as_ptr() as *mut u8) as *mut ArcInner<T>; diff --git a/src/liballoc/btree/map.rs b/src/liballoc/btree/map.rs index 82cbec0517e..3984379ea86 100644 --- a/src/liballoc/btree/map.rs +++ b/src/liballoc/btree/map.rs @@ -2155,8 +2155,8 @@ impl<'a, K: Ord, V> Entry<'a, K, V> { /// assert_eq!(map["poneyland"], 43); /// ``` #[stable(feature = "entry_and_modify", since = "1.26.0")] - pub fn and_modify<F>(self, mut f: F) -> Self - where F: FnMut(&mut V) + pub fn and_modify<F>(self, f: F) -> Self + where F: FnOnce(&mut V) { match self { Occupied(mut entry) => { diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs index faac38ca7ce..16f0630b911 100644 --- a/src/liballoc/heap.rs +++ b/src/liballoc/heap.rs @@ -59,7 +59,7 @@ unsafe impl<T> Alloc for T where T: CoreAlloc { } fn oom(&mut self, _: AllocErr) -> ! { - CoreAlloc::oom(self) + unsafe { ::core::intrinsics::abort() } } fn usable_size(&self, layout: &Layout) -> (usize, usize) { diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 163aef61b43..6399be98cd5 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -75,7 +75,7 @@ #![deny(missing_debug_implementations)] #![cfg_attr(test, allow(deprecated))] // rand -#![cfg_attr(not(test), feature(core_float))] +#![cfg_attr(all(not(test), stage0), feature(float_internals))] #![cfg_attr(not(test), feature(exact_size_is_empty))] #![cfg_attr(not(test), feature(generator_trait))] #![cfg_attr(test, feature(rand, test))] @@ -90,6 +90,8 @@ #![feature(collections_range)] #![feature(const_fn)] #![feature(core_intrinsics)] +#![cfg_attr(stage0, feature(core_slice_ext))] +#![cfg_attr(stage0, feature(core_str_ext))] #![feature(custom_attribute)] #![feature(dropck_eyepatch)] #![feature(exact_size_is_empty)] diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index 24b7cd3db0c..7ef0a27fc72 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -14,7 +14,7 @@ use core::ops::Drop; use core::ptr::{self, NonNull, Unique}; use core::slice; -use alloc::{Alloc, Layout, Global}; +use alloc::{Alloc, Layout, Global, oom}; use alloc::CollectionAllocErr; use alloc::CollectionAllocErr::*; use boxed::Box; @@ -101,7 +101,7 @@ impl<T, A: Alloc> RawVec<T, A> { }; match result { Ok(ptr) => ptr, - Err(_) => a.oom(), + Err(_) => oom(), } }; @@ -316,7 +316,7 @@ impl<T, A: Alloc> RawVec<T, A> { new_size); match ptr_res { Ok(ptr) => (new_cap, ptr.cast().into()), - Err(_) => self.a.oom(), + Err(_) => oom(), } } None => { @@ -325,7 +325,7 @@ impl<T, A: Alloc> RawVec<T, A> { let new_cap = if elem_size > (!0) / 8 { 1 } else { 4 }; match self.a.alloc_array::<T>(new_cap) { Ok(ptr) => (new_cap, ptr.into()), - Err(_) => self.a.oom(), + Err(_) => oom(), } } }; @@ -442,7 +442,7 @@ impl<T, A: Alloc> RawVec<T, A> { pub fn reserve_exact(&mut self, used_cap: usize, needed_extra_cap: usize) { match self.try_reserve_exact(used_cap, needed_extra_cap) { Err(CapacityOverflow) => capacity_overflow(), - Err(AllocErr) => self.a.oom(), + Err(AllocErr) => oom(), Ok(()) => { /* yay */ } } } @@ -552,7 +552,7 @@ impl<T, A: Alloc> RawVec<T, A> { pub fn reserve(&mut self, used_cap: usize, needed_extra_cap: usize) { match self.try_reserve(used_cap, needed_extra_cap) { Err(CapacityOverflow) => capacity_overflow(), - Err(AllocErr) => self.a.oom(), + Err(AllocErr) => oom(), Ok(()) => { /* yay */ } } } @@ -667,7 +667,7 @@ impl<T, A: Alloc> RawVec<T, A> { old_layout, new_size) { Ok(p) => self.ptr = p.cast().into(), - Err(_) => self.a.oom(), + Err(_) => oom(), } } self.cap = amount; diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index de0422d82bb..8fb8e111754 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -259,7 +259,7 @@ use core::ops::CoerceUnsized; use core::ptr::{self, NonNull}; use core::convert::From; -use alloc::{Global, Alloc, Layout, Opaque, box_free}; +use alloc::{Global, Alloc, Layout, Opaque, box_free, oom}; use string::String; use vec::Vec; @@ -668,7 +668,7 @@ impl<T: ?Sized> Rc<T> { let layout = Layout::for_value(&*fake_ptr); let mem = Global.alloc(layout) - .unwrap_or_else(|_| Global.oom()); + .unwrap_or_else(|_| oom()); // Initialize the real RcBox let inner = set_data_ptr(ptr as *mut T, mem.as_ptr() as *mut u8) as *mut RcBox<T>; diff --git a/src/liballoc/repeat-generic-slice.rs b/src/liballoc/repeat-generic-slice.rs new file mode 100644 index 00000000000..5c14ee4fd83 --- /dev/null +++ b/src/liballoc/repeat-generic-slice.rs @@ -0,0 +1,19 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(repeat_generic_slice)] + +fn main() { + assert_eq!([1, 2].repeat(2), vec![1, 2, 1, 2]); + assert_eq!([1, 2, 3, 4].repeat(0), vec![]); + assert_eq!([1, 2, 3, 4].repeat(1), vec![1, 2, 3, 4]); + assert_eq!([1, 2, 3, 4].repeat(3), + vec![1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]); +} diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 33e652856e8..d50a3458f20 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -101,7 +101,7 @@ use core::cmp::Ordering::{self, Less}; use core::mem::size_of; use core::mem; use core::ptr; -use core::slice as core_slice; +#[cfg(stage0)] use core::slice::SliceExt; use core::{u8, u16, u32}; use borrow::{Borrow, BorrowMut, ToOwned}; @@ -171,1059 +171,12 @@ mod hack { } } -#[lang = "slice"] +#[cfg_attr(stage0, lang = "slice")] +#[cfg_attr(not(stage0), lang = "slice_alloc")] #[cfg(not(test))] impl<T> [T] { - /// Returns the number of elements in the slice. - /// - /// # Examples - /// - /// ``` - /// let a = [1, 2, 3]; - /// assert_eq!(a.len(), 3); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn len(&self) -> usize { - core_slice::SliceExt::len(self) - } - - /// Returns `true` if the slice has a length of 0. - /// - /// # Examples - /// - /// ``` - /// let a = [1, 2, 3]; - /// assert!(!a.is_empty()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn is_empty(&self) -> bool { - core_slice::SliceExt::is_empty(self) - } - - /// Returns the first element of the slice, or `None` if it is empty. - /// - /// # Examples - /// - /// ``` - /// let v = [10, 40, 30]; - /// assert_eq!(Some(&10), v.first()); - /// - /// let w: &[i32] = &[]; - /// assert_eq!(None, w.first()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn first(&self) -> Option<&T> { - core_slice::SliceExt::first(self) - } - - /// Returns a mutable pointer to the first element of the slice, or `None` if it is empty. - /// - /// # Examples - /// - /// ``` - /// let x = &mut [0, 1, 2]; - /// - /// if let Some(first) = x.first_mut() { - /// *first = 5; - /// } - /// assert_eq!(x, &[5, 1, 2]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn first_mut(&mut self) -> Option<&mut T> { - core_slice::SliceExt::first_mut(self) - } - - /// Returns the first and all the rest of the elements of the slice, or `None` if it is empty. - /// - /// # Examples - /// - /// ``` - /// let x = &[0, 1, 2]; - /// - /// if let Some((first, elements)) = x.split_first() { - /// assert_eq!(first, &0); - /// assert_eq!(elements, &[1, 2]); - /// } - /// ``` - #[stable(feature = "slice_splits", since = "1.5.0")] - #[inline] - pub fn split_first(&self) -> Option<(&T, &[T])> { - core_slice::SliceExt::split_first(self) - } - - /// Returns the first and all the rest of the elements of the slice, or `None` if it is empty. - /// - /// # Examples - /// - /// ``` - /// let x = &mut [0, 1, 2]; - /// - /// if let Some((first, elements)) = x.split_first_mut() { - /// *first = 3; - /// elements[0] = 4; - /// elements[1] = 5; - /// } - /// assert_eq!(x, &[3, 4, 5]); - /// ``` - #[stable(feature = "slice_splits", since = "1.5.0")] - #[inline] - pub fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> { - core_slice::SliceExt::split_first_mut(self) - } - - /// Returns the last and all the rest of the elements of the slice, or `None` if it is empty. - /// - /// # Examples - /// - /// ``` - /// let x = &[0, 1, 2]; - /// - /// if let Some((last, elements)) = x.split_last() { - /// assert_eq!(last, &2); - /// assert_eq!(elements, &[0, 1]); - /// } - /// ``` - #[stable(feature = "slice_splits", since = "1.5.0")] - #[inline] - pub fn split_last(&self) -> Option<(&T, &[T])> { - core_slice::SliceExt::split_last(self) - - } - - /// Returns the last and all the rest of the elements of the slice, or `None` if it is empty. - /// - /// # Examples - /// - /// ``` - /// let x = &mut [0, 1, 2]; - /// - /// if let Some((last, elements)) = x.split_last_mut() { - /// *last = 3; - /// elements[0] = 4; - /// elements[1] = 5; - /// } - /// assert_eq!(x, &[4, 5, 3]); - /// ``` - #[stable(feature = "slice_splits", since = "1.5.0")] - #[inline] - pub fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> { - core_slice::SliceExt::split_last_mut(self) - } - - /// Returns the last element of the slice, or `None` if it is empty. - /// - /// # Examples - /// - /// ``` - /// let v = [10, 40, 30]; - /// assert_eq!(Some(&30), v.last()); - /// - /// let w: &[i32] = &[]; - /// assert_eq!(None, w.last()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn last(&self) -> Option<&T> { - core_slice::SliceExt::last(self) - } - - /// Returns a mutable pointer to the last item in the slice. - /// - /// # Examples - /// - /// ``` - /// let x = &mut [0, 1, 2]; - /// - /// if let Some(last) = x.last_mut() { - /// *last = 10; - /// } - /// assert_eq!(x, &[0, 1, 10]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn last_mut(&mut self) -> Option<&mut T> { - core_slice::SliceExt::last_mut(self) - } - - /// Returns a reference to an element or subslice depending on the type of - /// index. - /// - /// - If given a position, returns a reference to the element at that - /// position or `None` if out of bounds. - /// - If given a range, returns the subslice corresponding to that range, - /// or `None` if out of bounds. - /// - /// # Examples - /// - /// ``` - /// let v = [10, 40, 30]; - /// assert_eq!(Some(&40), v.get(1)); - /// assert_eq!(Some(&[10, 40][..]), v.get(0..2)); - /// assert_eq!(None, v.get(3)); - /// assert_eq!(None, v.get(0..4)); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn get<I>(&self, index: I) -> Option<&I::Output> - where I: SliceIndex<Self> - { - core_slice::SliceExt::get(self, index) - } - - /// Returns a mutable reference to an element or subslice depending on the - /// type of index (see [`get`]) or `None` if the index is out of bounds. - /// - /// [`get`]: #method.get - /// - /// # Examples - /// - /// ``` - /// let x = &mut [0, 1, 2]; - /// - /// if let Some(elem) = x.get_mut(1) { - /// *elem = 42; - /// } - /// assert_eq!(x, &[0, 42, 2]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output> - where I: SliceIndex<Self> - { - core_slice::SliceExt::get_mut(self, index) - } - - /// Returns a reference to an element or subslice, without doing bounds - /// checking. - /// - /// This is generally not recommended, use with caution! For a safe - /// alternative see [`get`]. - /// - /// [`get`]: #method.get - /// - /// # Examples - /// - /// ``` - /// let x = &[1, 2, 4]; - /// - /// unsafe { - /// assert_eq!(x.get_unchecked(1), &2); - /// } - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub unsafe fn get_unchecked<I>(&self, index: I) -> &I::Output - where I: SliceIndex<Self> - { - core_slice::SliceExt::get_unchecked(self, index) - } - - /// Returns a mutable reference to an element or subslice, without doing - /// bounds checking. - /// - /// This is generally not recommended, use with caution! For a safe - /// alternative see [`get_mut`]. - /// - /// [`get_mut`]: #method.get_mut - /// - /// # Examples - /// - /// ``` - /// let x = &mut [1, 2, 4]; - /// - /// unsafe { - /// let elem = x.get_unchecked_mut(1); - /// *elem = 13; - /// } - /// assert_eq!(x, &[1, 13, 4]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output - where I: SliceIndex<Self> - { - core_slice::SliceExt::get_unchecked_mut(self, index) - } - - /// Returns a raw pointer to the slice's buffer. - /// - /// The caller must ensure that the slice outlives the pointer this - /// function returns, or else it will end up pointing to garbage. - /// - /// Modifying the container referenced by this slice may cause its buffer - /// to be reallocated, which would also make any pointers to it invalid. - /// - /// # Examples - /// - /// ``` - /// let x = &[1, 2, 4]; - /// let x_ptr = x.as_ptr(); - /// - /// unsafe { - /// for i in 0..x.len() { - /// assert_eq!(x.get_unchecked(i), &*x_ptr.offset(i as isize)); - /// } - /// } - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn as_ptr(&self) -> *const T { - core_slice::SliceExt::as_ptr(self) - } - - /// Returns an unsafe mutable pointer to the slice's buffer. - /// - /// The caller must ensure that the slice outlives the pointer this - /// function returns, or else it will end up pointing to garbage. - /// - /// Modifying the container referenced by this slice may cause its buffer - /// to be reallocated, which would also make any pointers to it invalid. - /// - /// # Examples - /// - /// ``` - /// let x = &mut [1, 2, 4]; - /// let x_ptr = x.as_mut_ptr(); - /// - /// unsafe { - /// for i in 0..x.len() { - /// *x_ptr.offset(i as isize) += 2; - /// } - /// } - /// assert_eq!(x, &[3, 4, 6]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn as_mut_ptr(&mut self) -> *mut T { - core_slice::SliceExt::as_mut_ptr(self) - } - - /// Swaps two elements in the slice. - /// - /// # Arguments - /// - /// * a - The index of the first element - /// * b - The index of the second element - /// - /// # Panics - /// - /// Panics if `a` or `b` are out of bounds. - /// - /// # Examples - /// - /// ``` - /// let mut v = ["a", "b", "c", "d"]; - /// v.swap(1, 3); - /// assert!(v == ["a", "d", "c", "b"]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn swap(&mut self, a: usize, b: usize) { - core_slice::SliceExt::swap(self, a, b) - } - - /// Reverses the order of elements in the slice, in place. - /// - /// # Examples - /// - /// ``` - /// let mut v = [1, 2, 3]; - /// v.reverse(); - /// assert!(v == [3, 2, 1]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn reverse(&mut self) { - core_slice::SliceExt::reverse(self) - } - - /// Returns an iterator over the slice. - /// - /// # Examples - /// - /// ``` - /// let x = &[1, 2, 4]; - /// let mut iterator = x.iter(); - /// - /// assert_eq!(iterator.next(), Some(&1)); - /// assert_eq!(iterator.next(), Some(&2)); - /// assert_eq!(iterator.next(), Some(&4)); - /// assert_eq!(iterator.next(), None); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn iter(&self) -> Iter<T> { - core_slice::SliceExt::iter(self) - } - - /// Returns an iterator that allows modifying each value. - /// - /// # Examples - /// - /// ``` - /// let x = &mut [1, 2, 4]; - /// for elem in x.iter_mut() { - /// *elem += 2; - /// } - /// assert_eq!(x, &[3, 4, 6]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn iter_mut(&mut self) -> IterMut<T> { - core_slice::SliceExt::iter_mut(self) - } - - /// Returns an iterator over all contiguous windows of length - /// `size`. The windows overlap. If the slice is shorter than - /// `size`, the iterator returns no values. - /// - /// # Panics - /// - /// Panics if `size` is 0. - /// - /// # Examples - /// - /// ``` - /// let slice = ['r', 'u', 's', 't']; - /// let mut iter = slice.windows(2); - /// assert_eq!(iter.next().unwrap(), &['r', 'u']); - /// assert_eq!(iter.next().unwrap(), &['u', 's']); - /// assert_eq!(iter.next().unwrap(), &['s', 't']); - /// assert!(iter.next().is_none()); - /// ``` - /// - /// If the slice is shorter than `size`: - /// - /// ``` - /// let slice = ['f', 'o', 'o']; - /// let mut iter = slice.windows(4); - /// assert!(iter.next().is_none()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn windows(&self, size: usize) -> Windows<T> { - core_slice::SliceExt::windows(self, size) - } - - /// Returns an iterator over `chunk_size` elements of the slice at a - /// time. The chunks are slices and do not overlap. If `chunk_size` does - /// not divide the length of the slice, then the last chunk will - /// not have length `chunk_size`. - /// - /// See [`exact_chunks`] for a variant of this iterator that returns chunks - /// of always exactly `chunk_size` elements. - /// - /// # Panics - /// - /// Panics if `chunk_size` is 0. - /// - /// # Examples - /// - /// ``` - /// let slice = ['l', 'o', 'r', 'e', 'm']; - /// let mut iter = slice.chunks(2); - /// assert_eq!(iter.next().unwrap(), &['l', 'o']); - /// assert_eq!(iter.next().unwrap(), &['r', 'e']); - /// assert_eq!(iter.next().unwrap(), &['m']); - /// assert!(iter.next().is_none()); - /// ``` - /// - /// [`exact_chunks`]: #method.exact_chunks - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn chunks(&self, chunk_size: usize) -> Chunks<T> { - core_slice::SliceExt::chunks(self, chunk_size) - } - - /// Returns an iterator over `chunk_size` elements of the slice at a - /// time. The chunks are slices and do not overlap. If `chunk_size` does - /// not divide the length of the slice, then the last up to `chunk_size-1` - /// elements will be omitted. - /// - /// Due to each chunk having exactly `chunk_size` elements, the compiler - /// can often optimize the resulting code better than in the case of - /// [`chunks`]. - /// - /// # Panics - /// - /// Panics if `chunk_size` is 0. - /// - /// # Examples - /// - /// ``` - /// #![feature(exact_chunks)] - /// - /// let slice = ['l', 'o', 'r', 'e', 'm']; - /// let mut iter = slice.exact_chunks(2); - /// assert_eq!(iter.next().unwrap(), &['l', 'o']); - /// assert_eq!(iter.next().unwrap(), &['r', 'e']); - /// assert!(iter.next().is_none()); - /// ``` - /// - /// [`chunks`]: #method.chunks - #[unstable(feature = "exact_chunks", issue = "47115")] - #[inline] - pub fn exact_chunks(&self, chunk_size: usize) -> ExactChunks<T> { - core_slice::SliceExt::exact_chunks(self, chunk_size) - } - - /// Returns an iterator over `chunk_size` elements of the slice at a time. - /// The chunks are mutable slices, and do not overlap. If `chunk_size` does - /// not divide the length of the slice, then the last chunk will not - /// have length `chunk_size`. - /// - /// See [`exact_chunks_mut`] for a variant of this iterator that returns chunks - /// of always exactly `chunk_size` elements. - /// - /// # Panics - /// - /// Panics if `chunk_size` is 0. - /// - /// # Examples - /// - /// ``` - /// let v = &mut [0, 0, 0, 0, 0]; - /// let mut count = 1; - /// - /// for chunk in v.chunks_mut(2) { - /// for elem in chunk.iter_mut() { - /// *elem += count; - /// } - /// count += 1; - /// } - /// assert_eq!(v, &[1, 1, 2, 2, 3]); - /// ``` - /// - /// [`exact_chunks_mut`]: #method.exact_chunks_mut - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<T> { - core_slice::SliceExt::chunks_mut(self, chunk_size) - } - - /// Returns an iterator over `chunk_size` elements of the slice at a time. - /// The chunks are mutable slices, and do not overlap. If `chunk_size` does - /// not divide the length of the slice, then the last up to `chunk_size-1` - /// elements will be omitted. - /// - /// - /// Due to each chunk having exactly `chunk_size` elements, the compiler - /// can often optimize the resulting code better than in the case of - /// [`chunks_mut`]. - /// - /// # Panics - /// - /// Panics if `chunk_size` is 0. - /// - /// # Examples - /// - /// ``` - /// #![feature(exact_chunks)] - /// - /// let v = &mut [0, 0, 0, 0, 0]; - /// let mut count = 1; - /// - /// for chunk in v.exact_chunks_mut(2) { - /// for elem in chunk.iter_mut() { - /// *elem += count; - /// } - /// count += 1; - /// } - /// assert_eq!(v, &[1, 1, 2, 2, 0]); - /// ``` - /// - /// [`chunks_mut`]: #method.chunks_mut - #[unstable(feature = "exact_chunks", issue = "47115")] - #[inline] - pub fn exact_chunks_mut(&mut self, chunk_size: usize) -> ExactChunksMut<T> { - core_slice::SliceExt::exact_chunks_mut(self, chunk_size) - } - - /// Divides one slice into two at an index. - /// - /// The first will contain all indices from `[0, mid)` (excluding - /// the index `mid` itself) and the second will contain all - /// indices from `[mid, len)` (excluding the index `len` itself). - /// - /// # Panics - /// - /// Panics if `mid > len`. - /// - /// # Examples - /// - /// ``` - /// let v = [1, 2, 3, 4, 5, 6]; - /// - /// { - /// let (left, right) = v.split_at(0); - /// assert!(left == []); - /// assert!(right == [1, 2, 3, 4, 5, 6]); - /// } - /// - /// { - /// let (left, right) = v.split_at(2); - /// assert!(left == [1, 2]); - /// assert!(right == [3, 4, 5, 6]); - /// } - /// - /// { - /// let (left, right) = v.split_at(6); - /// assert!(left == [1, 2, 3, 4, 5, 6]); - /// assert!(right == []); - /// } - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn split_at(&self, mid: usize) -> (&[T], &[T]) { - core_slice::SliceExt::split_at(self, mid) - } - - /// Divides one mutable slice into two at an index. - /// - /// The first will contain all indices from `[0, mid)` (excluding - /// the index `mid` itself) and the second will contain all - /// indices from `[mid, len)` (excluding the index `len` itself). - /// - /// # Panics - /// - /// Panics if `mid > len`. - /// - /// # Examples - /// - /// ``` - /// let mut v = [1, 0, 3, 0, 5, 6]; - /// // scoped to restrict the lifetime of the borrows - /// { - /// let (left, right) = v.split_at_mut(2); - /// assert!(left == [1, 0]); - /// assert!(right == [3, 0, 5, 6]); - /// left[1] = 2; - /// right[1] = 4; - /// } - /// assert!(v == [1, 2, 3, 4, 5, 6]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { - core_slice::SliceExt::split_at_mut(self, mid) - } - - /// Returns an iterator over subslices separated by elements that match - /// `pred`. The matched element is not contained in the subslices. - /// - /// # Examples - /// - /// ``` - /// let slice = [10, 40, 33, 20]; - /// let mut iter = slice.split(|num| num % 3 == 0); - /// - /// assert_eq!(iter.next().unwrap(), &[10, 40]); - /// assert_eq!(iter.next().unwrap(), &[20]); - /// assert!(iter.next().is_none()); - /// ``` - /// - /// If the first element is matched, an empty slice will be the first item - /// returned by the iterator. Similarly, if the last element in the slice - /// is matched, an empty slice will be the last item returned by the - /// iterator: - /// - /// ``` - /// let slice = [10, 40, 33]; - /// let mut iter = slice.split(|num| num % 3 == 0); - /// - /// assert_eq!(iter.next().unwrap(), &[10, 40]); - /// assert_eq!(iter.next().unwrap(), &[]); - /// assert!(iter.next().is_none()); - /// ``` - /// - /// If two matched elements are directly adjacent, an empty slice will be - /// present between them: - /// - /// ``` - /// let slice = [10, 6, 33, 20]; - /// let mut iter = slice.split(|num| num % 3 == 0); - /// - /// assert_eq!(iter.next().unwrap(), &[10]); - /// assert_eq!(iter.next().unwrap(), &[]); - /// assert_eq!(iter.next().unwrap(), &[20]); - /// assert!(iter.next().is_none()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn split<F>(&self, pred: F) -> Split<T, F> - where F: FnMut(&T) -> bool - { - core_slice::SliceExt::split(self, pred) - } - - /// Returns an iterator over mutable subslices separated by elements that - /// match `pred`. The matched element is not contained in the subslices. - /// - /// # Examples - /// - /// ``` - /// let mut v = [10, 40, 30, 20, 60, 50]; - /// - /// for group in v.split_mut(|num| *num % 3 == 0) { - /// group[0] = 1; - /// } - /// assert_eq!(v, [1, 40, 30, 1, 60, 1]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn split_mut<F>(&mut self, pred: F) -> SplitMut<T, F> - where F: FnMut(&T) -> bool - { - core_slice::SliceExt::split_mut(self, pred) - } - - /// Returns an iterator over subslices separated by elements that match - /// `pred`, starting at the end of the slice and working backwards. - /// The matched element is not contained in the subslices. - /// - /// # Examples - /// - /// ``` - /// - /// let slice = [11, 22, 33, 0, 44, 55]; - /// let mut iter = slice.rsplit(|num| *num == 0); - /// - /// assert_eq!(iter.next().unwrap(), &[44, 55]); - /// assert_eq!(iter.next().unwrap(), &[11, 22, 33]); - /// assert_eq!(iter.next(), None); - /// ``` - /// - /// As with `split()`, if the first or last element is matched, an empty - /// slice will be the first (or last) item returned by the iterator. - /// - /// ``` - /// let v = &[0, 1, 1, 2, 3, 5, 8]; - /// let mut it = v.rsplit(|n| *n % 2 == 0); - /// assert_eq!(it.next().unwrap(), &[]); - /// assert_eq!(it.next().unwrap(), &[3, 5]); - /// assert_eq!(it.next().unwrap(), &[1, 1]); - /// assert_eq!(it.next().unwrap(), &[]); - /// assert_eq!(it.next(), None); - /// ``` - #[stable(feature = "slice_rsplit", since = "1.27.0")] - #[inline] - pub fn rsplit<F>(&self, pred: F) -> RSplit<T, F> - where F: FnMut(&T) -> bool - { - core_slice::SliceExt::rsplit(self, pred) - } - - /// Returns an iterator over mutable subslices separated by elements that - /// match `pred`, starting at the end of the slice and working - /// backwards. The matched element is not contained in the subslices. - /// - /// # Examples - /// - /// ``` - /// let mut v = [100, 400, 300, 200, 600, 500]; - /// - /// let mut count = 0; - /// for group in v.rsplit_mut(|num| *num % 3 == 0) { - /// count += 1; - /// group[0] = count; - /// } - /// assert_eq!(v, [3, 400, 300, 2, 600, 1]); - /// ``` - /// - #[stable(feature = "slice_rsplit", since = "1.27.0")] - #[inline] - pub fn rsplit_mut<F>(&mut self, pred: F) -> RSplitMut<T, F> - where F: FnMut(&T) -> bool - { - core_slice::SliceExt::rsplit_mut(self, pred) - } - - /// Returns an iterator over subslices separated by elements that match - /// `pred`, limited to returning at most `n` items. The matched element is - /// not contained in the subslices. - /// - /// The last element returned, if any, will contain the remainder of the - /// slice. - /// - /// # Examples - /// - /// Print the slice split once by numbers divisible by 3 (i.e. `[10, 40]`, - /// `[20, 60, 50]`): - /// - /// ``` - /// let v = [10, 40, 30, 20, 60, 50]; - /// - /// for group in v.splitn(2, |num| *num % 3 == 0) { - /// println!("{:?}", group); - /// } - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn splitn<F>(&self, n: usize, pred: F) -> SplitN<T, F> - where F: FnMut(&T) -> bool - { - core_slice::SliceExt::splitn(self, n, pred) - } - - /// Returns an iterator over subslices separated by elements that match - /// `pred`, limited to returning at most `n` items. The matched element is - /// not contained in the subslices. - /// - /// The last element returned, if any, will contain the remainder of the - /// slice. - /// - /// # Examples - /// - /// ``` - /// let mut v = [10, 40, 30, 20, 60, 50]; - /// - /// for group in v.splitn_mut(2, |num| *num % 3 == 0) { - /// group[0] = 1; - /// } - /// assert_eq!(v, [1, 40, 30, 1, 60, 50]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn splitn_mut<F>(&mut self, n: usize, pred: F) -> SplitNMut<T, F> - where F: FnMut(&T) -> bool - { - core_slice::SliceExt::splitn_mut(self, n, pred) - } - - /// Returns an iterator over subslices separated by elements that match - /// `pred` limited to returning at most `n` items. This starts at the end of - /// the slice and works backwards. The matched element is not contained in - /// the subslices. - /// - /// The last element returned, if any, will contain the remainder of the - /// slice. - /// - /// # Examples - /// - /// Print the slice split once, starting from the end, by numbers divisible - /// by 3 (i.e. `[50]`, `[10, 40, 30, 20]`): - /// - /// ``` - /// let v = [10, 40, 30, 20, 60, 50]; - /// - /// for group in v.rsplitn(2, |num| *num % 3 == 0) { - /// println!("{:?}", group); - /// } - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn rsplitn<F>(&self, n: usize, pred: F) -> RSplitN<T, F> - where F: FnMut(&T) -> bool - { - core_slice::SliceExt::rsplitn(self, n, pred) - } - - /// Returns an iterator over subslices separated by elements that match - /// `pred` limited to returning at most `n` items. This starts at the end of - /// the slice and works backwards. The matched element is not contained in - /// the subslices. - /// - /// The last element returned, if any, will contain the remainder of the - /// slice. - /// - /// # Examples - /// - /// ``` - /// let mut s = [10, 40, 30, 20, 60, 50]; - /// - /// for group in s.rsplitn_mut(2, |num| *num % 3 == 0) { - /// group[0] = 1; - /// } - /// assert_eq!(s, [1, 40, 30, 20, 60, 1]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn rsplitn_mut<F>(&mut self, n: usize, pred: F) -> RSplitNMut<T, F> - where F: FnMut(&T) -> bool - { - core_slice::SliceExt::rsplitn_mut(self, n, pred) - } - - /// Returns `true` if the slice contains an element with the given value. - /// - /// # Examples - /// - /// ``` - /// let v = [10, 40, 30]; - /// assert!(v.contains(&30)); - /// assert!(!v.contains(&50)); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn contains(&self, x: &T) -> bool - where T: PartialEq - { - core_slice::SliceExt::contains(self, x) - } - - /// Returns `true` if `needle` is a prefix of the slice. - /// - /// # Examples - /// - /// ``` - /// let v = [10, 40, 30]; - /// assert!(v.starts_with(&[10])); - /// assert!(v.starts_with(&[10, 40])); - /// assert!(!v.starts_with(&[50])); - /// assert!(!v.starts_with(&[10, 50])); - /// ``` - /// - /// Always returns `true` if `needle` is an empty slice: - /// - /// ``` - /// let v = &[10, 40, 30]; - /// assert!(v.starts_with(&[])); - /// let v: &[u8] = &[]; - /// assert!(v.starts_with(&[])); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn starts_with(&self, needle: &[T]) -> bool - where T: PartialEq - { - core_slice::SliceExt::starts_with(self, needle) - } - - /// Returns `true` if `needle` is a suffix of the slice. - /// - /// # Examples - /// - /// ``` - /// let v = [10, 40, 30]; - /// assert!(v.ends_with(&[30])); - /// assert!(v.ends_with(&[40, 30])); - /// assert!(!v.ends_with(&[50])); - /// assert!(!v.ends_with(&[50, 30])); - /// ``` - /// - /// Always returns `true` if `needle` is an empty slice: - /// - /// ``` - /// let v = &[10, 40, 30]; - /// assert!(v.ends_with(&[])); - /// let v: &[u8] = &[]; - /// assert!(v.ends_with(&[])); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn ends_with(&self, needle: &[T]) -> bool - where T: PartialEq - { - core_slice::SliceExt::ends_with(self, needle) - } - - /// Binary searches this sorted slice for a given element. - /// - /// If the value is found then `Ok` is returned, containing the - /// index of the matching element; if the value is not found then - /// `Err` is returned, containing the index where a matching - /// element could be inserted while maintaining sorted order. - /// - /// # Examples - /// - /// Looks up a series of four elements. The first is found, with a - /// uniquely determined position; the second and third are not - /// found; the fourth could match any position in `[1, 4]`. - /// - /// ``` - /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; - /// - /// assert_eq!(s.binary_search(&13), Ok(9)); - /// assert_eq!(s.binary_search(&4), Err(7)); - /// assert_eq!(s.binary_search(&100), Err(13)); - /// let r = s.binary_search(&1); - /// assert!(match r { Ok(1...4) => true, _ => false, }); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn binary_search(&self, x: &T) -> Result<usize, usize> - where T: Ord - { - core_slice::SliceExt::binary_search(self, x) - } - - /// Binary searches this sorted slice with a comparator function. - /// - /// The comparator function should implement an order consistent - /// with the sort order of the underlying slice, returning an - /// order code that indicates whether its argument is `Less`, - /// `Equal` or `Greater` the desired target. - /// - /// If a matching value is found then returns `Ok`, containing - /// the index for the matched element; if no match is found then - /// `Err` is returned, containing the index where a matching - /// element could be inserted while maintaining sorted order. - /// - /// # Examples - /// - /// Looks up a series of four elements. The first is found, with a - /// uniquely determined position; the second and third are not - /// found; the fourth could match any position in `[1, 4]`. - /// - /// ``` - /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; - /// - /// let seek = 13; - /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Ok(9)); - /// let seek = 4; - /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(7)); - /// let seek = 100; - /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(13)); - /// let seek = 1; - /// let r = s.binary_search_by(|probe| probe.cmp(&seek)); - /// assert!(match r { Ok(1...4) => true, _ => false, }); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn binary_search_by<'a, F>(&'a self, f: F) -> Result<usize, usize> - where F: FnMut(&'a T) -> Ordering - { - core_slice::SliceExt::binary_search_by(self, f) - } - - /// Binary searches this sorted slice with a key extraction function. - /// - /// Assumes that the slice is sorted by the key, for instance with - /// [`sort_by_key`] using the same key extraction function. - /// - /// If a matching value is found then returns `Ok`, containing the - /// index for the matched element; if no match is found then `Err` - /// is returned, containing the index where a matching element could - /// be inserted while maintaining sorted order. - /// - /// [`sort_by_key`]: #method.sort_by_key - /// - /// # Examples - /// - /// Looks up a series of four elements in a slice of pairs sorted by - /// their second elements. The first is found, with a uniquely - /// determined position; the second and third are not found; the - /// fourth could match any position in `[1, 4]`. - /// - /// ``` - /// let s = [(0, 0), (2, 1), (4, 1), (5, 1), (3, 1), - /// (1, 2), (2, 3), (4, 5), (5, 8), (3, 13), - /// (1, 21), (2, 34), (4, 55)]; - /// - /// assert_eq!(s.binary_search_by_key(&13, |&(a,b)| b), Ok(9)); - /// assert_eq!(s.binary_search_by_key(&4, |&(a,b)| b), Err(7)); - /// assert_eq!(s.binary_search_by_key(&100, |&(a,b)| b), Err(13)); - /// let r = s.binary_search_by_key(&1, |&(a,b)| b); - /// assert!(match r { Ok(1...4) => true, _ => false, }); - /// ``` - #[stable(feature = "slice_binary_search_by_key", since = "1.10.0")] - #[inline] - pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, f: F) -> Result<usize, usize> - where F: FnMut(&'a T) -> B, - B: Ord - { - core_slice::SliceExt::binary_search_by_key(self, b, f) - } + #[cfg(stage0)] + slice_core_methods!(); /// Sorts the slice. /// @@ -1402,345 +355,6 @@ impl<T> [T] { sort_by_key!(usize, self, f) } - /// Sorts the slice, but may not preserve the order of equal elements. - /// - /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate), - /// and `O(n log n)` worst-case. - /// - /// # Current implementation - /// - /// The current algorithm is based on [pattern-defeating quicksort][pdqsort] by Orson Peters, - /// which combines the fast average case of randomized quicksort with the fast worst case of - /// heapsort, while achieving linear time on slices with certain patterns. It uses some - /// randomization to avoid degenerate cases, but with a fixed seed to always provide - /// deterministic behavior. - /// - /// It is typically faster than stable sorting, except in a few special cases, e.g. when the - /// slice consists of several concatenated sorted sequences. - /// - /// # Examples - /// - /// ``` - /// let mut v = [-5, 4, 1, -3, 2]; - /// - /// v.sort_unstable(); - /// assert!(v == [-5, -3, 1, 2, 4]); - /// ``` - /// - /// [pdqsort]: https://github.com/orlp/pdqsort - #[stable(feature = "sort_unstable", since = "1.20.0")] - #[inline] - pub fn sort_unstable(&mut self) - where T: Ord - { - core_slice::SliceExt::sort_unstable(self); - } - - /// Sorts the slice with a comparator function, but may not preserve the order of equal - /// elements. - /// - /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate), - /// and `O(n log n)` worst-case. - /// - /// # Current implementation - /// - /// The current algorithm is based on [pattern-defeating quicksort][pdqsort] by Orson Peters, - /// which combines the fast average case of randomized quicksort with the fast worst case of - /// heapsort, while achieving linear time on slices with certain patterns. It uses some - /// randomization to avoid degenerate cases, but with a fixed seed to always provide - /// deterministic behavior. - /// - /// It is typically faster than stable sorting, except in a few special cases, e.g. when the - /// slice consists of several concatenated sorted sequences. - /// - /// # Examples - /// - /// ``` - /// let mut v = [5, 4, 1, 3, 2]; - /// v.sort_unstable_by(|a, b| a.cmp(b)); - /// assert!(v == [1, 2, 3, 4, 5]); - /// - /// // reverse sorting - /// v.sort_unstable_by(|a, b| b.cmp(a)); - /// assert!(v == [5, 4, 3, 2, 1]); - /// ``` - /// - /// [pdqsort]: https://github.com/orlp/pdqsort - #[stable(feature = "sort_unstable", since = "1.20.0")] - #[inline] - pub fn sort_unstable_by<F>(&mut self, compare: F) - where F: FnMut(&T, &T) -> Ordering - { - core_slice::SliceExt::sort_unstable_by(self, compare); - } - - /// Sorts the slice with a key extraction function, but may not preserve the order of equal - /// elements. - /// - /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate), - /// and `O(m n log(m n))` worst-case, where the key function is `O(m)`. - /// - /// # Current implementation - /// - /// The current algorithm is based on [pattern-defeating quicksort][pdqsort] by Orson Peters, - /// which combines the fast average case of randomized quicksort with the fast worst case of - /// heapsort, while achieving linear time on slices with certain patterns. It uses some - /// randomization to avoid degenerate cases, but with a fixed seed to always provide - /// deterministic behavior. - /// - /// # Examples - /// - /// ``` - /// let mut v = [-5i32, 4, 1, -3, 2]; - /// - /// v.sort_unstable_by_key(|k| k.abs()); - /// assert!(v == [1, 2, -3, 4, -5]); - /// ``` - /// - /// [pdqsort]: https://github.com/orlp/pdqsort - #[stable(feature = "sort_unstable", since = "1.20.0")] - #[inline] - pub fn sort_unstable_by_key<K, F>(&mut self, f: F) - where F: FnMut(&T) -> K, K: Ord - { - core_slice::SliceExt::sort_unstable_by_key(self, f); - } - - /// Rotates the slice in-place such that the first `mid` elements of the - /// slice move to the end while the last `self.len() - mid` elements move to - /// the front. After calling `rotate_left`, the element previously at index - /// `mid` will become the first element in the slice. - /// - /// # Panics - /// - /// This function will panic if `mid` is greater than the length of the - /// slice. Note that `mid == self.len()` does _not_ panic and is a no-op - /// rotation. - /// - /// # Complexity - /// - /// Takes linear (in `self.len()`) time. - /// - /// # Examples - /// - /// ``` - /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f']; - /// a.rotate_left(2); - /// assert_eq!(a, ['c', 'd', 'e', 'f', 'a', 'b']); - /// ``` - /// - /// Rotating a subslice: - /// - /// ``` - /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f']; - /// a[1..5].rotate_left(1); - /// assert_eq!(a, ['a', 'c', 'd', 'e', 'b', 'f']); - /// ``` - #[stable(feature = "slice_rotate", since = "1.26.0")] - pub fn rotate_left(&mut self, mid: usize) { - core_slice::SliceExt::rotate_left(self, mid); - } - - /// Rotates the slice in-place such that the first `self.len() - k` - /// elements of the slice move to the end while the last `k` elements move - /// to the front. After calling `rotate_right`, the element previously at - /// index `self.len() - k` will become the first element in the slice. - /// - /// # Panics - /// - /// This function will panic if `k` is greater than the length of the - /// slice. Note that `k == self.len()` does _not_ panic and is a no-op - /// rotation. - /// - /// # Complexity - /// - /// Takes linear (in `self.len()`) time. - /// - /// # Examples - /// - /// ``` - /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f']; - /// a.rotate_right(2); - /// assert_eq!(a, ['e', 'f', 'a', 'b', 'c', 'd']); - /// ``` - /// - /// Rotate a subslice: - /// - /// ``` - /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f']; - /// a[1..5].rotate_right(1); - /// assert_eq!(a, ['a', 'e', 'b', 'c', 'd', 'f']); - /// ``` - #[stable(feature = "slice_rotate", since = "1.26.0")] - pub fn rotate_right(&mut self, k: usize) { - core_slice::SliceExt::rotate_right(self, k); - } - - /// Copies the elements from `src` into `self`. - /// - /// The length of `src` must be the same as `self`. - /// - /// If `src` implements `Copy`, it can be more performant to use - /// [`copy_from_slice`]. - /// - /// # Panics - /// - /// This function will panic if the two slices have different lengths. - /// - /// # Examples - /// - /// Cloning two elements from a slice into another: - /// - /// ``` - /// let src = [1, 2, 3, 4]; - /// let mut dst = [0, 0]; - /// - /// dst.clone_from_slice(&src[2..]); - /// - /// assert_eq!(src, [1, 2, 3, 4]); - /// assert_eq!(dst, [3, 4]); - /// ``` - /// - /// Rust enforces that there can only be one mutable reference with no - /// immutable references to a particular piece of data in a particular - /// scope. Because of this, attempting to use `clone_from_slice` on a - /// single slice will result in a compile failure: - /// - /// ```compile_fail - /// let mut slice = [1, 2, 3, 4, 5]; - /// - /// slice[..2].clone_from_slice(&slice[3..]); // compile fail! - /// ``` - /// - /// To work around this, we can use [`split_at_mut`] to create two distinct - /// sub-slices from a slice: - /// - /// ``` - /// let mut slice = [1, 2, 3, 4, 5]; - /// - /// { - /// let (left, right) = slice.split_at_mut(2); - /// left.clone_from_slice(&right[1..]); - /// } - /// - /// assert_eq!(slice, [4, 5, 3, 4, 5]); - /// ``` - /// - /// [`copy_from_slice`]: #method.copy_from_slice - /// [`split_at_mut`]: #method.split_at_mut - #[stable(feature = "clone_from_slice", since = "1.7.0")] - pub fn clone_from_slice(&mut self, src: &[T]) where T: Clone { - core_slice::SliceExt::clone_from_slice(self, src) - } - - /// Copies all elements from `src` into `self`, using a memcpy. - /// - /// The length of `src` must be the same as `self`. - /// - /// If `src` does not implement `Copy`, use [`clone_from_slice`]. - /// - /// # Panics - /// - /// This function will panic if the two slices have different lengths. - /// - /// # Examples - /// - /// Copying two elements from a slice into another: - /// - /// ``` - /// let src = [1, 2, 3, 4]; - /// let mut dst = [0, 0]; - /// - /// dst.copy_from_slice(&src[2..]); - /// - /// assert_eq!(src, [1, 2, 3, 4]); - /// assert_eq!(dst, [3, 4]); - /// ``` - /// - /// Rust enforces that there can only be one mutable reference with no - /// immutable references to a particular piece of data in a particular - /// scope. Because of this, attempting to use `copy_from_slice` on a - /// single slice will result in a compile failure: - /// - /// ```compile_fail - /// let mut slice = [1, 2, 3, 4, 5]; - /// - /// slice[..2].copy_from_slice(&slice[3..]); // compile fail! - /// ``` - /// - /// To work around this, we can use [`split_at_mut`] to create two distinct - /// sub-slices from a slice: - /// - /// ``` - /// let mut slice = [1, 2, 3, 4, 5]; - /// - /// { - /// let (left, right) = slice.split_at_mut(2); - /// left.copy_from_slice(&right[1..]); - /// } - /// - /// assert_eq!(slice, [4, 5, 3, 4, 5]); - /// ``` - /// - /// [`clone_from_slice`]: #method.clone_from_slice - /// [`split_at_mut`]: #method.split_at_mut - #[stable(feature = "copy_from_slice", since = "1.9.0")] - pub fn copy_from_slice(&mut self, src: &[T]) where T: Copy { - core_slice::SliceExt::copy_from_slice(self, src) - } - - /// Swaps all elements in `self` with those in `other`. - /// - /// The length of `other` must be the same as `self`. - /// - /// # Panics - /// - /// This function will panic if the two slices have different lengths. - /// - /// # Example - /// - /// Swapping two elements across slices: - /// - /// ``` - /// let mut slice1 = [0, 0]; - /// let mut slice2 = [1, 2, 3, 4]; - /// - /// slice1.swap_with_slice(&mut slice2[2..]); - /// - /// assert_eq!(slice1, [3, 4]); - /// assert_eq!(slice2, [1, 2, 0, 0]); - /// ``` - /// - /// Rust enforces that there can only be one mutable reference to a - /// particular piece of data in a particular scope. Because of this, - /// attempting to use `swap_with_slice` on a single slice will result in - /// a compile failure: - /// - /// ```compile_fail - /// let mut slice = [1, 2, 3, 4, 5]; - /// slice[..2].swap_with_slice(&mut slice[3..]); // compile fail! - /// ``` - /// - /// To work around this, we can use [`split_at_mut`] to create two distinct - /// mutable sub-slices from a slice: - /// - /// ``` - /// let mut slice = [1, 2, 3, 4, 5]; - /// - /// { - /// let (left, right) = slice.split_at_mut(2); - /// left.swap_with_slice(&mut right[1..]); - /// } - /// - /// assert_eq!(slice, [4, 5, 3, 1, 2]); - /// ``` - /// - /// [`split_at_mut`]: #method.split_at_mut - #[stable(feature = "swap_with_slice", since = "1.27.0")] - pub fn swap_with_slice(&mut self, other: &mut [T]) { - core_slice::SliceExt::swap_with_slice(self, other) - } - /// Copies `self` into a new `Vec`. /// /// # Examples @@ -1780,18 +394,83 @@ impl<T> [T] { // NB see hack module in this file hack::into_vec(self) } + + /// Creates a vector by repeating a slice `n` times. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(repeat_generic_slice)] + /// + /// fn main() { + /// assert_eq!([1, 2].repeat(3), vec![1, 2, 1, 2, 1, 2]); + /// } + /// ``` + #[unstable(feature = "repeat_generic_slice", + reason = "it's on str, why not on slice?", + issue = "48784")] + pub fn repeat(&self, n: usize) -> Vec<T> where T: Copy { + if n == 0 { + return Vec::new(); + } + + // If `n` is larger than zero, it can be split as + // `n = 2^expn + rem (2^expn > rem, expn >= 0, rem >= 0)`. + // `2^expn` is the number represented by the leftmost '1' bit of `n`, + // and `rem` is the remaining part of `n`. + + // Using `Vec` to access `set_len()`. + let mut buf = Vec::with_capacity(self.len() * n); + + // `2^expn` repetition is done by doubling `buf` `expn`-times. + buf.extend(self); + { + let mut m = n >> 1; + // If `m > 0`, there are remaining bits up to the leftmost '1'. + while m > 0 { + // `buf.extend(buf)`: + unsafe { + ptr::copy_nonoverlapping( + buf.as_ptr(), + (buf.as_mut_ptr() as *mut T).add(buf.len()), + buf.len(), + ); + // `buf` has capacity of `self.len() * n`. + let buf_len = buf.len(); + buf.set_len(buf_len * 2); + } + + m >>= 1; + } + } + + // `rem` (`= n - 2^expn`) repetition is done by copying + // first `rem` repetitions from `buf` itself. + let rem_len = self.len() * n - buf.len(); // `self.len() * rem` + if rem_len > 0 { + // `buf.extend(buf[0 .. rem_len])`: + unsafe { + // This is non-overlapping since `2^expn > rem`. + ptr::copy_nonoverlapping( + buf.as_ptr(), + (buf.as_mut_ptr() as *mut T).add(buf.len()), + rem_len, + ); + // `buf.len() + rem_len` equals to `buf.capacity()` (`= self.len() * n`). + let buf_cap = buf.capacity(); + buf.set_len(buf_cap); + } + } + buf + } } -#[lang = "slice_u8"] +#[cfg_attr(stage0, lang = "slice_u8")] +#[cfg_attr(not(stage0), lang = "slice_u8_alloc")] #[cfg(not(test))] impl [u8] { - /// Checks if all bytes in this slice are within the ASCII range. - #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[inline] - pub fn is_ascii(&self) -> bool { - self.iter().all(|b| b.is_ascii()) - } - /// Returns a vector containing a copy of this slice where each byte /// is mapped to its ASCII upper case equivalent. /// @@ -1826,52 +505,8 @@ impl [u8] { me } - /// Checks that two slices are an ASCII case-insensitive match. - /// - /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`, - /// but without allocating and copying temporaries. - #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[inline] - pub fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool { - self.len() == other.len() && - self.iter().zip(other).all(|(a, b)| { - a.eq_ignore_ascii_case(b) - }) - } - - /// Converts this slice to its ASCII upper case equivalent in-place. - /// - /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', - /// but non-ASCII letters are unchanged. - /// - /// To return a new uppercased value without modifying the existing one, use - /// [`to_ascii_uppercase`]. - /// - /// [`to_ascii_uppercase`]: #method.to_ascii_uppercase - #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[inline] - pub fn make_ascii_uppercase(&mut self) { - for byte in self { - byte.make_ascii_uppercase(); - } - } - - /// Converts this slice to its ASCII lower case equivalent in-place. - /// - /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', - /// but non-ASCII letters are unchanged. - /// - /// To return a new lowercased value without modifying the existing one, use - /// [`to_ascii_lowercase`]. - /// - /// [`to_ascii_lowercase`]: #method.to_ascii_lowercase - #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[inline] - pub fn make_ascii_lowercase(&mut self) { - for byte in self { - byte.make_ascii_lowercase(); - } - } + #[cfg(stage0)] + slice_u8_core_methods!(); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index 0e708465332..cac94edf649 100644 --- a/src/liballoc/str.rs +++ b/src/liballoc/str.rs @@ -40,6 +40,7 @@ use core::fmt; use core::str as core_str; +#[cfg(stage0)] use core::str::StrExt; use core::str::pattern::Pattern; use core::str::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher}; use core::mem; @@ -76,7 +77,8 @@ pub use core::str::{from_utf8_unchecked, from_utf8_unchecked_mut, ParseBoolError pub use core::str::SplitWhitespace; #[stable(feature = "rust1", since = "1.0.0")] pub use core::str::pattern; - +#[stable(feature = "encode_utf16", since = "1.8.0")] +pub use core::str::EncodeUtf16; #[unstable(feature = "slice_concat_ext", reason = "trait should not have to exist", @@ -133,64 +135,6 @@ impl<S: Borrow<str>> SliceConcatExt<str> for [S] { } } -/// An iterator of [`u16`] over the string encoded as UTF-16. -/// -/// [`u16`]: ../../std/primitive.u16.html -/// -/// This struct is created by the [`encode_utf16`] method on [`str`]. -/// See its documentation for more. -/// -/// [`encode_utf16`]: ../../std/primitive.str.html#method.encode_utf16 -/// [`str`]: ../../std/primitive.str.html -#[derive(Clone)] -#[stable(feature = "encode_utf16", since = "1.8.0")] -pub struct EncodeUtf16<'a> { - chars: Chars<'a>, - extra: u16, -} - -#[stable(feature = "collection_debug", since = "1.17.0")] -impl<'a> fmt::Debug for EncodeUtf16<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad("EncodeUtf16 { .. }") - } -} - -#[stable(feature = "encode_utf16", since = "1.8.0")] -impl<'a> Iterator for EncodeUtf16<'a> { - type Item = u16; - - #[inline] - fn next(&mut self) -> Option<u16> { - if self.extra != 0 { - let tmp = self.extra; - self.extra = 0; - return Some(tmp); - } - - let mut buf = [0; 2]; - self.chars.next().map(|ch| { - let n = ch.encode_utf16(&mut buf).len(); - if n == 2 { - self.extra = buf[1]; - } - buf[0] - }) - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - let (low, high) = self.chars.size_hint(); - // every char gets either one u16 or two u16, - // so this iterator is between 1 or 2 times as - // long as the underlying iterator. - (low, high.and_then(|n| n.checked_mul(2))) - } -} - -#[stable(feature = "fused", since = "1.26.0")] -impl<'a> FusedIterator for EncodeUtf16<'a> {} - #[stable(feature = "rust1", since = "1.0.0")] impl Borrow<str> for String { #[inline] @@ -214,1605 +158,12 @@ impl ToOwned for str { } /// Methods for string slices. -#[lang = "str"] +#[cfg_attr(stage0, lang = "str")] +#[cfg_attr(not(stage0), lang = "str_alloc")] #[cfg(not(test))] impl str { - /// Returns the length of `self`. - /// - /// This length is in bytes, not [`char`]s or graphemes. In other words, - /// it may not be what a human considers the length of the string. - /// - /// [`char`]: primitive.char.html - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let len = "foo".len(); - /// assert_eq!(3, len); - /// - /// let len = "ƒoo".len(); // fancy f! - /// assert_eq!(4, len); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn len(&self) -> usize { - core_str::StrExt::len(self) - } - - /// Returns `true` if `self` has a length of zero bytes. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let s = ""; - /// assert!(s.is_empty()); - /// - /// let s = "not empty"; - /// assert!(!s.is_empty()); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn is_empty(&self) -> bool { - core_str::StrExt::is_empty(self) - } - - /// Checks that `index`-th byte lies at the start and/or end of a - /// UTF-8 code point sequence. - /// - /// The start and end of the string (when `index == self.len()`) are - /// considered to be - /// boundaries. - /// - /// Returns `false` if `index` is greater than `self.len()`. - /// - /// # Examples - /// - /// ``` - /// let s = "Löwe 老虎 Léopard"; - /// assert!(s.is_char_boundary(0)); - /// // start of `老` - /// assert!(s.is_char_boundary(6)); - /// assert!(s.is_char_boundary(s.len())); - /// - /// // second byte of `ö` - /// assert!(!s.is_char_boundary(2)); - /// - /// // third byte of `老` - /// assert!(!s.is_char_boundary(8)); - /// ``` - #[stable(feature = "is_char_boundary", since = "1.9.0")] - #[inline] - pub fn is_char_boundary(&self, index: usize) -> bool { - core_str::StrExt::is_char_boundary(self, index) - } - - /// Converts a string slice to a byte slice. To convert the byte slice back - /// into a string slice, use the [`str::from_utf8`] function. - /// - /// [`str::from_utf8`]: ./str/fn.from_utf8.html - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let bytes = "bors".as_bytes(); - /// assert_eq!(b"bors", bytes); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline(always)] - pub fn as_bytes(&self) -> &[u8] { - core_str::StrExt::as_bytes(self) - } - - /// Converts a mutable string slice to a mutable byte slice. To convert the - /// mutable byte slice back into a mutable string slice, use the - /// [`str::from_utf8_mut`] function. - /// - /// [`str::from_utf8_mut`]: ./str/fn.from_utf8_mut.html - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let mut s = String::from("Hello"); - /// let bytes = unsafe { s.as_bytes_mut() }; - /// - /// assert_eq!(b"Hello", bytes); - /// ``` - /// - /// Mutability: - /// - /// ``` - /// let mut s = String::from("🗻∈🌏"); - /// - /// unsafe { - /// let bytes = s.as_bytes_mut(); - /// - /// bytes[0] = 0xF0; - /// bytes[1] = 0x9F; - /// bytes[2] = 0x8D; - /// bytes[3] = 0x94; - /// } - /// - /// assert_eq!("🍔∈🌏", s); - /// ``` - #[stable(feature = "str_mut_extras", since = "1.20.0")] - #[inline(always)] - pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] { - core_str::StrExt::as_bytes_mut(self) - } - - /// Converts a string slice to a raw pointer. - /// - /// As string slices are a slice of bytes, the raw pointer points to a - /// [`u8`]. This pointer will be pointing to the first byte of the string - /// slice. - /// - /// [`u8`]: primitive.u8.html - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let s = "Hello"; - /// let ptr = s.as_ptr(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn as_ptr(&self) -> *const u8 { - core_str::StrExt::as_ptr(self) - } - - /// Returns a subslice of `str`. - /// - /// This is the non-panicking alternative to indexing the `str`. Returns - /// [`None`] whenever equivalent indexing operation would panic. - /// - /// [`None`]: option/enum.Option.html#variant.None - /// - /// # Examples - /// - /// ``` - /// let v = String::from("🗻∈🌏"); - /// - /// assert_eq!(Some("🗻"), v.get(0..4)); - /// - /// // indices not on UTF-8 sequence boundaries - /// assert!(v.get(1..).is_none()); - /// assert!(v.get(..8).is_none()); - /// - /// // out of bounds - /// assert!(v.get(..42).is_none()); - /// ``` - #[stable(feature = "str_checked_slicing", since = "1.20.0")] - #[inline] - pub fn get<I: SliceIndex<str>>(&self, i: I) -> Option<&I::Output> { - core_str::StrExt::get(self, i) - } - - /// Returns a mutable subslice of `str`. - /// - /// This is the non-panicking alternative to indexing the `str`. Returns - /// [`None`] whenever equivalent indexing operation would panic. - /// - /// [`None`]: option/enum.Option.html#variant.None - /// - /// # Examples - /// - /// ``` - /// let mut v = String::from("hello"); - /// // correct length - /// assert!(v.get_mut(0..5).is_some()); - /// // out of bounds - /// assert!(v.get_mut(..42).is_none()); - /// assert_eq!(Some("he"), v.get_mut(0..2).map(|v| &*v)); - /// - /// assert_eq!("hello", v); - /// { - /// let s = v.get_mut(0..2); - /// let s = s.map(|s| { - /// s.make_ascii_uppercase(); - /// &*s - /// }); - /// assert_eq!(Some("HE"), s); - /// } - /// assert_eq!("HEllo", v); - /// ``` - #[stable(feature = "str_checked_slicing", since = "1.20.0")] - #[inline] - pub fn get_mut<I: SliceIndex<str>>(&mut self, i: I) -> Option<&mut I::Output> { - core_str::StrExt::get_mut(self, i) - } - - /// Returns a unchecked subslice of `str`. - /// - /// This is the unchecked alternative to indexing the `str`. - /// - /// # Safety - /// - /// Callers of this function are responsible that these preconditions are - /// satisfied: - /// - /// * The starting index must come before the ending index; - /// * Indexes must be within bounds of the original slice; - /// * Indexes must lie on UTF-8 sequence boundaries. - /// - /// Failing that, the returned string slice may reference invalid memory or - /// violate the invariants communicated by the `str` type. - /// - /// # Examples - /// - /// ``` - /// let v = "🗻∈🌏"; - /// unsafe { - /// assert_eq!("🗻", v.get_unchecked(0..4)); - /// assert_eq!("∈", v.get_unchecked(4..7)); - /// assert_eq!("🌏", v.get_unchecked(7..11)); - /// } - /// ``` - #[stable(feature = "str_checked_slicing", since = "1.20.0")] - #[inline] - pub unsafe fn get_unchecked<I: SliceIndex<str>>(&self, i: I) -> &I::Output { - core_str::StrExt::get_unchecked(self, i) - } - - /// Returns a mutable, unchecked subslice of `str`. - /// - /// This is the unchecked alternative to indexing the `str`. - /// - /// # Safety - /// - /// Callers of this function are responsible that these preconditions are - /// satisfied: - /// - /// * The starting index must come before the ending index; - /// * Indexes must be within bounds of the original slice; - /// * Indexes must lie on UTF-8 sequence boundaries. - /// - /// Failing that, the returned string slice may reference invalid memory or - /// violate the invariants communicated by the `str` type. - /// - /// # Examples - /// - /// ``` - /// let mut v = String::from("🗻∈🌏"); - /// unsafe { - /// assert_eq!("🗻", v.get_unchecked_mut(0..4)); - /// assert_eq!("∈", v.get_unchecked_mut(4..7)); - /// assert_eq!("🌏", v.get_unchecked_mut(7..11)); - /// } - /// ``` - #[stable(feature = "str_checked_slicing", since = "1.20.0")] - #[inline] - pub unsafe fn get_unchecked_mut<I: SliceIndex<str>>(&mut self, i: I) -> &mut I::Output { - core_str::StrExt::get_unchecked_mut(self, i) - } - - /// Creates a string slice from another string slice, bypassing safety - /// checks. - /// - /// This is generally not recommended, use with caution! For a safe - /// alternative see [`str`] and [`Index`]. - /// - /// [`str`]: primitive.str.html - /// [`Index`]: ops/trait.Index.html - /// - /// This new slice goes from `begin` to `end`, including `begin` but - /// excluding `end`. - /// - /// To get a mutable string slice instead, see the - /// [`slice_mut_unchecked`] method. - /// - /// [`slice_mut_unchecked`]: #method.slice_mut_unchecked - /// - /// # Safety - /// - /// Callers of this function are responsible that three preconditions are - /// satisfied: - /// - /// * `begin` must come before `end`. - /// * `begin` and `end` must be byte positions within the string slice. - /// * `begin` and `end` must lie on UTF-8 sequence boundaries. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let s = "Löwe 老虎 Léopard"; - /// - /// unsafe { - /// assert_eq!("Löwe 老虎 Léopard", s.slice_unchecked(0, 21)); - /// } - /// - /// let s = "Hello, world!"; - /// - /// unsafe { - /// assert_eq!("world", s.slice_unchecked(7, 12)); - /// } - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str { - core_str::StrExt::slice_unchecked(self, begin, end) - } - - /// Creates a string slice from another string slice, bypassing safety - /// checks. - /// This is generally not recommended, use with caution! For a safe - /// alternative see [`str`] and [`IndexMut`]. - /// - /// [`str`]: primitive.str.html - /// [`IndexMut`]: ops/trait.IndexMut.html - /// - /// This new slice goes from `begin` to `end`, including `begin` but - /// excluding `end`. - /// - /// To get an immutable string slice instead, see the - /// [`slice_unchecked`] method. - /// - /// [`slice_unchecked`]: #method.slice_unchecked - /// - /// # Safety - /// - /// Callers of this function are responsible that three preconditions are - /// satisfied: - /// - /// * `begin` must come before `end`. - /// * `begin` and `end` must be byte positions within the string slice. - /// * `begin` and `end` must lie on UTF-8 sequence boundaries. - #[stable(feature = "str_slice_mut", since = "1.5.0")] - #[inline] - pub unsafe fn slice_mut_unchecked(&mut self, begin: usize, end: usize) -> &mut str { - core_str::StrExt::slice_mut_unchecked(self, begin, end) - } - - /// Divide one string slice into two at an index. - /// - /// The argument, `mid`, should be a byte offset from the start of the - /// string. It must also be on the boundary of a UTF-8 code point. - /// - /// The two slices returned go from the start of the string slice to `mid`, - /// and from `mid` to the end of the string slice. - /// - /// To get mutable string slices instead, see the [`split_at_mut`] - /// method. - /// - /// [`split_at_mut`]: #method.split_at_mut - /// - /// # Panics - /// - /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is - /// beyond the last code point of the string slice. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let s = "Per Martin-Löf"; - /// - /// let (first, last) = s.split_at(3); - /// - /// assert_eq!("Per", first); - /// assert_eq!(" Martin-Löf", last); - /// ``` - #[inline] - #[stable(feature = "str_split_at", since = "1.4.0")] - pub fn split_at(&self, mid: usize) -> (&str, &str) { - core_str::StrExt::split_at(self, mid) - } - - /// Divide one mutable string slice into two at an index. - /// - /// The argument, `mid`, should be a byte offset from the start of the - /// string. It must also be on the boundary of a UTF-8 code point. - /// - /// The two slices returned go from the start of the string slice to `mid`, - /// and from `mid` to the end of the string slice. - /// - /// To get immutable string slices instead, see the [`split_at`] method. - /// - /// [`split_at`]: #method.split_at - /// - /// # Panics - /// - /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is - /// beyond the last code point of the string slice. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let mut s = "Per Martin-Löf".to_string(); - /// { - /// let (first, last) = s.split_at_mut(3); - /// first.make_ascii_uppercase(); - /// assert_eq!("PER", first); - /// assert_eq!(" Martin-Löf", last); - /// } - /// assert_eq!("PER Martin-Löf", s); - /// ``` - #[inline] - #[stable(feature = "str_split_at", since = "1.4.0")] - pub fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str) { - core_str::StrExt::split_at_mut(self, mid) - } - - /// Returns an iterator over the [`char`]s of a string slice. - /// - /// As a string slice consists of valid UTF-8, we can iterate through a - /// string slice by [`char`]. This method returns such an iterator. - /// - /// It's important to remember that [`char`] represents a Unicode Scalar - /// Value, and may not match your idea of what a 'character' is. Iteration - /// over grapheme clusters may be what you actually want. - /// - /// [`char`]: primitive.char.html - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let word = "goodbye"; - /// - /// let count = word.chars().count(); - /// assert_eq!(7, count); - /// - /// let mut chars = word.chars(); - /// - /// assert_eq!(Some('g'), chars.next()); - /// assert_eq!(Some('o'), chars.next()); - /// assert_eq!(Some('o'), chars.next()); - /// assert_eq!(Some('d'), chars.next()); - /// assert_eq!(Some('b'), chars.next()); - /// assert_eq!(Some('y'), chars.next()); - /// assert_eq!(Some('e'), chars.next()); - /// - /// assert_eq!(None, chars.next()); - /// ``` - /// - /// Remember, [`char`]s may not match your human intuition about characters: - /// - /// ``` - /// let y = "y̆"; - /// - /// let mut chars = y.chars(); - /// - /// assert_eq!(Some('y'), chars.next()); // not 'y̆' - /// assert_eq!(Some('\u{0306}'), chars.next()); - /// - /// assert_eq!(None, chars.next()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn chars(&self) -> Chars { - core_str::StrExt::chars(self) - } - /// Returns an iterator over the [`char`]s of a string slice, and their - /// positions. - /// - /// As a string slice consists of valid UTF-8, we can iterate through a - /// string slice by [`char`]. This method returns an iterator of both - /// these [`char`]s, as well as their byte positions. - /// - /// The iterator yields tuples. The position is first, the [`char`] is - /// second. - /// - /// [`char`]: primitive.char.html - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let word = "goodbye"; - /// - /// let count = word.char_indices().count(); - /// assert_eq!(7, count); - /// - /// let mut char_indices = word.char_indices(); - /// - /// assert_eq!(Some((0, 'g')), char_indices.next()); - /// assert_eq!(Some((1, 'o')), char_indices.next()); - /// assert_eq!(Some((2, 'o')), char_indices.next()); - /// assert_eq!(Some((3, 'd')), char_indices.next()); - /// assert_eq!(Some((4, 'b')), char_indices.next()); - /// assert_eq!(Some((5, 'y')), char_indices.next()); - /// assert_eq!(Some((6, 'e')), char_indices.next()); - /// - /// assert_eq!(None, char_indices.next()); - /// ``` - /// - /// Remember, [`char`]s may not match your human intuition about characters: - /// - /// ``` - /// let yes = "y̆es"; - /// - /// let mut char_indices = yes.char_indices(); - /// - /// assert_eq!(Some((0, 'y')), char_indices.next()); // not (0, 'y̆') - /// assert_eq!(Some((1, '\u{0306}')), char_indices.next()); - /// - /// // note the 3 here - the last character took up two bytes - /// assert_eq!(Some((3, 'e')), char_indices.next()); - /// assert_eq!(Some((4, 's')), char_indices.next()); - /// - /// assert_eq!(None, char_indices.next()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn char_indices(&self) -> CharIndices { - core_str::StrExt::char_indices(self) - } - - /// An iterator over the bytes of a string slice. - /// - /// As a string slice consists of a sequence of bytes, we can iterate - /// through a string slice by byte. This method returns such an iterator. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let mut bytes = "bors".bytes(); - /// - /// assert_eq!(Some(b'b'), bytes.next()); - /// assert_eq!(Some(b'o'), bytes.next()); - /// assert_eq!(Some(b'r'), bytes.next()); - /// assert_eq!(Some(b's'), bytes.next()); - /// - /// assert_eq!(None, bytes.next()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn bytes(&self) -> Bytes { - core_str::StrExt::bytes(self) - } - - /// Split a string slice by whitespace. - /// - /// The iterator returned will return string slices that are sub-slices of - /// the original string slice, separated by any amount of whitespace. - /// - /// 'Whitespace' is defined according to the terms of the Unicode Derived - /// Core Property `White_Space`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let mut iter = "A few words".split_whitespace(); - /// - /// assert_eq!(Some("A"), iter.next()); - /// assert_eq!(Some("few"), iter.next()); - /// assert_eq!(Some("words"), iter.next()); - /// - /// assert_eq!(None, iter.next()); - /// ``` - /// - /// All kinds of whitespace are considered: - /// - /// ``` - /// let mut iter = " Mary had\ta\u{2009}little \n\t lamb".split_whitespace(); - /// assert_eq!(Some("Mary"), iter.next()); - /// assert_eq!(Some("had"), iter.next()); - /// assert_eq!(Some("a"), iter.next()); - /// assert_eq!(Some("little"), iter.next()); - /// assert_eq!(Some("lamb"), iter.next()); - /// - /// assert_eq!(None, iter.next()); - /// ``` - #[stable(feature = "split_whitespace", since = "1.1.0")] - #[inline] - pub fn split_whitespace(&self) -> SplitWhitespace { - StrExt::split_whitespace(self) - } - - /// An iterator over the lines of a string, as string slices. - /// - /// Lines are ended with either a newline (`\n`) or a carriage return with - /// a line feed (`\r\n`). - /// - /// The final line ending is optional. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let text = "foo\r\nbar\n\nbaz\n"; - /// let mut lines = text.lines(); - /// - /// assert_eq!(Some("foo"), lines.next()); - /// assert_eq!(Some("bar"), lines.next()); - /// assert_eq!(Some(""), lines.next()); - /// assert_eq!(Some("baz"), lines.next()); - /// - /// assert_eq!(None, lines.next()); - /// ``` - /// - /// The final line ending isn't required: - /// - /// ``` - /// let text = "foo\nbar\n\r\nbaz"; - /// let mut lines = text.lines(); - /// - /// assert_eq!(Some("foo"), lines.next()); - /// assert_eq!(Some("bar"), lines.next()); - /// assert_eq!(Some(""), lines.next()); - /// assert_eq!(Some("baz"), lines.next()); - /// - /// assert_eq!(None, lines.next()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn lines(&self) -> Lines { - core_str::StrExt::lines(self) - } - - /// An iterator over the lines of a string. - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_deprecated(since = "1.4.0", reason = "use lines() instead now")] - #[inline] - #[allow(deprecated)] - pub fn lines_any(&self) -> LinesAny { - core_str::StrExt::lines_any(self) - } - - /// Returns an iterator of `u16` over the string encoded as UTF-16. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let text = "Zażółć gęślą jaźń"; - /// - /// let utf8_len = text.len(); - /// let utf16_len = text.encode_utf16().count(); - /// - /// assert!(utf16_len <= utf8_len); - /// ``` - #[stable(feature = "encode_utf16", since = "1.8.0")] - pub fn encode_utf16(&self) -> EncodeUtf16 { - EncodeUtf16 { chars: self[..].chars(), extra: 0 } - } - - /// Returns `true` if the given pattern matches a sub-slice of - /// this string slice. - /// - /// Returns `false` if it does not. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let bananas = "bananas"; - /// - /// assert!(bananas.contains("nana")); - /// assert!(!bananas.contains("apples")); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool { - core_str::StrExt::contains(self, pat) - } - - /// Returns `true` if the given pattern matches a prefix of this - /// string slice. - /// - /// Returns `false` if it does not. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let bananas = "bananas"; - /// - /// assert!(bananas.starts_with("bana")); - /// assert!(!bananas.starts_with("nana")); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn starts_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool { - core_str::StrExt::starts_with(self, pat) - } - - /// Returns `true` if the given pattern matches a suffix of this - /// string slice. - /// - /// Returns `false` if it does not. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let bananas = "bananas"; - /// - /// assert!(bananas.ends_with("anas")); - /// assert!(!bananas.ends_with("nana")); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn ends_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool - where P::Searcher: ReverseSearcher<'a> - { - core_str::StrExt::ends_with(self, pat) - } - - /// Returns the byte index of the first character of this string slice that - /// matches the pattern. - /// - /// Returns [`None`] if the pattern doesn't match. - /// - /// The pattern can be a `&str`, [`char`], or a closure that determines if - /// a character matches. - /// - /// [`char`]: primitive.char.html - /// [`None`]: option/enum.Option.html#variant.None - /// - /// # Examples - /// - /// Simple patterns: - /// - /// ``` - /// let s = "Löwe 老虎 Léopard"; - /// - /// assert_eq!(s.find('L'), Some(0)); - /// assert_eq!(s.find('é'), Some(14)); - /// assert_eq!(s.find("Léopard"), Some(13)); - /// ``` - /// - /// More complex patterns using point-free style and closures: - /// - /// ``` - /// let s = "Löwe 老虎 Léopard"; - /// - /// assert_eq!(s.find(char::is_whitespace), Some(5)); - /// assert_eq!(s.find(char::is_lowercase), Some(1)); - /// assert_eq!(s.find(|c: char| c.is_whitespace() || c.is_lowercase()), Some(1)); - /// assert_eq!(s.find(|c: char| (c < 'o') && (c > 'a')), Some(4)); - /// ``` - /// - /// Not finding the pattern: - /// - /// ``` - /// let s = "Löwe 老虎 Léopard"; - /// let x: &[_] = &['1', '2']; - /// - /// assert_eq!(s.find(x), None); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> { - core_str::StrExt::find(self, pat) - } - - /// Returns the byte index of the last character of this string slice that - /// matches the pattern. - /// - /// Returns [`None`] if the pattern doesn't match. - /// - /// The pattern can be a `&str`, [`char`], or a closure that determines if - /// a character matches. - /// - /// [`char`]: primitive.char.html - /// [`None`]: option/enum.Option.html#variant.None - /// - /// # Examples - /// - /// Simple patterns: - /// - /// ``` - /// let s = "Löwe 老虎 Léopard"; - /// - /// assert_eq!(s.rfind('L'), Some(13)); - /// assert_eq!(s.rfind('é'), Some(14)); - /// ``` - /// - /// More complex patterns with closures: - /// - /// ``` - /// let s = "Löwe 老虎 Léopard"; - /// - /// assert_eq!(s.rfind(char::is_whitespace), Some(12)); - /// assert_eq!(s.rfind(char::is_lowercase), Some(20)); - /// ``` - /// - /// Not finding the pattern: - /// - /// ``` - /// let s = "Löwe 老虎 Léopard"; - /// let x: &[_] = &['1', '2']; - /// - /// assert_eq!(s.rfind(x), None); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> - where P::Searcher: ReverseSearcher<'a> - { - core_str::StrExt::rfind(self, pat) - } - - /// An iterator over substrings of this string slice, separated by - /// characters matched by a pattern. - /// - /// The pattern can be a `&str`, [`char`], or a closure that determines the - /// split. - /// - /// # Iterator behavior - /// - /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern - /// allows a reverse search and forward/reverse search yields the same - /// elements. This is true for, eg, [`char`] but not for `&str`. - /// - /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html - /// - /// If the pattern allows a reverse search but its results might differ - /// from a forward search, the [`rsplit`] method can be used. - /// - /// [`char`]: primitive.char.html - /// [`rsplit`]: #method.rsplit - /// - /// # Examples - /// - /// Simple patterns: - /// - /// ``` - /// let v: Vec<&str> = "Mary had a little lamb".split(' ').collect(); - /// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]); - /// - /// let v: Vec<&str> = "".split('X').collect(); - /// assert_eq!(v, [""]); - /// - /// let v: Vec<&str> = "lionXXtigerXleopard".split('X').collect(); - /// assert_eq!(v, ["lion", "", "tiger", "leopard"]); - /// - /// let v: Vec<&str> = "lion::tiger::leopard".split("::").collect(); - /// assert_eq!(v, ["lion", "tiger", "leopard"]); - /// - /// let v: Vec<&str> = "abc1def2ghi".split(char::is_numeric).collect(); - /// assert_eq!(v, ["abc", "def", "ghi"]); - /// - /// let v: Vec<&str> = "lionXtigerXleopard".split(char::is_uppercase).collect(); - /// assert_eq!(v, ["lion", "tiger", "leopard"]); - /// ``` - /// - /// A more complex pattern, using a closure: - /// - /// ``` - /// let v: Vec<&str> = "abc1defXghi".split(|c| c == '1' || c == 'X').collect(); - /// assert_eq!(v, ["abc", "def", "ghi"]); - /// ``` - /// - /// If a string contains multiple contiguous separators, you will end up - /// with empty strings in the output: - /// - /// ``` - /// let x = "||||a||b|c".to_string(); - /// let d: Vec<_> = x.split('|').collect(); - /// - /// assert_eq!(d, &["", "", "", "", "a", "", "b", "c"]); - /// ``` - /// - /// Contiguous separators are separated by the empty string. - /// - /// ``` - /// let x = "(///)".to_string(); - /// let d: Vec<_> = x.split('/').collect(); - /// - /// assert_eq!(d, &["(", "", "", ")"]); - /// ``` - /// - /// Separators at the start or end of a string are neighbored - /// by empty strings. - /// - /// ``` - /// let d: Vec<_> = "010".split("0").collect(); - /// assert_eq!(d, &["", "1", ""]); - /// ``` - /// - /// When the empty string is used as a separator, it separates - /// every character in the string, along with the beginning - /// and end of the string. - /// - /// ``` - /// let f: Vec<_> = "rust".split("").collect(); - /// assert_eq!(f, &["", "r", "u", "s", "t", ""]); - /// ``` - /// - /// Contiguous separators can lead to possibly surprising behavior - /// when whitespace is used as the separator. This code is correct: - /// - /// ``` - /// let x = " a b c".to_string(); - /// let d: Vec<_> = x.split(' ').collect(); - /// - /// assert_eq!(d, &["", "", "", "", "a", "", "b", "c"]); - /// ``` - /// - /// It does _not_ give you: - /// - /// ```,ignore - /// assert_eq!(d, &["a", "b", "c"]); - /// ``` - /// - /// Use [`split_whitespace`] for this behavior. - /// - /// [`split_whitespace`]: #method.split_whitespace - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> { - core_str::StrExt::split(self, pat) - } - - /// An iterator over substrings of the given string slice, separated by - /// characters matched by a pattern and yielded in reverse order. - /// - /// The pattern can be a `&str`, [`char`], or a closure that determines the - /// split. - /// - /// [`char`]: primitive.char.html - /// - /// # Iterator behavior - /// - /// The returned iterator requires that the pattern supports a reverse - /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse - /// search yields the same elements. - /// - /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html - /// - /// For iterating from the front, the [`split`] method can be used. - /// - /// [`split`]: #method.split - /// - /// # Examples - /// - /// Simple patterns: - /// - /// ``` - /// let v: Vec<&str> = "Mary had a little lamb".rsplit(' ').collect(); - /// assert_eq!(v, ["lamb", "little", "a", "had", "Mary"]); - /// - /// let v: Vec<&str> = "".rsplit('X').collect(); - /// assert_eq!(v, [""]); - /// - /// let v: Vec<&str> = "lionXXtigerXleopard".rsplit('X').collect(); - /// assert_eq!(v, ["leopard", "tiger", "", "lion"]); - /// - /// let v: Vec<&str> = "lion::tiger::leopard".rsplit("::").collect(); - /// assert_eq!(v, ["leopard", "tiger", "lion"]); - /// ``` - /// - /// A more complex pattern, using a closure: - /// - /// ``` - /// let v: Vec<&str> = "abc1defXghi".rsplit(|c| c == '1' || c == 'X').collect(); - /// assert_eq!(v, ["ghi", "def", "abc"]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn rsplit<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplit<'a, P> - where P::Searcher: ReverseSearcher<'a> - { - core_str::StrExt::rsplit(self, pat) - } - - /// An iterator over substrings of the given string slice, separated by - /// characters matched by a pattern. - /// - /// The pattern can be a `&str`, [`char`], or a closure that determines the - /// split. - /// - /// Equivalent to [`split`], except that the trailing substring - /// is skipped if empty. - /// - /// [`split`]: #method.split - /// - /// This method can be used for string data that is _terminated_, - /// rather than _separated_ by a pattern. - /// - /// # Iterator behavior - /// - /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern - /// allows a reverse search and forward/reverse search yields the same - /// elements. This is true for, eg, [`char`] but not for `&str`. - /// - /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html - /// [`char`]: primitive.char.html - /// - /// If the pattern allows a reverse search but its results might differ - /// from a forward search, the [`rsplit_terminator`] method can be used. - /// - /// [`rsplit_terminator`]: #method.rsplit_terminator - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let v: Vec<&str> = "A.B.".split_terminator('.').collect(); - /// assert_eq!(v, ["A", "B"]); - /// - /// let v: Vec<&str> = "A..B..".split_terminator(".").collect(); - /// assert_eq!(v, ["A", "", "B", ""]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator<'a, P> { - core_str::StrExt::split_terminator(self, pat) - } - - /// An iterator over substrings of `self`, separated by characters - /// matched by a pattern and yielded in reverse order. - /// - /// The pattern can be a simple `&str`, [`char`], or a closure that - /// determines the split. - /// Additional libraries might provide more complex patterns like - /// regular expressions. - /// - /// [`char`]: primitive.char.html - /// - /// Equivalent to [`split`], except that the trailing substring is - /// skipped if empty. - /// - /// [`split`]: #method.split - /// - /// This method can be used for string data that is _terminated_, - /// rather than _separated_ by a pattern. - /// - /// # Iterator behavior - /// - /// The returned iterator requires that the pattern supports a - /// reverse search, and it will be double ended if a forward/reverse - /// search yields the same elements. - /// - /// For iterating from the front, the [`split_terminator`] method can be - /// used. - /// - /// [`split_terminator`]: #method.split_terminator - /// - /// # Examples - /// - /// ``` - /// let v: Vec<&str> = "A.B.".rsplit_terminator('.').collect(); - /// assert_eq!(v, ["B", "A"]); - /// - /// let v: Vec<&str> = "A..B..".rsplit_terminator(".").collect(); - /// assert_eq!(v, ["", "B", "", "A"]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn rsplit_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplitTerminator<'a, P> - where P::Searcher: ReverseSearcher<'a> - { - core_str::StrExt::rsplit_terminator(self, pat) - } - - /// An iterator over substrings of the given string slice, separated by a - /// pattern, restricted to returning at most `n` items. - /// - /// If `n` substrings are returned, the last substring (the `n`th substring) - /// will contain the remainder of the string. - /// - /// The pattern can be a `&str`, [`char`], or a closure that determines the - /// split. - /// - /// [`char`]: primitive.char.html - /// - /// # Iterator behavior - /// - /// The returned iterator will not be double ended, because it is - /// not efficient to support. - /// - /// If the pattern allows a reverse search, the [`rsplitn`] method can be - /// used. - /// - /// [`rsplitn`]: #method.rsplitn - /// - /// # Examples - /// - /// Simple patterns: - /// - /// ``` - /// let v: Vec<&str> = "Mary had a little lambda".splitn(3, ' ').collect(); - /// assert_eq!(v, ["Mary", "had", "a little lambda"]); - /// - /// let v: Vec<&str> = "lionXXtigerXleopard".splitn(3, "X").collect(); - /// assert_eq!(v, ["lion", "", "tigerXleopard"]); - /// - /// let v: Vec<&str> = "abcXdef".splitn(1, 'X').collect(); - /// assert_eq!(v, ["abcXdef"]); - /// - /// let v: Vec<&str> = "".splitn(1, 'X').collect(); - /// assert_eq!(v, [""]); - /// ``` - /// - /// A more complex pattern, using a closure: - /// - /// ``` - /// let v: Vec<&str> = "abc1defXghi".splitn(2, |c| c == '1' || c == 'X').collect(); - /// assert_eq!(v, ["abc", "defXghi"]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn splitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> SplitN<'a, P> { - core_str::StrExt::splitn(self, n, pat) - } - - /// An iterator over substrings of this string slice, separated by a - /// pattern, starting from the end of the string, restricted to returning - /// at most `n` items. - /// - /// If `n` substrings are returned, the last substring (the `n`th substring) - /// will contain the remainder of the string. - /// - /// The pattern can be a `&str`, [`char`], or a closure that - /// determines the split. - /// - /// [`char`]: primitive.char.html - /// - /// # Iterator behavior - /// - /// The returned iterator will not be double ended, because it is not - /// efficient to support. - /// - /// For splitting from the front, the [`splitn`] method can be used. - /// - /// [`splitn`]: #method.splitn - /// - /// # Examples - /// - /// Simple patterns: - /// - /// ``` - /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(3, ' ').collect(); - /// assert_eq!(v, ["lamb", "little", "Mary had a"]); - /// - /// let v: Vec<&str> = "lionXXtigerXleopard".rsplitn(3, 'X').collect(); - /// assert_eq!(v, ["leopard", "tiger", "lionX"]); - /// - /// let v: Vec<&str> = "lion::tiger::leopard".rsplitn(2, "::").collect(); - /// assert_eq!(v, ["leopard", "lion::tiger"]); - /// ``` - /// - /// A more complex pattern, using a closure: - /// - /// ``` - /// let v: Vec<&str> = "abc1defXghi".rsplitn(2, |c| c == '1' || c == 'X').collect(); - /// assert_eq!(v, ["ghi", "abc1def"]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn rsplitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> RSplitN<'a, P> - where P::Searcher: ReverseSearcher<'a> - { - core_str::StrExt::rsplitn(self, n, pat) - } - - /// An iterator over the disjoint matches of a pattern within the given string - /// slice. - /// - /// The pattern can be a `&str`, [`char`], or a closure that - /// determines if a character matches. - /// - /// [`char`]: primitive.char.html - /// - /// # Iterator behavior - /// - /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern - /// allows a reverse search and forward/reverse search yields the same - /// elements. This is true for, eg, [`char`] but not for `&str`. - /// - /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html - /// [`char`]: primitive.char.html - /// - /// If the pattern allows a reverse search but its results might differ - /// from a forward search, the [`rmatches`] method can be used. - /// - /// [`rmatches`]: #method.rmatches - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let v: Vec<&str> = "abcXXXabcYYYabc".matches("abc").collect(); - /// assert_eq!(v, ["abc", "abc", "abc"]); - /// - /// let v: Vec<&str> = "1abc2abc3".matches(char::is_numeric).collect(); - /// assert_eq!(v, ["1", "2", "3"]); - /// ``` - #[stable(feature = "str_matches", since = "1.2.0")] - #[inline] - pub fn matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> Matches<'a, P> { - core_str::StrExt::matches(self, pat) - } - - /// An iterator over the disjoint matches of a pattern within this string slice, - /// yielded in reverse order. - /// - /// The pattern can be a `&str`, [`char`], or a closure that determines if - /// a character matches. - /// - /// [`char`]: primitive.char.html - /// - /// # Iterator behavior - /// - /// The returned iterator requires that the pattern supports a reverse - /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse - /// search yields the same elements. - /// - /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html - /// - /// For iterating from the front, the [`matches`] method can be used. - /// - /// [`matches`]: #method.matches - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let v: Vec<&str> = "abcXXXabcYYYabc".rmatches("abc").collect(); - /// assert_eq!(v, ["abc", "abc", "abc"]); - /// - /// let v: Vec<&str> = "1abc2abc3".rmatches(char::is_numeric).collect(); - /// assert_eq!(v, ["3", "2", "1"]); - /// ``` - #[stable(feature = "str_matches", since = "1.2.0")] - #[inline] - pub fn rmatches<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatches<'a, P> - where P::Searcher: ReverseSearcher<'a> - { - core_str::StrExt::rmatches(self, pat) - } - - /// An iterator over the disjoint matches of a pattern within this string - /// slice as well as the index that the match starts at. - /// - /// For matches of `pat` within `self` that overlap, only the indices - /// corresponding to the first match are returned. - /// - /// The pattern can be a `&str`, [`char`], or a closure that determines - /// if a character matches. - /// - /// [`char`]: primitive.char.html - /// - /// # Iterator behavior - /// - /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern - /// allows a reverse search and forward/reverse search yields the same - /// elements. This is true for, eg, [`char`] but not for `&str`. - /// - /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html - /// - /// If the pattern allows a reverse search but its results might differ - /// from a forward search, the [`rmatch_indices`] method can be used. - /// - /// [`rmatch_indices`]: #method.rmatch_indices - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let v: Vec<_> = "abcXXXabcYYYabc".match_indices("abc").collect(); - /// assert_eq!(v, [(0, "abc"), (6, "abc"), (12, "abc")]); - /// - /// let v: Vec<_> = "1abcabc2".match_indices("abc").collect(); - /// assert_eq!(v, [(1, "abc"), (4, "abc")]); - /// - /// let v: Vec<_> = "ababa".match_indices("aba").collect(); - /// assert_eq!(v, [(0, "aba")]); // only the first `aba` - /// ``` - #[stable(feature = "str_match_indices", since = "1.5.0")] - #[inline] - pub fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P> { - core_str::StrExt::match_indices(self, pat) - } - - /// An iterator over the disjoint matches of a pattern within `self`, - /// yielded in reverse order along with the index of the match. - /// - /// For matches of `pat` within `self` that overlap, only the indices - /// corresponding to the last match are returned. - /// - /// The pattern can be a `&str`, [`char`], or a closure that determines if a - /// character matches. - /// - /// [`char`]: primitive.char.html - /// - /// # Iterator behavior - /// - /// The returned iterator requires that the pattern supports a reverse - /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse - /// search yields the same elements. - /// - /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html - /// - /// For iterating from the front, the [`match_indices`] method can be used. - /// - /// [`match_indices`]: #method.match_indices - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let v: Vec<_> = "abcXXXabcYYYabc".rmatch_indices("abc").collect(); - /// assert_eq!(v, [(12, "abc"), (6, "abc"), (0, "abc")]); - /// - /// let v: Vec<_> = "1abcabc2".rmatch_indices("abc").collect(); - /// assert_eq!(v, [(4, "abc"), (1, "abc")]); - /// - /// let v: Vec<_> = "ababa".rmatch_indices("aba").collect(); - /// assert_eq!(v, [(2, "aba")]); // only the last `aba` - /// ``` - #[stable(feature = "str_match_indices", since = "1.5.0")] - #[inline] - pub fn rmatch_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatchIndices<'a, P> - where P::Searcher: ReverseSearcher<'a> - { - core_str::StrExt::rmatch_indices(self, pat) - } - - /// Returns a string slice with leading and trailing whitespace removed. - /// - /// 'Whitespace' is defined according to the terms of the Unicode Derived - /// Core Property `White_Space`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let s = " Hello\tworld\t"; - /// - /// assert_eq!("Hello\tworld", s.trim()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn trim(&self) -> &str { - StrExt::trim(self) - } - - /// Returns a string slice with leading whitespace removed. - /// - /// 'Whitespace' is defined according to the terms of the Unicode Derived - /// Core Property `White_Space`. - /// - /// # Text directionality - /// - /// A string is a sequence of bytes. 'Left' in this context means the first - /// position of that byte string; for a language like Arabic or Hebrew - /// which are 'right to left' rather than 'left to right', this will be - /// the _right_ side, not the left. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let s = " Hello\tworld\t"; - /// - /// assert_eq!("Hello\tworld\t", s.trim_left()); - /// ``` - /// - /// Directionality: - /// - /// ``` - /// let s = " English"; - /// assert!(Some('E') == s.trim_left().chars().next()); - /// - /// let s = " עברית"; - /// assert!(Some('ע') == s.trim_left().chars().next()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn trim_left(&self) -> &str { - StrExt::trim_left(self) - } - - /// Returns a string slice with trailing whitespace removed. - /// - /// 'Whitespace' is defined according to the terms of the Unicode Derived - /// Core Property `White_Space`. - /// - /// # Text directionality - /// - /// A string is a sequence of bytes. 'Right' in this context means the last - /// position of that byte string; for a language like Arabic or Hebrew - /// which are 'right to left' rather than 'left to right', this will be - /// the _left_ side, not the right. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let s = " Hello\tworld\t"; - /// - /// assert_eq!(" Hello\tworld", s.trim_right()); - /// ``` - /// - /// Directionality: - /// - /// ``` - /// let s = "English "; - /// assert!(Some('h') == s.trim_right().chars().rev().next()); - /// - /// let s = "עברית "; - /// assert!(Some('ת') == s.trim_right().chars().rev().next()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn trim_right(&self) -> &str { - StrExt::trim_right(self) - } - - /// Returns a string slice with all prefixes and suffixes that match a - /// pattern repeatedly removed. - /// - /// The pattern can be a [`char`] or a closure that determines if a - /// character matches. - /// - /// [`char`]: primitive.char.html - /// - /// # Examples - /// - /// Simple patterns: - /// - /// ``` - /// assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar"); - /// assert_eq!("123foo1bar123".trim_matches(char::is_numeric), "foo1bar"); - /// - /// let x: &[_] = &['1', '2']; - /// assert_eq!("12foo1bar12".trim_matches(x), "foo1bar"); - /// ``` - /// - /// A more complex pattern, using a closure: - /// - /// ``` - /// assert_eq!("1foo1barXX".trim_matches(|c| c == '1' || c == 'X'), "foo1bar"); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn trim_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str - where P::Searcher: DoubleEndedSearcher<'a> - { - core_str::StrExt::trim_matches(self, pat) - } - - /// Returns a string slice with all prefixes that match a pattern - /// repeatedly removed. - /// - /// The pattern can be a `&str`, [`char`], or a closure that determines if - /// a character matches. - /// - /// [`char`]: primitive.char.html - /// - /// # Text directionality - /// - /// A string is a sequence of bytes. 'Left' in this context means the first - /// position of that byte string; for a language like Arabic or Hebrew - /// which are 'right to left' rather than 'left to right', this will be - /// the _right_ side, not the left. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11"); - /// assert_eq!("123foo1bar123".trim_left_matches(char::is_numeric), "foo1bar123"); - /// - /// let x: &[_] = &['1', '2']; - /// assert_eq!("12foo1bar12".trim_left_matches(x), "foo1bar12"); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str { - core_str::StrExt::trim_left_matches(self, pat) - } - - /// Returns a string slice with all suffixes that match a pattern - /// repeatedly removed. - /// - /// The pattern can be a `&str`, [`char`], or a closure that - /// determines if a character matches. - /// - /// [`char`]: primitive.char.html - /// - /// # Text directionality - /// - /// A string is a sequence of bytes. 'Right' in this context means the last - /// position of that byte string; for a language like Arabic or Hebrew - /// which are 'right to left' rather than 'left to right', this will be - /// the _left_ side, not the right. - /// - /// # Examples - /// - /// Simple patterns: - /// - /// ``` - /// assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar"); - /// assert_eq!("123foo1bar123".trim_right_matches(char::is_numeric), "123foo1bar"); - /// - /// let x: &[_] = &['1', '2']; - /// assert_eq!("12foo1bar12".trim_right_matches(x), "12foo1bar"); - /// ``` - /// - /// A more complex pattern, using a closure: - /// - /// ``` - /// assert_eq!("1fooX".trim_right_matches(|c| c == '1' || c == 'X'), "1foo"); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str - where P::Searcher: ReverseSearcher<'a> - { - core_str::StrExt::trim_right_matches(self, pat) - } - - /// Parses this string slice into another type. - /// - /// Because `parse` is so general, it can cause problems with type - /// inference. As such, `parse` is one of the few times you'll see - /// the syntax affectionately known as the 'turbofish': `::<>`. This - /// helps the inference algorithm understand specifically which type - /// you're trying to parse into. - /// - /// `parse` can parse any type that implements the [`FromStr`] trait. - /// - /// [`FromStr`]: str/trait.FromStr.html - /// - /// # Errors - /// - /// Will return [`Err`] if it's not possible to parse this string slice into - /// the desired type. - /// - /// [`Err`]: str/trait.FromStr.html#associatedtype.Err - /// - /// # Examples - /// - /// Basic usage - /// - /// ``` - /// let four: u32 = "4".parse().unwrap(); - /// - /// assert_eq!(4, four); - /// ``` - /// - /// Using the 'turbofish' instead of annotating `four`: - /// - /// ``` - /// let four = "4".parse::<u32>(); - /// - /// assert_eq!(Ok(4), four); - /// ``` - /// - /// Failing to parse: - /// - /// ``` - /// let nope = "j".parse::<u32>(); - /// - /// assert!(nope.is_err()); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn parse<F: FromStr>(&self) -> Result<F, F::Err> { - core_str::StrExt::parse(self) - } + #[cfg(stage0)] + str_core_methods!(); /// Converts a `Box<str>` into a `Box<[u8]>` without copying or allocating. /// @@ -2085,121 +436,7 @@ impl str { /// ``` #[stable(feature = "repeat_str", since = "1.16.0")] pub fn repeat(&self, n: usize) -> String { - if n == 0 { - return String::new(); - } - - // If `n` is larger than zero, it can be split as - // `n = 2^expn + rem (2^expn > rem, expn >= 0, rem >= 0)`. - // `2^expn` is the number represented by the leftmost '1' bit of `n`, - // and `rem` is the remaining part of `n`. - - // Using `Vec` to access `set_len()`. - let mut buf = Vec::with_capacity(self.len() * n); - - // `2^expn` repetition is done by doubling `buf` `expn`-times. - buf.extend(self.as_bytes()); - { - let mut m = n >> 1; - // If `m > 0`, there are remaining bits up to the leftmost '1'. - while m > 0 { - // `buf.extend(buf)`: - unsafe { - ptr::copy_nonoverlapping( - buf.as_ptr(), - (buf.as_mut_ptr() as *mut u8).add(buf.len()), - buf.len(), - ); - // `buf` has capacity of `self.len() * n`. - let buf_len = buf.len(); - buf.set_len(buf_len * 2); - } - - m >>= 1; - } - } - - // `rem` (`= n - 2^expn`) repetition is done by copying - // first `rem` repetitions from `buf` itself. - let rem_len = self.len() * n - buf.len(); // `self.len() * rem` - if rem_len > 0 { - // `buf.extend(buf[0 .. rem_len])`: - unsafe { - // This is non-overlapping since `2^expn > rem`. - ptr::copy_nonoverlapping( - buf.as_ptr(), - (buf.as_mut_ptr() as *mut u8).add(buf.len()), - rem_len, - ); - // `buf.len() + rem_len` equals to `buf.capacity()` (`= self.len() * n`). - let buf_cap = buf.capacity(); - buf.set_len(buf_cap); - } - } - - unsafe { String::from_utf8_unchecked(buf) } - } - - /// Returns true if this `str` is entirely whitespace, and false otherwise. - /// - /// 'Whitespace' is defined according to the terms of the Unicode Derived Core - /// Property `White_Space`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// assert!(" \t ".is_whitespace()); - /// - /// // a non-breaking space - /// assert!("\u{A0}".is_whitespace()); - /// - /// assert!(!" 越".is_whitespace()); - /// ``` - #[stable(feature = "unicode_methods_on_intrinsics", since = "1.27.0")] - #[inline] - pub fn is_whitespace(&self) -> bool { - StrExt::is_whitespace(self) - } - - /// Returns true if this `str` is entirely alphanumeric, and false otherwise. - /// - /// 'Alphanumeric'-ness is defined in terms of the Unicode General Categories - /// 'Nd', 'Nl', 'No' and the Derived Core Property 'Alphabetic'. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// assert!("٣7৬Kو藏".is_alphanumeric()); - /// assert!(!"¾①".is_alphanumeric()); - /// ``` - #[stable(feature = "unicode_methods_on_intrinsics", since = "1.27.0")] - #[inline] - pub fn is_alphanumeric(&self) -> bool { - StrExt::is_alphanumeric(self) - } - - /// Checks if all characters in this string are within the ASCII range. - /// - /// # Examples - /// - /// ``` - /// let ascii = "hello!\n"; - /// let non_ascii = "Grüße, Jürgen ❤"; - /// - /// assert!(ascii.is_ascii()); - /// assert!(!non_ascii.is_ascii()); - /// ``` - #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[inline] - pub fn is_ascii(&self) -> bool { - // We can treat each byte as character here: all multibyte characters - // start with a byte that is not in the ascii range, so we will stop - // there already. - self.bytes().all(|b| b.is_ascii()) + unsafe { String::from_utf8_unchecked(self.as_bytes().repeat(n)) } } /// Returns a copy of this string where each character is mapped to its @@ -2261,54 +498,6 @@ impl str { // make_ascii_lowercase() preserves the UTF-8 invariant. unsafe { String::from_utf8_unchecked(bytes) } } - - /// Checks that two strings are an ASCII case-insensitive match. - /// - /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`, - /// but without allocating and copying temporaries. - /// - /// # Examples - /// - /// ``` - /// assert!("Ferris".eq_ignore_ascii_case("FERRIS")); - /// assert!("Ferrös".eq_ignore_ascii_case("FERRöS")); - /// assert!(!"Ferrös".eq_ignore_ascii_case("FERRÖS")); - /// ``` - #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[inline] - pub fn eq_ignore_ascii_case(&self, other: &str) -> bool { - self.as_bytes().eq_ignore_ascii_case(other.as_bytes()) - } - - /// Converts this string to its ASCII upper case equivalent in-place. - /// - /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', - /// but non-ASCII letters are unchanged. - /// - /// To return a new uppercased value without modifying the existing one, use - /// [`to_ascii_uppercase`]. - /// - /// [`to_ascii_uppercase`]: #method.to_ascii_uppercase - #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - pub fn make_ascii_uppercase(&mut self) { - let me = unsafe { self.as_bytes_mut() }; - me.make_ascii_uppercase() - } - - /// Converts this string to its ASCII lower case equivalent in-place. - /// - /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', - /// but non-ASCII letters are unchanged. - /// - /// To return a new lowercased value without modifying the existing one, use - /// [`to_ascii_lowercase`]. - /// - /// [`to_ascii_lowercase`]: #method.to_ascii_lowercase - #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - pub fn make_ascii_lowercase(&mut self) { - let me = unsafe { self.as_bytes_mut() }; - me.make_ascii_lowercase() - } } /// Converts a boxed slice of bytes to a boxed string slice without checking diff --git a/src/liballoc/tests/str.rs b/src/liballoc/tests/str.rs index a3f4c385fe2..a03b61ec97e 100644 --- a/src/liballoc/tests/str.rs +++ b/src/liballoc/tests/str.rs @@ -402,6 +402,36 @@ fn test_str_get_maxinclusive() { } #[test] +fn test_str_slice_rangetoinclusive_ok() { + let s = "abcαβγ"; + assert_eq!(&s[..=2], "abc"); + assert_eq!(&s[..=4], "abcα"); +} + +#[test] +#[should_panic] +fn test_str_slice_rangetoinclusive_notok() { + let s = "abcαβγ"; + &s[..=3]; +} + +#[test] +fn test_str_slicemut_rangetoinclusive_ok() { + let mut s = "abcαβγ".to_owned(); + let s: &mut str = &mut s; + assert_eq!(&mut s[..=2], "abc"); + assert_eq!(&mut s[..=4], "abcα"); +} + +#[test] +#[should_panic] +fn test_str_slicemut_rangetoinclusive_notok() { + let mut s = "abcαβγ".to_owned(); + let s: &mut str = &mut s; + &mut s[..=3]; +} + +#[test] fn test_is_char_boundary() { let s = "ศไทย中华Việt Nam β-release 🐱123"; assert!(s.is_char_boundary(0)); diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 7d1b2ed85c7..b184404c15b 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -74,6 +74,7 @@ use core::iter::{FromIterator, FusedIterator, TrustedLen}; use core::marker::PhantomData; use core::mem; #[cfg(not(test))] +#[cfg(stage0)] use core::num::Float; use core::ops::Bound::{Excluded, Included, Unbounded}; use core::ops::{Index, IndexMut, RangeBounds}; diff --git a/src/liballoc_jemalloc/Cargo.toml b/src/liballoc_jemalloc/Cargo.toml index 02435170374..7986d5dd2eb 100644 --- a/src/liballoc_jemalloc/Cargo.toml +++ b/src/liballoc_jemalloc/Cargo.toml @@ -12,7 +12,6 @@ test = false doc = false [dependencies] -alloc_system = { path = "../liballoc_system" } core = { path = "../libcore" } libc = { path = "../rustc/libc_shim" } compiler_builtins = { path = "../rustc/compiler_builtins_shim" } diff --git a/src/liballoc_jemalloc/lib.rs b/src/liballoc_jemalloc/lib.rs index 2b66c293f21..4b8755877de 100644 --- a/src/liballoc_jemalloc/lib.rs +++ b/src/liballoc_jemalloc/lib.rs @@ -14,7 +14,7 @@ reason = "this library is unlikely to be stabilized in its current \ form or name", issue = "27783")] -#![feature(alloc_system)] +#![feature(core_intrinsics)] #![feature(libc)] #![feature(linkage)] #![feature(staged_api)] @@ -23,15 +23,12 @@ #![cfg_attr(not(dummy_jemalloc), feature(allocator_api))] #![rustc_alloc_kind = "exe"] -extern crate alloc_system; extern crate libc; #[cfg(not(dummy_jemalloc))] pub use contents::*; #[cfg(not(dummy_jemalloc))] mod contents { - use core::alloc::GlobalAlloc; - use alloc_system::System; use libc::{c_int, c_void, size_t}; // Note that the symbols here are prefixed by default on macOS and Windows (we @@ -100,10 +97,11 @@ mod contents { ptr } + #[cfg(stage0)] #[no_mangle] #[rustc_std_internal_symbol] pub unsafe extern fn __rde_oom() -> ! { - System.oom() + ::core::intrinsics::abort(); } #[no_mangle] diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs index fd8109e2a4a..7376ac0f15d 100644 --- a/src/liballoc_system/lib.rs +++ b/src/liballoc_system/lib.rs @@ -71,11 +71,6 @@ unsafe impl Alloc for System { new_size: usize) -> Result<NonNull<Opaque>, AllocErr> { NonNull::new(GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size)).ok_or(AllocErr) } - - #[inline] - fn oom(&mut self) -> ! { - ::oom() - } } #[cfg(stage0)] @@ -103,11 +98,6 @@ unsafe impl<'a> Alloc for &'a System { new_size: usize) -> Result<NonNull<Opaque>, AllocErr> { NonNull::new(GlobalAlloc::realloc(*self, ptr.as_ptr(), layout, new_size)).ok_or(AllocErr) } - - #[inline] - fn oom(&mut self) -> ! { - ::oom() - } } #[cfg(any(windows, unix, target_os = "cloudabi", target_os = "redox"))] @@ -366,63 +356,3 @@ mod platform { } } } - -#[inline] -fn oom() -> ! { - write_to_stderr("fatal runtime error: memory allocation failed"); - unsafe { - ::core::intrinsics::abort(); - } -} - -#[cfg(any(unix, target_os = "redox"))] -#[inline] -fn write_to_stderr(s: &str) { - extern crate libc; - - unsafe { - libc::write(libc::STDERR_FILENO, - s.as_ptr() as *const libc::c_void, - s.len()); - } -} - -#[cfg(windows)] -#[inline] -fn write_to_stderr(s: &str) { - use core::ptr; - - type LPVOID = *mut u8; - type HANDLE = LPVOID; - type DWORD = u32; - type BOOL = i32; - type LPDWORD = *mut DWORD; - type LPOVERLAPPED = *mut u8; - - const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD; - - extern "system" { - fn WriteFile(hFile: HANDLE, - lpBuffer: LPVOID, - nNumberOfBytesToWrite: DWORD, - lpNumberOfBytesWritten: LPDWORD, - lpOverlapped: LPOVERLAPPED) - -> BOOL; - fn GetStdHandle(which: DWORD) -> HANDLE; - } - - unsafe { - // WriteFile silently fails if it is passed an invalid - // handle, so there is no need to check the result of - // GetStdHandle. - WriteFile(GetStdHandle(STD_ERROR_HANDLE), - s.as_ptr() as LPVOID, - s.len() as DWORD, - ptr::null_mut(), - ptr::null_mut()); - } -} - -#[cfg(not(any(windows, unix, target_os = "redox")))] -#[inline] -fn write_to_stderr(_: &str) {} diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs index f08baa3dd71..674c4fb57c7 100644 --- a/src/libcore/alloc.rs +++ b/src/libcore/alloc.rs @@ -63,7 +63,7 @@ fn size_align<T>() -> (usize, usize) { /// requests have positive size. A caller to the `Alloc::alloc` /// method must either ensure that conditions like this are met, or /// use specific allocators with looser requirements.) -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct Layout { // size of the requested block of memory, measured in bytes. size: usize, @@ -451,17 +451,6 @@ pub unsafe trait GlobalAlloc { } new_ptr } - - /// Aborts the thread or process, optionally performing - /// cleanup or logging diagnostic information before panicking or - /// aborting. - /// - /// `oom` is meant to be used by clients unable to cope with an - /// unsatisfied allocation request, and wish to abandon - /// computation rather than attempt to recover locally. - fn oom(&self) -> ! { - unsafe { ::intrinsics::abort() } - } } /// An implementation of `Alloc` can allocate, reallocate, and @@ -614,32 +603,6 @@ pub unsafe trait Alloc { /// to allocate that block of memory. unsafe fn dealloc(&mut self, ptr: NonNull<Opaque>, layout: Layout); - /// Allocator-specific method for signaling an out-of-memory - /// condition. - /// - /// `oom` aborts the thread or process, optionally performing - /// cleanup or logging diagnostic information before panicking or - /// aborting. - /// - /// `oom` is meant to be used by clients unable to cope with an - /// unsatisfied allocation request, and wish to abandon - /// computation rather than attempt to recover locally. - /// - /// Implementations of the `oom` method are discouraged from - /// infinitely regressing in nested calls to `oom`. In - /// practice this means implementors should eschew allocating, - /// especially from `self` (directly or indirectly). - /// - /// Implementations of the allocation and reallocation methods - /// (e.g. `alloc`, `alloc_one`, `realloc`) are discouraged from - /// panicking (or aborting) in the event of memory exhaustion; - /// instead they should return an appropriate error from the - /// invoked method, and let the client decide whether to invoke - /// this `oom` method in response. - fn oom(&mut self) -> ! { - unsafe { ::intrinsics::abort() } - } - // == ALLOCATOR-SPECIFIC QUANTITIES AND LIMITS == // usable_size diff --git a/src/libcore/array.rs b/src/libcore/array.rs index 87144c27c9e..3d24f8902bd 100644 --- a/src/libcore/array.rs +++ b/src/libcore/array.rs @@ -59,7 +59,7 @@ unsafe impl<T, A: Unsize<[T]>> FixedSizeArray<T> for A { } /// The error type returned when a conversion from a slice to an array fails. -#[stable(feature = "try_from", since = "1.26.0")] +#[unstable(feature = "try_from", issue = "33417")] #[derive(Debug, Copy, Clone)] pub struct TryFromSliceError(()); @@ -148,7 +148,7 @@ macro_rules! array_impls { } } - #[stable(feature = "try_from", since = "1.26.0")] + #[unstable(feature = "try_from", issue = "33417")] impl<'a, T> TryFrom<&'a [T]> for &'a [T; $N] { type Error = TryFromSliceError; @@ -162,7 +162,7 @@ macro_rules! array_impls { } } - #[stable(feature = "try_from", since = "1.26.0")] + #[unstable(feature = "try_from", issue = "33417")] impl<'a, T> TryFrom<&'a mut [T]> for &'a mut [T; $N] { type Error = TryFromSliceError; diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index c8ee166fee3..1ff187ed3f1 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -256,6 +256,33 @@ impl<T:Copy> Cell<T> { pub fn get(&self) -> T { unsafe{ *self.value.get() } } + + /// Updates the contained value using a function and returns the new value. + /// + /// # Examples + /// + /// ``` + /// #![feature(cell_update)] + /// + /// use std::cell::Cell; + /// + /// let c = Cell::new(5); + /// let new = c.update(|x| x + 1); + /// + /// assert_eq!(new, 6); + /// assert_eq!(c.get(), 6); + /// ``` + #[inline] + #[unstable(feature = "cell_update", issue = "50186")] + pub fn update<F>(&self, f: F) -> T + where + F: FnOnce(T) -> T, + { + let old = self.get(); + let new = f(old); + self.set(new); + new + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/char/convert.rs b/src/libcore/char/convert.rs index 150562a4a9b..803a924eb3a 100644 --- a/src/libcore/char/convert.rs +++ b/src/libcore/char/convert.rs @@ -204,7 +204,7 @@ impl FromStr for char { } -#[stable(feature = "try_from", since = "1.26.0")] +#[unstable(feature = "try_from", issue = "33417")] impl TryFrom<u32> for char { type Error = CharTryFromError; @@ -219,11 +219,11 @@ impl TryFrom<u32> for char { } /// The error type returned when a conversion from u32 to char fails. -#[stable(feature = "try_from", since = "1.26.0")] +#[unstable(feature = "try_from", issue = "33417")] #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct CharTryFromError(()); -#[stable(feature = "try_from", since = "1.26.0")] +#[unstable(feature = "try_from", issue = "33417")] impl fmt::Display for CharTryFromError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { "converted integer out of range for `char`".fmt(f) diff --git a/src/libcore/char/decode.rs b/src/libcore/char/decode.rs index 48b531104f8..45a73191db2 100644 --- a/src/libcore/char/decode.rs +++ b/src/libcore/char/decode.rs @@ -17,11 +17,17 @@ use super::from_u32_unchecked; /// An iterator over an iterator of bytes of the characters the bytes represent /// as UTF-8 #[unstable(feature = "decode_utf8", issue = "33906")] +#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead: + https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")] #[derive(Clone, Debug)] +#[allow(deprecated)] pub struct DecodeUtf8<I: Iterator<Item = u8>>(::iter::Peekable<I>); /// Decodes an `Iterator` of bytes as UTF-8. #[unstable(feature = "decode_utf8", issue = "33906")] +#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead: + https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")] +#[allow(deprecated)] #[inline] pub fn decode_utf8<I: IntoIterator<Item = u8>>(i: I) -> DecodeUtf8<I::IntoIter> { DecodeUtf8(i.into_iter().peekable()) @@ -29,10 +35,14 @@ pub fn decode_utf8<I: IntoIterator<Item = u8>>(i: I) -> DecodeUtf8<I::IntoIter> /// `<DecodeUtf8 as Iterator>::next` returns this for an invalid input sequence. #[unstable(feature = "decode_utf8", issue = "33906")] +#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead: + https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")] #[derive(PartialEq, Eq, Debug)] +#[allow(deprecated)] pub struct InvalidSequence(()); #[unstable(feature = "decode_utf8", issue = "33906")] +#[allow(deprecated)] impl<I: Iterator<Item = u8>> Iterator for DecodeUtf8<I> { type Item = Result<char, InvalidSequence>; #[inline] @@ -127,6 +137,7 @@ impl<I: Iterator<Item = u8>> Iterator for DecodeUtf8<I> { } #[unstable(feature = "decode_utf8", issue = "33906")] +#[allow(deprecated)] impl<I: FusedIterator<Item = u8>> FusedIterator for DecodeUtf8<I> {} /// An iterator that decodes UTF-16 encoded code points from an iterator of `u16`s. diff --git a/src/libcore/char/mod.rs b/src/libcore/char/mod.rs index 9edc0c88756..4f6c302247d 100644 --- a/src/libcore/char/mod.rs +++ b/src/libcore/char/mod.rs @@ -40,7 +40,7 @@ pub use self::convert::{from_u32, from_digit}; pub use self::convert::from_u32_unchecked; #[stable(feature = "char_from_str", since = "1.20.0")] pub use self::convert::ParseCharError; -#[stable(feature = "try_from", since = "1.26.0")] +#[unstable(feature = "try_from", issue = "33417")] pub use self::convert::CharTryFromError; #[stable(feature = "decode_utf16", since = "1.9.0")] pub use self::decode::{decode_utf16, DecodeUtf16, DecodeUtf16Error}; @@ -51,6 +51,9 @@ pub use unicode::tables::UNICODE_VERSION; #[unstable(feature = "unicode_version", issue = "49726")] pub use unicode::version::UnicodeVersion; #[unstable(feature = "decode_utf8", issue = "33906")] +#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead: + https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")] +#[allow(deprecated)] pub use self::decode::{decode_utf8, DecodeUtf8, InvalidSequence}; use fmt::{self, Write}; diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index 58a8439162c..f79f7351698 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -179,7 +179,7 @@ mod impls { bool char } - #[stable(feature = "never_type", since = "1.26.0")] + #[unstable(feature = "never_type", issue = "35121")] impl Clone for ! { #[inline] fn clone(&self) -> Self { diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 3ae9b05b865..c91aa06609d 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -881,24 +881,24 @@ mod impls { ord_impl! { char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } - #[stable(feature = "never_type", since = "1.26.0")] + #[unstable(feature = "never_type", issue = "35121")] impl PartialEq for ! { fn eq(&self, _: &!) -> bool { *self } } - #[stable(feature = "never_type", since = "1.26.0")] + #[unstable(feature = "never_type", issue = "35121")] impl Eq for ! {} - #[stable(feature = "never_type", since = "1.26.0")] + #[unstable(feature = "never_type", issue = "35121")] impl PartialOrd for ! { fn partial_cmp(&self, _: &!) -> Option<Ordering> { *self } } - #[stable(feature = "never_type", since = "1.26.0")] + #[unstable(feature = "never_type", issue = "35121")] impl Ord for ! { fn cmp(&self, _: &!) -> Ordering { *self diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index 63721395784..7324df95bc5 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -322,26 +322,22 @@ pub trait From<T>: Sized { /// /// [`TryFrom`]: trait.TryFrom.html /// [`Into`]: trait.Into.html -#[stable(feature = "try_from", since = "1.26.0")] +#[unstable(feature = "try_from", issue = "33417")] pub trait TryInto<T>: Sized { /// The type returned in the event of a conversion error. - #[stable(feature = "try_from", since = "1.26.0")] type Error; /// Performs the conversion. - #[stable(feature = "try_from", since = "1.26.0")] fn try_into(self) -> Result<T, Self::Error>; } /// Attempt to construct `Self` via a conversion. -#[stable(feature = "try_from", since = "1.26.0")] +#[unstable(feature = "try_from", issue = "33417")] pub trait TryFrom<T>: Sized { /// The type returned in the event of a conversion error. - #[stable(feature = "try_from", since = "1.26.0")] type Error; /// Performs the conversion. - #[stable(feature = "try_from", since = "1.26.0")] fn try_from(value: T) -> Result<Self, Self::Error>; } @@ -409,7 +405,7 @@ impl<T> From<T> for T { // TryFrom implies TryInto -#[stable(feature = "try_from", since = "1.26.0")] +#[unstable(feature = "try_from", issue = "33417")] impl<T, U> TryInto<U> for T where U: TryFrom<T> { type Error = U::Error; @@ -421,7 +417,7 @@ impl<T, U> TryInto<U> for T where U: TryFrom<T> // Infallible conversions are semantically equivalent to fallible conversions // with an uninhabited error type. -#[stable(feature = "try_from", since = "1.26.0")] +#[unstable(feature = "try_from", issue = "33417")] impl<T, U> TryFrom<U> for T where T: From<U> { type Error = !; diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 277bef2bf66..a8430f14410 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -1780,14 +1780,14 @@ macro_rules! fmt_refs { fmt_refs! { Debug, Display, Octal, Binary, LowerHex, UpperHex, LowerExp, UpperExp } -#[stable(feature = "never_type", since = "1.26.0")] +#[unstable(feature = "never_type", issue = "35121")] impl Debug for ! { fn fmt(&self, _: &mut Formatter) -> Result { *self } } -#[stable(feature = "never_type", since = "1.26.0")] +#[unstable(feature = "never_type", issue = "35121")] impl Display for ! { fn fmt(&self, _: &mut Formatter) -> Result { *self diff --git a/src/libcore/hint.rs b/src/libcore/hint.rs new file mode 100644 index 00000000000..f4e96e67b2c --- /dev/null +++ b/src/libcore/hint.rs @@ -0,0 +1,61 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![stable(feature = "core_hint", since = "1.27.0")] + +//! Hints to compiler that affects how code should be emitted or optimized. + +use intrinsics; + +/// Informs the compiler that this point in the code is not reachable, enabling +/// further optimizations. +/// +/// # Safety +/// +/// Reaching this function is completely *undefined behavior* (UB). In +/// particular, the compiler assumes that all UB must never happen, and +/// therefore will eliminate all branches that reach to a call to +/// `unreachable_unchecked()`. +/// +/// Like all instances of UB, if this assumption turns out to be wrong, i.e. the +/// `unreachable_unchecked()` call is actually reachable among all possible +/// control flow, the compiler will apply the wrong optimization strategy, and +/// may sometimes even corrupt seemingly unrelated code, causing +/// difficult-to-debug problems. +/// +/// Use this function only when you can prove that the code will never call it. +/// +/// The [`unreachable!()`] macro is the safe counterpart of this function, which +/// will panic instead when executed. +/// +/// [`unreachable!()`]: ../macro.unreachable.html +/// +/// # Example +/// +/// ``` +/// fn div_1(a: u32, b: u32) -> u32 { +/// use std::hint::unreachable_unchecked; +/// +/// // `b.saturating_add(1)` is always positive (not zero), +/// // hence `checked_div` will never return None. +/// // Therefore, the else branch is unreachable. +/// a.checked_div(b.saturating_add(1)) +/// .unwrap_or_else(|| unsafe { unreachable_unchecked() }) +/// } +/// +/// assert_eq!(div_1(7, 0), 7); +/// assert_eq!(div_1(9, 1), 4); +/// assert_eq!(div_1(11, std::u32::MAX), 0); +/// ``` +#[inline] +#[stable(feature = "unreachable", since = "1.27.0")] +pub unsafe fn unreachable_unchecked() -> ! { + intrinsics::unreachable() +} diff --git a/src/libcore/internal_macros.rs b/src/libcore/internal_macros.rs index cb215a38e53..58eef649287 100644 --- a/src/libcore/internal_macros.rs +++ b/src/libcore/internal_macros.rs @@ -87,3 +87,16 @@ macro_rules! forward_ref_op_assign { } } +#[cfg(stage0)] +macro_rules! public_in_stage0 { + ( { $(#[$attr:meta])* } $($Item: tt)*) => { + $(#[$attr])* pub $($Item)* + } +} + +#[cfg(not(stage0))] +macro_rules! public_in_stage0 { + ( { $(#[$attr:meta])* } $($Item: tt)*) => { + $(#[$attr])* pub(crate) $($Item)* + } +} diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 83274682250..fb0d2d9c882 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -638,6 +638,9 @@ extern "rust-intrinsic" { /// NB: This is very different from the `unreachable!()` macro: Unlike the /// macro, which panics when it is executed, it is *undefined behavior* to /// reach code marked with this function. + /// + /// The stabilized version of this intrinsic is + /// [`std::hint::unreachable_unchecked`](../../std/hint/fn.unreachable_unchecked.html). pub fn unreachable() -> !; /// Informs the optimizer that a condition is always true. diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index ea7a46f44ae..0e21a3327fd 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -71,6 +71,7 @@ #![feature(cfg_target_has_atomic)] #![feature(concat_idents)] #![feature(const_fn)] +#![feature(core_float)] #![feature(custom_attribute)] #![feature(doc_cfg)] #![feature(doc_spotlight)] @@ -82,6 +83,7 @@ #![feature(iterator_repeat_with)] #![feature(lang_items)] #![feature(link_llvm_intrinsics)] +#![feature(never_type)] #![feature(exhaustive_patterns)] #![feature(macro_at_most_once_rep)] #![feature(no_core)] @@ -92,12 +94,15 @@ #![feature(rustc_attrs)] #![feature(rustc_const_unstable)] #![feature(simd_ffi)] +#![feature(core_slice_ext)] +#![feature(core_str_ext)] #![feature(specialization)] #![feature(staged_api)] #![feature(stmt_expr_attributes)] #![feature(unboxed_closures)] #![feature(untagged_unions)] #![feature(unwind_attributes)] +#![feature(doc_alias)] #![cfg_attr(not(stage0), feature(mmx_target_feature))] #![cfg_attr(not(stage0), feature(tbm_target_feature))] @@ -158,6 +163,7 @@ pub mod intrinsics; pub mod mem; pub mod nonzero; pub mod ptr; +pub mod hint; /* Core language traits */ @@ -228,7 +234,7 @@ macro_rules! test_v512 { ($item:item) => {}; } #[allow(unused_macros)] macro_rules! vector_impl { ($([$f:ident, $($args:tt)*]),*) => { $($f!($($args)*);)* } } #[path = "../stdsimd/coresimd/mod.rs"] -#[allow(missing_docs, missing_debug_implementations, dead_code)] +#[allow(missing_docs, missing_debug_implementations, dead_code, unused_imports)] #[unstable(feature = "stdsimd", issue = "48556")] #[cfg(not(stage0))] // allow changes to how stdsimd works in stage0 mod coresimd; diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 90a9cb3379b..f9371ed0575 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -295,6 +295,7 @@ macro_rules! debug_assert_ne { /// ``` #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] +#[doc(alias = "?")] macro_rules! try { ($expr:expr) => (match $expr { $crate::result::Result::Ok(val) => val, @@ -420,13 +421,13 @@ macro_rules! writeln { /// * Iterators that dynamically terminate. /// /// If the determination that the code is unreachable proves incorrect, the -/// program immediately terminates with a [`panic!`]. The function [`unreachable`], -/// which belongs to the [`std::intrinsics`] module, informs the compilier to +/// program immediately terminates with a [`panic!`]. The function [`unreachable_unchecked`], +/// which belongs to the [`std::hint`] module, informs the compilier to /// optimize the code out of the release version entirely. /// /// [`panic!`]: ../std/macro.panic.html -/// [`unreachable`]: ../std/intrinsics/fn.unreachable.html -/// [`std::intrinsics`]: ../std/intrinsics/index.html +/// [`unreachable_unchecked`]: ../std/hint/fn.unreachable_unchecked.html +/// [`std::hint`]: ../std/hint/index.html /// /// # Panics /// diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 885aabe0806..feb689dbc1f 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -630,7 +630,7 @@ mod copy_impls { bool char } - #[stable(feature = "never_type", since = "1.26.0")] + #[unstable(feature = "never_type", issue = "35121")] impl Copy for ! {} #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index e3f08926610..10efab82ddf 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -1094,18 +1094,6 @@ impl<T: ::hash::Hash> ::hash::Hash for ManuallyDrop<T> { } } -/// Tells LLVM that this point in the code is not reachable, enabling further -/// optimizations. -/// -/// NB: This is very different from the `unreachable!()` macro: Unlike the -/// macro, which panics when it is executed, it is *undefined behavior* to -/// reach code marked with this function. -#[inline] -#[unstable(feature = "unreachable", issue = "43751")] -pub unsafe fn unreachable() -> ! { - intrinsics::unreachable() -} - /// A pinned reference. /// /// A pinned reference is a lot like a mutable reference, except that it is not diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 3586fa5442f..8d5f6f601da 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -17,9 +17,9 @@ #![stable(feature = "rust1", since = "1.0.0")] -use intrinsics; use mem; use num::Float; +#[cfg(not(stage0))] use num::FpCategory; use num::FpCategory as Fp; /// The radix or base of the internal representation of `f32`. @@ -188,27 +188,6 @@ impl Float for f32 { } } - /// Computes the absolute value of `self`. Returns `Float::nan()` if the - /// number is `Float::nan()`. - #[inline] - fn abs(self) -> f32 { - unsafe { intrinsics::fabsf32(self) } - } - - /// Returns a number that represents the sign of `self`. - /// - /// - `1.0` if the number is positive, `+0.0` or `Float::infinity()` - /// - `-1.0` if the number is negative, `-0.0` or `Float::neg_infinity()` - /// - `Float::nan()` if the number is `Float::nan()` - #[inline] - fn signum(self) -> f32 { - if self.is_nan() { - NAN - } else { - unsafe { intrinsics::copysignf32(1.0, self) } - } - } - /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with /// positive sign bit and positive infinity. #[inline] @@ -231,11 +210,6 @@ impl Float for f32 { 1.0 / self } - #[inline] - fn powi(self, n: i32) -> f32 { - unsafe { intrinsics::powif32(self, n) } - } - /// Converts to degrees, assuming the number is in radians. #[inline] fn to_degrees(self) -> f32 { @@ -292,3 +266,286 @@ impl Float for f32 { unsafe { mem::transmute(v) } } } + +// FIXME: remove (inline) this macro and the Float trait +// when updating to a bootstrap compiler that has the new lang items. +#[cfg_attr(stage0, macro_export)] +#[unstable(feature = "core_float", issue = "32110")] +macro_rules! f32_core_methods { () => { + /// Returns `true` if this value is `NaN` and false otherwise. + /// + /// ``` + /// use std::f32; + /// + /// let nan = f32::NAN; + /// let f = 7.0_f32; + /// + /// assert!(nan.is_nan()); + /// assert!(!f.is_nan()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_nan(self) -> bool { Float::is_nan(self) } + + /// Returns `true` if this value is positive infinity or negative infinity and + /// false otherwise. + /// + /// ``` + /// use std::f32; + /// + /// let f = 7.0f32; + /// let inf = f32::INFINITY; + /// let neg_inf = f32::NEG_INFINITY; + /// let nan = f32::NAN; + /// + /// assert!(!f.is_infinite()); + /// assert!(!nan.is_infinite()); + /// + /// assert!(inf.is_infinite()); + /// assert!(neg_inf.is_infinite()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_infinite(self) -> bool { Float::is_infinite(self) } + + /// Returns `true` if this number is neither infinite nor `NaN`. + /// + /// ``` + /// use std::f32; + /// + /// let f = 7.0f32; + /// let inf = f32::INFINITY; + /// let neg_inf = f32::NEG_INFINITY; + /// let nan = f32::NAN; + /// + /// assert!(f.is_finite()); + /// + /// assert!(!nan.is_finite()); + /// assert!(!inf.is_finite()); + /// assert!(!neg_inf.is_finite()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_finite(self) -> bool { Float::is_finite(self) } + + /// Returns `true` if the number is neither zero, infinite, + /// [subnormal][subnormal], or `NaN`. + /// + /// ``` + /// use std::f32; + /// + /// let min = f32::MIN_POSITIVE; // 1.17549435e-38f32 + /// let max = f32::MAX; + /// let lower_than_min = 1.0e-40_f32; + /// let zero = 0.0_f32; + /// + /// assert!(min.is_normal()); + /// assert!(max.is_normal()); + /// + /// assert!(!zero.is_normal()); + /// assert!(!f32::NAN.is_normal()); + /// assert!(!f32::INFINITY.is_normal()); + /// // Values between `0` and `min` are Subnormal. + /// assert!(!lower_than_min.is_normal()); + /// ``` + /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_normal(self) -> bool { Float::is_normal(self) } + + /// Returns the floating point category of the number. If only one property + /// is going to be tested, it is generally faster to use the specific + /// predicate instead. + /// + /// ``` + /// use std::num::FpCategory; + /// use std::f32; + /// + /// let num = 12.4_f32; + /// let inf = f32::INFINITY; + /// + /// assert_eq!(num.classify(), FpCategory::Normal); + /// assert_eq!(inf.classify(), FpCategory::Infinite); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn classify(self) -> FpCategory { Float::classify(self) } + + /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with + /// positive sign bit and positive infinity. + /// + /// ``` + /// let f = 7.0_f32; + /// let g = -7.0_f32; + /// + /// assert!(f.is_sign_positive()); + /// assert!(!g.is_sign_positive()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_sign_positive(self) -> bool { Float::is_sign_positive(self) } + + /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with + /// negative sign bit and negative infinity. + /// + /// ``` + /// let f = 7.0f32; + /// let g = -7.0f32; + /// + /// assert!(!f.is_sign_negative()); + /// assert!(g.is_sign_negative()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_sign_negative(self) -> bool { Float::is_sign_negative(self) } + + /// Takes the reciprocal (inverse) of a number, `1/x`. + /// + /// ``` + /// use std::f32; + /// + /// let x = 2.0_f32; + /// let abs_difference = (x.recip() - (1.0/x)).abs(); + /// + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn recip(self) -> f32 { Float::recip(self) } + + /// Converts radians to degrees. + /// + /// ``` + /// use std::f32::{self, consts}; + /// + /// let angle = consts::PI; + /// + /// let abs_difference = (angle.to_degrees() - 180.0).abs(); + /// + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + #[stable(feature = "f32_deg_rad_conversions", since="1.7.0")] + #[inline] + pub fn to_degrees(self) -> f32 { Float::to_degrees(self) } + + /// Converts degrees to radians. + /// + /// ``` + /// use std::f32::{self, consts}; + /// + /// let angle = 180.0f32; + /// + /// let abs_difference = (angle.to_radians() - consts::PI).abs(); + /// + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + #[stable(feature = "f32_deg_rad_conversions", since="1.7.0")] + #[inline] + pub fn to_radians(self) -> f32 { Float::to_radians(self) } + + /// Returns the maximum of the two numbers. + /// + /// ``` + /// let x = 1.0f32; + /// let y = 2.0f32; + /// + /// assert_eq!(x.max(y), y); + /// ``` + /// + /// If one of the arguments is NaN, then the other argument is returned. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn max(self, other: f32) -> f32 { + Float::max(self, other) + } + + /// Returns the minimum of the two numbers. + /// + /// ``` + /// let x = 1.0f32; + /// let y = 2.0f32; + /// + /// assert_eq!(x.min(y), x); + /// ``` + /// + /// If one of the arguments is NaN, then the other argument is returned. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn min(self, other: f32) -> f32 { + Float::min(self, other) + } + + /// Raw transmutation to `u32`. + /// + /// This is currently identical to `transmute::<f32, u32>(self)` on all platforms. + /// + /// See `from_bits` for some discussion of the portability of this operation + /// (there are almost no issues). + /// + /// Note that this function is distinct from `as` casting, which attempts to + /// preserve the *numeric* value, and not the bitwise value. + /// + /// # Examples + /// + /// ``` + /// assert_ne!((1f32).to_bits(), 1f32 as u32); // to_bits() is not casting! + /// assert_eq!((12.5f32).to_bits(), 0x41480000); + /// + /// ``` + #[stable(feature = "float_bits_conv", since = "1.20.0")] + #[inline] + pub fn to_bits(self) -> u32 { + Float::to_bits(self) + } + + /// Raw transmutation from `u32`. + /// + /// This is currently identical to `transmute::<u32, f32>(v)` on all platforms. + /// It turns out this is incredibly portable, for two reasons: + /// + /// * Floats and Ints have the same endianness on all supported platforms. + /// * IEEE-754 very precisely specifies the bit layout of floats. + /// + /// However there is one caveat: prior to the 2008 version of IEEE-754, how + /// to interpret the NaN signaling bit wasn't actually specified. Most platforms + /// (notably x86 and ARM) picked the interpretation that was ultimately + /// standardized in 2008, but some didn't (notably MIPS). As a result, all + /// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa. + /// + /// Rather than trying to preserve signaling-ness cross-platform, this + /// implementation favours preserving the exact bits. This means that + /// any payloads encoded in NaNs will be preserved even if the result of + /// this method is sent over the network from an x86 machine to a MIPS one. + /// + /// If the results of this method are only manipulated by the same + /// architecture that produced them, then there is no portability concern. + /// + /// If the input isn't NaN, then there is no portability concern. + /// + /// If you don't care about signalingness (very likely), then there is no + /// portability concern. + /// + /// Note that this function is distinct from `as` casting, which attempts to + /// preserve the *numeric* value, and not the bitwise value. + /// + /// # Examples + /// + /// ``` + /// use std::f32; + /// let v = f32::from_bits(0x41480000); + /// let difference = (v - 12.5).abs(); + /// assert!(difference <= 1e-5); + /// ``` + #[stable(feature = "float_bits_conv", since = "1.20.0")] + #[inline] + pub fn from_bits(v: u32) -> Self { + Float::from_bits(v) + } +}} + +#[lang = "f32"] +#[cfg(not(test))] +#[cfg(not(stage0))] +impl f32 { + f32_core_methods!(); +} diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 64c0d508b38..08b869734d4 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -17,10 +17,10 @@ #![stable(feature = "rust1", since = "1.0.0")] -use intrinsics; use mem; -use num::FpCategory as Fp; use num::Float; +#[cfg(not(stage0))] use num::FpCategory; +use num::FpCategory as Fp; /// The radix or base of the internal representation of `f64`. #[stable(feature = "rust1", since = "1.0.0")] @@ -188,27 +188,6 @@ impl Float for f64 { } } - /// Computes the absolute value of `self`. Returns `Float::nan()` if the - /// number is `Float::nan()`. - #[inline] - fn abs(self) -> f64 { - unsafe { intrinsics::fabsf64(self) } - } - - /// Returns a number that represents the sign of `self`. - /// - /// - `1.0` if the number is positive, `+0.0` or `Float::infinity()` - /// - `-1.0` if the number is negative, `-0.0` or `Float::neg_infinity()` - /// - `Float::nan()` if the number is `Float::nan()` - #[inline] - fn signum(self) -> f64 { - if self.is_nan() { - NAN - } else { - unsafe { intrinsics::copysignf64(1.0, self) } - } - } - /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with /// positive sign bit and positive infinity. #[inline] @@ -229,11 +208,6 @@ impl Float for f64 { 1.0 / self } - #[inline] - fn powi(self, n: i32) -> f64 { - unsafe { intrinsics::powif64(self, n) } - } - /// Converts to degrees, assuming the number is in radians. #[inline] fn to_degrees(self) -> f64 { @@ -291,3 +265,296 @@ impl Float for f64 { unsafe { mem::transmute(v) } } } + +// FIXME: remove (inline) this macro and the Float trait +// when updating to a bootstrap compiler that has the new lang items. +#[cfg_attr(stage0, macro_export)] +#[unstable(feature = "core_float", issue = "32110")] +macro_rules! f64_core_methods { () => { + /// Returns `true` if this value is `NaN` and false otherwise. + /// + /// ``` + /// use std::f64; + /// + /// let nan = f64::NAN; + /// let f = 7.0_f64; + /// + /// assert!(nan.is_nan()); + /// assert!(!f.is_nan()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_nan(self) -> bool { Float::is_nan(self) } + + /// Returns `true` if this value is positive infinity or negative infinity and + /// false otherwise. + /// + /// ``` + /// use std::f64; + /// + /// let f = 7.0f64; + /// let inf = f64::INFINITY; + /// let neg_inf = f64::NEG_INFINITY; + /// let nan = f64::NAN; + /// + /// assert!(!f.is_infinite()); + /// assert!(!nan.is_infinite()); + /// + /// assert!(inf.is_infinite()); + /// assert!(neg_inf.is_infinite()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_infinite(self) -> bool { Float::is_infinite(self) } + + /// Returns `true` if this number is neither infinite nor `NaN`. + /// + /// ``` + /// use std::f64; + /// + /// let f = 7.0f64; + /// let inf: f64 = f64::INFINITY; + /// let neg_inf: f64 = f64::NEG_INFINITY; + /// let nan: f64 = f64::NAN; + /// + /// assert!(f.is_finite()); + /// + /// assert!(!nan.is_finite()); + /// assert!(!inf.is_finite()); + /// assert!(!neg_inf.is_finite()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_finite(self) -> bool { Float::is_finite(self) } + + /// Returns `true` if the number is neither zero, infinite, + /// [subnormal][subnormal], or `NaN`. + /// + /// ``` + /// use std::f64; + /// + /// let min = f64::MIN_POSITIVE; // 2.2250738585072014e-308f64 + /// let max = f64::MAX; + /// let lower_than_min = 1.0e-308_f64; + /// let zero = 0.0f64; + /// + /// assert!(min.is_normal()); + /// assert!(max.is_normal()); + /// + /// assert!(!zero.is_normal()); + /// assert!(!f64::NAN.is_normal()); + /// assert!(!f64::INFINITY.is_normal()); + /// // Values between `0` and `min` are Subnormal. + /// assert!(!lower_than_min.is_normal()); + /// ``` + /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_normal(self) -> bool { Float::is_normal(self) } + + /// Returns the floating point category of the number. If only one property + /// is going to be tested, it is generally faster to use the specific + /// predicate instead. + /// + /// ``` + /// use std::num::FpCategory; + /// use std::f64; + /// + /// let num = 12.4_f64; + /// let inf = f64::INFINITY; + /// + /// assert_eq!(num.classify(), FpCategory::Normal); + /// assert_eq!(inf.classify(), FpCategory::Infinite); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn classify(self) -> FpCategory { Float::classify(self) } + + /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with + /// positive sign bit and positive infinity. + /// + /// ``` + /// let f = 7.0_f64; + /// let g = -7.0_f64; + /// + /// assert!(f.is_sign_positive()); + /// assert!(!g.is_sign_positive()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_sign_positive(self) -> bool { Float::is_sign_positive(self) } + + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_deprecated(since = "1.0.0", reason = "renamed to is_sign_positive")] + #[inline] + #[doc(hidden)] + pub fn is_positive(self) -> bool { Float::is_sign_positive(self) } + + /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with + /// negative sign bit and negative infinity. + /// + /// ``` + /// let f = 7.0_f64; + /// let g = -7.0_f64; + /// + /// assert!(!f.is_sign_negative()); + /// assert!(g.is_sign_negative()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_sign_negative(self) -> bool { Float::is_sign_negative(self) } + + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_deprecated(since = "1.0.0", reason = "renamed to is_sign_negative")] + #[inline] + #[doc(hidden)] + pub fn is_negative(self) -> bool { Float::is_sign_negative(self) } + + /// Takes the reciprocal (inverse) of a number, `1/x`. + /// + /// ``` + /// let x = 2.0_f64; + /// let abs_difference = (x.recip() - (1.0/x)).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn recip(self) -> f64 { Float::recip(self) } + + /// Converts radians to degrees. + /// + /// ``` + /// use std::f64::consts; + /// + /// let angle = consts::PI; + /// + /// let abs_difference = (angle.to_degrees() - 180.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn to_degrees(self) -> f64 { Float::to_degrees(self) } + + /// Converts degrees to radians. + /// + /// ``` + /// use std::f64::consts; + /// + /// let angle = 180.0_f64; + /// + /// let abs_difference = (angle.to_radians() - consts::PI).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn to_radians(self) -> f64 { Float::to_radians(self) } + + /// Returns the maximum of the two numbers. + /// + /// ``` + /// let x = 1.0_f64; + /// let y = 2.0_f64; + /// + /// assert_eq!(x.max(y), y); + /// ``` + /// + /// If one of the arguments is NaN, then the other argument is returned. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn max(self, other: f64) -> f64 { + Float::max(self, other) + } + + /// Returns the minimum of the two numbers. + /// + /// ``` + /// let x = 1.0_f64; + /// let y = 2.0_f64; + /// + /// assert_eq!(x.min(y), x); + /// ``` + /// + /// If one of the arguments is NaN, then the other argument is returned. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn min(self, other: f64) -> f64 { + Float::min(self, other) + } + + /// Raw transmutation to `u64`. + /// + /// This is currently identical to `transmute::<f64, u64>(self)` on all platforms. + /// + /// See `from_bits` for some discussion of the portability of this operation + /// (there are almost no issues). + /// + /// Note that this function is distinct from `as` casting, which attempts to + /// preserve the *numeric* value, and not the bitwise value. + /// + /// # Examples + /// + /// ``` + /// assert!((1f64).to_bits() != 1f64 as u64); // to_bits() is not casting! + /// assert_eq!((12.5f64).to_bits(), 0x4029000000000000); + /// + /// ``` + #[stable(feature = "float_bits_conv", since = "1.20.0")] + #[inline] + pub fn to_bits(self) -> u64 { + Float::to_bits(self) + } + + /// Raw transmutation from `u64`. + /// + /// This is currently identical to `transmute::<u64, f64>(v)` on all platforms. + /// It turns out this is incredibly portable, for two reasons: + /// + /// * Floats and Ints have the same endianness on all supported platforms. + /// * IEEE-754 very precisely specifies the bit layout of floats. + /// + /// However there is one caveat: prior to the 2008 version of IEEE-754, how + /// to interpret the NaN signaling bit wasn't actually specified. Most platforms + /// (notably x86 and ARM) picked the interpretation that was ultimately + /// standardized in 2008, but some didn't (notably MIPS). As a result, all + /// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa. + /// + /// Rather than trying to preserve signaling-ness cross-platform, this + /// implementation favours preserving the exact bits. This means that + /// any payloads encoded in NaNs will be preserved even if the result of + /// this method is sent over the network from an x86 machine to a MIPS one. + /// + /// If the results of this method are only manipulated by the same + /// architecture that produced them, then there is no portability concern. + /// + /// If the input isn't NaN, then there is no portability concern. + /// + /// If you don't care about signalingness (very likely), then there is no + /// portability concern. + /// + /// Note that this function is distinct from `as` casting, which attempts to + /// preserve the *numeric* value, and not the bitwise value. + /// + /// # Examples + /// + /// ``` + /// use std::f64; + /// let v = f64::from_bits(0x4029000000000000); + /// let difference = (v - 12.5).abs(); + /// assert!(difference <= 1e-5); + /// ``` + #[stable(feature = "float_bits_conv", since = "1.20.0")] + #[inline] + pub fn from_bits(v: u64) -> Self { + Float::from_bits(v) + } +}} + +#[lang = "f64"] +#[cfg(not(test))] +#[cfg(not(stage0))] +impl f64 { + f64_core_methods!(); +} diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index f2e8caaad14..a062fbda5ba 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1765,7 +1765,11 @@ assert_eq!((-a).mod_euc(-b), 1); pub fn mod_euc(self, rhs: Self) -> Self { let r = self % rhs; if r < 0 { - r + rhs.abs() + if rhs < 0 { + r - rhs + } else { + r + rhs + } } else { r } @@ -4098,83 +4102,58 @@ pub enum FpCategory { Normal, } -/// A built-in floating point number. +// Technically private and only exposed for coretests: #[doc(hidden)] -#[unstable(feature = "core_float", - reason = "stable interface is via `impl f{32,64}` in later crates", - issue = "32110")] +#[unstable(feature = "float_internals", + reason = "internal routines only exposed for testing", + issue = "0")] pub trait Float: Sized { /// Type used by `to_bits` and `from_bits`. - #[stable(feature = "core_float_bits", since = "1.25.0")] type Bits; /// Returns `true` if this value is NaN and false otherwise. - #[stable(feature = "core", since = "1.6.0")] fn is_nan(self) -> bool; + /// Returns `true` if this value is positive infinity or negative infinity and /// false otherwise. - #[stable(feature = "core", since = "1.6.0")] fn is_infinite(self) -> bool; + /// Returns `true` if this number is neither infinite nor NaN. - #[stable(feature = "core", since = "1.6.0")] fn is_finite(self) -> bool; + /// Returns `true` if this number is neither zero, infinite, denormal, or NaN. - #[stable(feature = "core", since = "1.6.0")] fn is_normal(self) -> bool; + /// Returns the category that this number falls into. - #[stable(feature = "core", since = "1.6.0")] fn classify(self) -> FpCategory; - /// Computes the absolute value of `self`. Returns `Float::nan()` if the - /// number is `Float::nan()`. - #[stable(feature = "core", since = "1.6.0")] - fn abs(self) -> Self; - /// Returns a number that represents the sign of `self`. - /// - /// - `1.0` if the number is positive, `+0.0` or `Float::infinity()` - /// - `-1.0` if the number is negative, `-0.0` or `Float::neg_infinity()` - /// - `Float::nan()` if the number is `Float::nan()` - #[stable(feature = "core", since = "1.6.0")] - fn signum(self) -> Self; - /// Returns `true` if `self` is positive, including `+0.0` and /// `Float::infinity()`. - #[stable(feature = "core", since = "1.6.0")] fn is_sign_positive(self) -> bool; + /// Returns `true` if `self` is negative, including `-0.0` and /// `Float::neg_infinity()`. - #[stable(feature = "core", since = "1.6.0")] fn is_sign_negative(self) -> bool; /// Take the reciprocal (inverse) of a number, `1/x`. - #[stable(feature = "core", since = "1.6.0")] fn recip(self) -> Self; - /// Raise a number to an integer power. - /// - /// Using this function is generally faster than using `powf` - #[stable(feature = "core", since = "1.6.0")] - fn powi(self, n: i32) -> Self; - /// Convert radians to degrees. - #[stable(feature = "deg_rad_conversions", since="1.7.0")] fn to_degrees(self) -> Self; + /// Convert degrees to radians. - #[stable(feature = "deg_rad_conversions", since="1.7.0")] fn to_radians(self) -> Self; /// Returns the maximum of the two numbers. - #[stable(feature = "core_float_min_max", since="1.20.0")] fn max(self, other: Self) -> Self; + /// Returns the minimum of the two numbers. - #[stable(feature = "core_float_min_max", since="1.20.0")] fn min(self, other: Self) -> Self; /// Raw transmutation to integer. - #[stable(feature = "core_float_bits", since="1.25.0")] fn to_bits(self) -> Self::Bits; + /// Raw transmutation from integer. - #[stable(feature = "core_float_bits", since="1.25.0")] fn from_bits(v: Self::Bits) -> Self; } @@ -4192,7 +4171,7 @@ macro_rules! from_str_radix_int_impl { from_str_radix_int_impl! { isize i8 i16 i32 i64 i128 usize u8 u16 u32 u64 u128 } /// The error type returned when a checked integral type conversion fails. -#[stable(feature = "try_from", since = "1.26.0")] +#[unstable(feature = "try_from", issue = "33417")] #[derive(Debug, Copy, Clone)] pub struct TryFromIntError(()); @@ -4207,14 +4186,14 @@ impl TryFromIntError { } } -#[stable(feature = "try_from", since = "1.26.0")] +#[unstable(feature = "try_from", issue = "33417")] impl fmt::Display for TryFromIntError { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { self.__description().fmt(fmt) } } -#[stable(feature = "try_from", since = "1.26.0")] +#[unstable(feature = "try_from", issue = "33417")] impl From<!> for TryFromIntError { fn from(never: !) -> TryFromIntError { never @@ -4224,7 +4203,7 @@ impl From<!> for TryFromIntError { // only negative bounds macro_rules! try_from_lower_bounded { ($source:ty, $($target:ty),*) => {$( - #[stable(feature = "try_from", since = "1.26.0")] + #[unstable(feature = "try_from", issue = "33417")] impl TryFrom<$source> for $target { type Error = TryFromIntError; @@ -4243,7 +4222,7 @@ macro_rules! try_from_lower_bounded { // unsigned to signed (only positive bound) macro_rules! try_from_upper_bounded { ($source:ty, $($target:ty),*) => {$( - #[stable(feature = "try_from", since = "1.26.0")] + #[unstable(feature = "try_from", issue = "33417")] impl TryFrom<$source> for $target { type Error = TryFromIntError; @@ -4262,7 +4241,7 @@ macro_rules! try_from_upper_bounded { // all other cases macro_rules! try_from_both_bounded { ($source:ty, $($target:ty),*) => {$( - #[stable(feature = "try_from", since = "1.26.0")] + #[unstable(feature = "try_from", issue = "33417")] impl TryFrom<$source> for $target { type Error = TryFromIntError; diff --git a/src/libcore/ops/arith.rs b/src/libcore/ops/arith.rs index 88db019b02f..a1f6030428f 100644 --- a/src/libcore/ops/arith.rs +++ b/src/libcore/ops/arith.rs @@ -87,6 +87,7 @@ message="cannot add `{RHS}` to `{Self}`", label="no implementation for `{Self} + {RHS}`", )] +#[doc(alias = "+")] pub trait Add<RHS=Self> { /// The resulting type after applying the `+` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -183,6 +184,7 @@ add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } #[stable(feature = "rust1", since = "1.0.0")] #[rustc_on_unimplemented(message="cannot subtract `{RHS}` from `{Self}`", label="no implementation for `{Self} - {RHS}`")] +#[doc(alias = "-")] pub trait Sub<RHS=Self> { /// The resulting type after applying the `-` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -301,6 +303,7 @@ sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } #[stable(feature = "rust1", since = "1.0.0")] #[rustc_on_unimplemented(message="cannot multiply `{RHS}` to `{Self}`", label="no implementation for `{Self} * {RHS}`")] +#[doc(alias = "*")] pub trait Mul<RHS=Self> { /// The resulting type after applying the `*` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -423,6 +426,7 @@ mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } #[stable(feature = "rust1", since = "1.0.0")] #[rustc_on_unimplemented(message="cannot divide `{Self}` by `{RHS}`", label="no implementation for `{Self} / {RHS}`")] +#[doc(alias = "/")] pub trait Div<RHS=Self> { /// The resulting type after applying the `/` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -506,6 +510,7 @@ div_impl_float! { f32 f64 } #[stable(feature = "rust1", since = "1.0.0")] #[rustc_on_unimplemented(message="cannot mod `{Self}` by `{RHS}`", label="no implementation for `{Self} % {RHS}`")] +#[doc(alias = "%")] pub trait Rem<RHS=Self> { /// The resulting type after applying the `%` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -589,6 +594,7 @@ rem_impl_float! { f32 f64 } /// ``` #[lang = "neg"] #[stable(feature = "rust1", since = "1.0.0")] +#[doc(alias = "-")] pub trait Neg { /// The resulting type after applying the `-` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -664,6 +670,8 @@ neg_impl_numeric! { isize i8 i16 i32 i64 i128 f32 f64 } #[stable(feature = "op_assign_traits", since = "1.8.0")] #[rustc_on_unimplemented(message="cannot add-assign `{Rhs}` to `{Self}`", label="no implementation for `{Self} += {Rhs}`")] +#[doc(alias = "+")] +#[doc(alias = "+=")] pub trait AddAssign<Rhs=Self> { /// Performs the `+=` operation. #[stable(feature = "op_assign_traits", since = "1.8.0")] @@ -718,6 +726,8 @@ add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } #[stable(feature = "op_assign_traits", since = "1.8.0")] #[rustc_on_unimplemented(message="cannot subtract-assign `{Rhs}` from `{Self}`", label="no implementation for `{Self} -= {Rhs}`")] +#[doc(alias = "-")] +#[doc(alias = "-=")] pub trait SubAssign<Rhs=Self> { /// Performs the `-=` operation. #[stable(feature = "op_assign_traits", since = "1.8.0")] @@ -763,6 +773,8 @@ sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } #[stable(feature = "op_assign_traits", since = "1.8.0")] #[rustc_on_unimplemented(message="cannot multiply-assign `{Rhs}` to `{Self}`", label="no implementation for `{Self} *= {Rhs}`")] +#[doc(alias = "*")] +#[doc(alias = "*=")] pub trait MulAssign<Rhs=Self> { /// Performs the `*=` operation. #[stable(feature = "op_assign_traits", since = "1.8.0")] @@ -808,6 +820,8 @@ mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } #[stable(feature = "op_assign_traits", since = "1.8.0")] #[rustc_on_unimplemented(message="cannot divide-assign `{Self}` by `{Rhs}`", label="no implementation for `{Self} /= {Rhs}`")] +#[doc(alias = "/")] +#[doc(alias = "/=")] pub trait DivAssign<Rhs=Self> { /// Performs the `/=` operation. #[stable(feature = "op_assign_traits", since = "1.8.0")] @@ -856,6 +870,8 @@ div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } #[stable(feature = "op_assign_traits", since = "1.8.0")] #[rustc_on_unimplemented(message="cannot mod-assign `{Self}` by `{Rhs}``", label="no implementation for `{Self} %= {Rhs}`")] +#[doc(alias = "%")] +#[doc(alias = "%=")] pub trait RemAssign<Rhs=Self> { /// Performs the `%=` operation. #[stable(feature = "op_assign_traits", since = "1.8.0")] diff --git a/src/libcore/ops/index.rs b/src/libcore/ops/index.rs index d65c0aba504..0a0e92a9180 100644 --- a/src/libcore/ops/index.rs +++ b/src/libcore/ops/index.rs @@ -62,6 +62,9 @@ #[lang = "index"] #[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"] #[stable(feature = "rust1", since = "1.0.0")] +#[doc(alias = "]")] +#[doc(alias = "[")] +#[doc(alias = "[]")] pub trait Index<Idx: ?Sized> { /// The returned type after indexing. #[stable(feature = "rust1", since = "1.0.0")] @@ -146,6 +149,9 @@ pub trait Index<Idx: ?Sized> { #[lang = "index_mut"] #[rustc_on_unimplemented = "the type `{Self}` cannot be mutably indexed by `{Idx}`"] #[stable(feature = "rust1", since = "1.0.0")] +#[doc(alias = "[")] +#[doc(alias = "]")] +#[doc(alias = "[]")] pub trait IndexMut<Idx: ?Sized>: Index<Idx> { /// Performs the mutable indexing (`container[index]`) operation. #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/ops/try.rs b/src/libcore/ops/try.rs index ef6a8fb6a61..4f2d30aa6a8 100644 --- a/src/libcore/ops/try.rs +++ b/src/libcore/ops/try.rs @@ -28,6 +28,7 @@ that implement `{Try}`", label="the `?` operator cannot be applied to type `{Self}`") )] +#[doc(alias = "?")] pub trait Try { /// The type of this value when viewed as successful. #[unstable(feature = "try_trait", issue = "42327")] diff --git a/src/libcore/prelude/v1.rs b/src/libcore/prelude/v1.rs index cc3ad71117a..8212648f2d8 100644 --- a/src/libcore/prelude/v1.rs +++ b/src/libcore/prelude/v1.rs @@ -58,7 +58,9 @@ pub use result::Result::{self, Ok, Err}; // Re-exported extension traits for primitive types #[stable(feature = "core_prelude", since = "1.4.0")] #[doc(no_inline)] +#[cfg(stage0)] pub use slice::SliceExt; #[stable(feature = "core_prelude", since = "1.4.0")] #[doc(no_inline)] +#[cfg(stage0)] pub use str::StrExt; diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index afb149f2997..cc42acd77ae 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -68,12 +68,15 @@ struct Repr<T> { // Extension traits // +public_in_stage0! { +{ /// Extension methods for slices. #[unstable(feature = "core_slice_ext", reason = "stable interface provided by `impl [T]` in later crates", issue = "32110")] #[allow(missing_docs)] // documented elsewhere -pub trait SliceExt { +} +trait SliceExt { type Item; #[stable(feature = "core", since = "1.6.0")] @@ -238,7 +241,7 @@ pub trait SliceExt { fn sort_unstable_by_key<B, F>(&mut self, f: F) where F: FnMut(&Self::Item) -> B, B: Ord; -} +}} // Use macros to be generic over const/mut macro_rules! slice_offset { @@ -755,6 +758,1475 @@ impl<T> SliceExt for [T] { } } +// FIXME: remove (inline) this macro and the SliceExt trait +// when updating to a bootstrap compiler that has the new lang items. +#[cfg_attr(stage0, macro_export)] +#[unstable(feature = "core_slice_ext", issue = "32110")] +macro_rules! slice_core_methods { () => { + /// Returns the number of elements in the slice. + /// + /// # Examples + /// + /// ``` + /// let a = [1, 2, 3]; + /// assert_eq!(a.len(), 3); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn len(&self) -> usize { + SliceExt::len(self) + } + + /// Returns `true` if the slice has a length of 0. + /// + /// # Examples + /// + /// ``` + /// let a = [1, 2, 3]; + /// assert!(!a.is_empty()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_empty(&self) -> bool { + SliceExt::is_empty(self) + } + + /// Returns the first element of the slice, or `None` if it is empty. + /// + /// # Examples + /// + /// ``` + /// let v = [10, 40, 30]; + /// assert_eq!(Some(&10), v.first()); + /// + /// let w: &[i32] = &[]; + /// assert_eq!(None, w.first()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn first(&self) -> Option<&T> { + SliceExt::first(self) + } + + /// Returns a mutable pointer to the first element of the slice, or `None` if it is empty. + /// + /// # Examples + /// + /// ``` + /// let x = &mut [0, 1, 2]; + /// + /// if let Some(first) = x.first_mut() { + /// *first = 5; + /// } + /// assert_eq!(x, &[5, 1, 2]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn first_mut(&mut self) -> Option<&mut T> { + SliceExt::first_mut(self) + } + + /// Returns the first and all the rest of the elements of the slice, or `None` if it is empty. + /// + /// # Examples + /// + /// ``` + /// let x = &[0, 1, 2]; + /// + /// if let Some((first, elements)) = x.split_first() { + /// assert_eq!(first, &0); + /// assert_eq!(elements, &[1, 2]); + /// } + /// ``` + #[stable(feature = "slice_splits", since = "1.5.0")] + #[inline] + pub fn split_first(&self) -> Option<(&T, &[T])> { + SliceExt::split_first(self) + } + + /// Returns the first and all the rest of the elements of the slice, or `None` if it is empty. + /// + /// # Examples + /// + /// ``` + /// let x = &mut [0, 1, 2]; + /// + /// if let Some((first, elements)) = x.split_first_mut() { + /// *first = 3; + /// elements[0] = 4; + /// elements[1] = 5; + /// } + /// assert_eq!(x, &[3, 4, 5]); + /// ``` + #[stable(feature = "slice_splits", since = "1.5.0")] + #[inline] + pub fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> { + SliceExt::split_first_mut(self) + } + + /// Returns the last and all the rest of the elements of the slice, or `None` if it is empty. + /// + /// # Examples + /// + /// ``` + /// let x = &[0, 1, 2]; + /// + /// if let Some((last, elements)) = x.split_last() { + /// assert_eq!(last, &2); + /// assert_eq!(elements, &[0, 1]); + /// } + /// ``` + #[stable(feature = "slice_splits", since = "1.5.0")] + #[inline] + pub fn split_last(&self) -> Option<(&T, &[T])> { + SliceExt::split_last(self) + + } + + /// Returns the last and all the rest of the elements of the slice, or `None` if it is empty. + /// + /// # Examples + /// + /// ``` + /// let x = &mut [0, 1, 2]; + /// + /// if let Some((last, elements)) = x.split_last_mut() { + /// *last = 3; + /// elements[0] = 4; + /// elements[1] = 5; + /// } + /// assert_eq!(x, &[4, 5, 3]); + /// ``` + #[stable(feature = "slice_splits", since = "1.5.0")] + #[inline] + pub fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> { + SliceExt::split_last_mut(self) + } + + /// Returns the last element of the slice, or `None` if it is empty. + /// + /// # Examples + /// + /// ``` + /// let v = [10, 40, 30]; + /// assert_eq!(Some(&30), v.last()); + /// + /// let w: &[i32] = &[]; + /// assert_eq!(None, w.last()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn last(&self) -> Option<&T> { + SliceExt::last(self) + } + + /// Returns a mutable pointer to the last item in the slice. + /// + /// # Examples + /// + /// ``` + /// let x = &mut [0, 1, 2]; + /// + /// if let Some(last) = x.last_mut() { + /// *last = 10; + /// } + /// assert_eq!(x, &[0, 1, 10]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn last_mut(&mut self) -> Option<&mut T> { + SliceExt::last_mut(self) + } + + /// Returns a reference to an element or subslice depending on the type of + /// index. + /// + /// - If given a position, returns a reference to the element at that + /// position or `None` if out of bounds. + /// - If given a range, returns the subslice corresponding to that range, + /// or `None` if out of bounds. + /// + /// # Examples + /// + /// ``` + /// let v = [10, 40, 30]; + /// assert_eq!(Some(&40), v.get(1)); + /// assert_eq!(Some(&[10, 40][..]), v.get(0..2)); + /// assert_eq!(None, v.get(3)); + /// assert_eq!(None, v.get(0..4)); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn get<I>(&self, index: I) -> Option<&I::Output> + where I: SliceIndex<Self> + { + SliceExt::get(self, index) + } + + /// Returns a mutable reference to an element or subslice depending on the + /// type of index (see [`get`]) or `None` if the index is out of bounds. + /// + /// [`get`]: #method.get + /// + /// # Examples + /// + /// ``` + /// let x = &mut [0, 1, 2]; + /// + /// if let Some(elem) = x.get_mut(1) { + /// *elem = 42; + /// } + /// assert_eq!(x, &[0, 42, 2]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output> + where I: SliceIndex<Self> + { + SliceExt::get_mut(self, index) + } + + /// Returns a reference to an element or subslice, without doing bounds + /// checking. + /// + /// This is generally not recommended, use with caution! For a safe + /// alternative see [`get`]. + /// + /// [`get`]: #method.get + /// + /// # Examples + /// + /// ``` + /// let x = &[1, 2, 4]; + /// + /// unsafe { + /// assert_eq!(x.get_unchecked(1), &2); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub unsafe fn get_unchecked<I>(&self, index: I) -> &I::Output + where I: SliceIndex<Self> + { + SliceExt::get_unchecked(self, index) + } + + /// Returns a mutable reference to an element or subslice, without doing + /// bounds checking. + /// + /// This is generally not recommended, use with caution! For a safe + /// alternative see [`get_mut`]. + /// + /// [`get_mut`]: #method.get_mut + /// + /// # Examples + /// + /// ``` + /// let x = &mut [1, 2, 4]; + /// + /// unsafe { + /// let elem = x.get_unchecked_mut(1); + /// *elem = 13; + /// } + /// assert_eq!(x, &[1, 13, 4]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output + where I: SliceIndex<Self> + { + SliceExt::get_unchecked_mut(self, index) + } + + /// Returns a raw pointer to the slice's buffer. + /// + /// The caller must ensure that the slice outlives the pointer this + /// function returns, or else it will end up pointing to garbage. + /// + /// Modifying the container referenced by this slice may cause its buffer + /// to be reallocated, which would also make any pointers to it invalid. + /// + /// # Examples + /// + /// ``` + /// let x = &[1, 2, 4]; + /// let x_ptr = x.as_ptr(); + /// + /// unsafe { + /// for i in 0..x.len() { + /// assert_eq!(x.get_unchecked(i), &*x_ptr.offset(i as isize)); + /// } + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn as_ptr(&self) -> *const T { + SliceExt::as_ptr(self) + } + + /// Returns an unsafe mutable pointer to the slice's buffer. + /// + /// The caller must ensure that the slice outlives the pointer this + /// function returns, or else it will end up pointing to garbage. + /// + /// Modifying the container referenced by this slice may cause its buffer + /// to be reallocated, which would also make any pointers to it invalid. + /// + /// # Examples + /// + /// ``` + /// let x = &mut [1, 2, 4]; + /// let x_ptr = x.as_mut_ptr(); + /// + /// unsafe { + /// for i in 0..x.len() { + /// *x_ptr.offset(i as isize) += 2; + /// } + /// } + /// assert_eq!(x, &[3, 4, 6]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut T { + SliceExt::as_mut_ptr(self) + } + + /// Swaps two elements in the slice. + /// + /// # Arguments + /// + /// * a - The index of the first element + /// * b - The index of the second element + /// + /// # Panics + /// + /// Panics if `a` or `b` are out of bounds. + /// + /// # Examples + /// + /// ``` + /// let mut v = ["a", "b", "c", "d"]; + /// v.swap(1, 3); + /// assert!(v == ["a", "d", "c", "b"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn swap(&mut self, a: usize, b: usize) { + SliceExt::swap(self, a, b) + } + + /// Reverses the order of elements in the slice, in place. + /// + /// # Examples + /// + /// ``` + /// let mut v = [1, 2, 3]; + /// v.reverse(); + /// assert!(v == [3, 2, 1]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn reverse(&mut self) { + SliceExt::reverse(self) + } + + /// Returns an iterator over the slice. + /// + /// # Examples + /// + /// ``` + /// let x = &[1, 2, 4]; + /// let mut iterator = x.iter(); + /// + /// assert_eq!(iterator.next(), Some(&1)); + /// assert_eq!(iterator.next(), Some(&2)); + /// assert_eq!(iterator.next(), Some(&4)); + /// assert_eq!(iterator.next(), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn iter(&self) -> Iter<T> { + SliceExt::iter(self) + } + + /// Returns an iterator that allows modifying each value. + /// + /// # Examples + /// + /// ``` + /// let x = &mut [1, 2, 4]; + /// for elem in x.iter_mut() { + /// *elem += 2; + /// } + /// assert_eq!(x, &[3, 4, 6]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn iter_mut(&mut self) -> IterMut<T> { + SliceExt::iter_mut(self) + } + + /// Returns an iterator over all contiguous windows of length + /// `size`. The windows overlap. If the slice is shorter than + /// `size`, the iterator returns no values. + /// + /// # Panics + /// + /// Panics if `size` is 0. + /// + /// # Examples + /// + /// ``` + /// let slice = ['r', 'u', 's', 't']; + /// let mut iter = slice.windows(2); + /// assert_eq!(iter.next().unwrap(), &['r', 'u']); + /// assert_eq!(iter.next().unwrap(), &['u', 's']); + /// assert_eq!(iter.next().unwrap(), &['s', 't']); + /// assert!(iter.next().is_none()); + /// ``` + /// + /// If the slice is shorter than `size`: + /// + /// ``` + /// let slice = ['f', 'o', 'o']; + /// let mut iter = slice.windows(4); + /// assert!(iter.next().is_none()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn windows(&self, size: usize) -> Windows<T> { + SliceExt::windows(self, size) + } + + /// Returns an iterator over `chunk_size` elements of the slice at a + /// time. The chunks are slices and do not overlap. If `chunk_size` does + /// not divide the length of the slice, then the last chunk will + /// not have length `chunk_size`. + /// + /// See [`exact_chunks`] for a variant of this iterator that returns chunks + /// of always exactly `chunk_size` elements. + /// + /// # Panics + /// + /// Panics if `chunk_size` is 0. + /// + /// # Examples + /// + /// ``` + /// let slice = ['l', 'o', 'r', 'e', 'm']; + /// let mut iter = slice.chunks(2); + /// assert_eq!(iter.next().unwrap(), &['l', 'o']); + /// assert_eq!(iter.next().unwrap(), &['r', 'e']); + /// assert_eq!(iter.next().unwrap(), &['m']); + /// assert!(iter.next().is_none()); + /// ``` + /// + /// [`exact_chunks`]: #method.exact_chunks + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn chunks(&self, chunk_size: usize) -> Chunks<T> { + SliceExt::chunks(self, chunk_size) + } + + /// Returns an iterator over `chunk_size` elements of the slice at a + /// time. The chunks are slices and do not overlap. If `chunk_size` does + /// not divide the length of the slice, then the last up to `chunk_size-1` + /// elements will be omitted. + /// + /// Due to each chunk having exactly `chunk_size` elements, the compiler + /// can often optimize the resulting code better than in the case of + /// [`chunks`]. + /// + /// # Panics + /// + /// Panics if `chunk_size` is 0. + /// + /// # Examples + /// + /// ``` + /// #![feature(exact_chunks)] + /// + /// let slice = ['l', 'o', 'r', 'e', 'm']; + /// let mut iter = slice.exact_chunks(2); + /// assert_eq!(iter.next().unwrap(), &['l', 'o']); + /// assert_eq!(iter.next().unwrap(), &['r', 'e']); + /// assert!(iter.next().is_none()); + /// ``` + /// + /// [`chunks`]: #method.chunks + #[unstable(feature = "exact_chunks", issue = "47115")] + #[inline] + pub fn exact_chunks(&self, chunk_size: usize) -> ExactChunks<T> { + SliceExt::exact_chunks(self, chunk_size) + } + + /// Returns an iterator over `chunk_size` elements of the slice at a time. + /// The chunks are mutable slices, and do not overlap. If `chunk_size` does + /// not divide the length of the slice, then the last chunk will not + /// have length `chunk_size`. + /// + /// See [`exact_chunks_mut`] for a variant of this iterator that returns chunks + /// of always exactly `chunk_size` elements. + /// + /// # Panics + /// + /// Panics if `chunk_size` is 0. + /// + /// # Examples + /// + /// ``` + /// let v = &mut [0, 0, 0, 0, 0]; + /// let mut count = 1; + /// + /// for chunk in v.chunks_mut(2) { + /// for elem in chunk.iter_mut() { + /// *elem += count; + /// } + /// count += 1; + /// } + /// assert_eq!(v, &[1, 1, 2, 2, 3]); + /// ``` + /// + /// [`exact_chunks_mut`]: #method.exact_chunks_mut + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<T> { + SliceExt::chunks_mut(self, chunk_size) + } + + /// Returns an iterator over `chunk_size` elements of the slice at a time. + /// The chunks are mutable slices, and do not overlap. If `chunk_size` does + /// not divide the length of the slice, then the last up to `chunk_size-1` + /// elements will be omitted. + /// + /// + /// Due to each chunk having exactly `chunk_size` elements, the compiler + /// can often optimize the resulting code better than in the case of + /// [`chunks_mut`]. + /// + /// # Panics + /// + /// Panics if `chunk_size` is 0. + /// + /// # Examples + /// + /// ``` + /// #![feature(exact_chunks)] + /// + /// let v = &mut [0, 0, 0, 0, 0]; + /// let mut count = 1; + /// + /// for chunk in v.exact_chunks_mut(2) { + /// for elem in chunk.iter_mut() { + /// *elem += count; + /// } + /// count += 1; + /// } + /// assert_eq!(v, &[1, 1, 2, 2, 0]); + /// ``` + /// + /// [`chunks_mut`]: #method.chunks_mut + #[unstable(feature = "exact_chunks", issue = "47115")] + #[inline] + pub fn exact_chunks_mut(&mut self, chunk_size: usize) -> ExactChunksMut<T> { + SliceExt::exact_chunks_mut(self, chunk_size) + } + + /// Divides one slice into two at an index. + /// + /// The first will contain all indices from `[0, mid)` (excluding + /// the index `mid` itself) and the second will contain all + /// indices from `[mid, len)` (excluding the index `len` itself). + /// + /// # Panics + /// + /// Panics if `mid > len`. + /// + /// # Examples + /// + /// ``` + /// let v = [1, 2, 3, 4, 5, 6]; + /// + /// { + /// let (left, right) = v.split_at(0); + /// assert!(left == []); + /// assert!(right == [1, 2, 3, 4, 5, 6]); + /// } + /// + /// { + /// let (left, right) = v.split_at(2); + /// assert!(left == [1, 2]); + /// assert!(right == [3, 4, 5, 6]); + /// } + /// + /// { + /// let (left, right) = v.split_at(6); + /// assert!(left == [1, 2, 3, 4, 5, 6]); + /// assert!(right == []); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn split_at(&self, mid: usize) -> (&[T], &[T]) { + SliceExt::split_at(self, mid) + } + + /// Divides one mutable slice into two at an index. + /// + /// The first will contain all indices from `[0, mid)` (excluding + /// the index `mid` itself) and the second will contain all + /// indices from `[mid, len)` (excluding the index `len` itself). + /// + /// # Panics + /// + /// Panics if `mid > len`. + /// + /// # Examples + /// + /// ``` + /// let mut v = [1, 0, 3, 0, 5, 6]; + /// // scoped to restrict the lifetime of the borrows + /// { + /// let (left, right) = v.split_at_mut(2); + /// assert!(left == [1, 0]); + /// assert!(right == [3, 0, 5, 6]); + /// left[1] = 2; + /// right[1] = 4; + /// } + /// assert!(v == [1, 2, 3, 4, 5, 6]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { + SliceExt::split_at_mut(self, mid) + } + + /// Returns an iterator over subslices separated by elements that match + /// `pred`. The matched element is not contained in the subslices. + /// + /// # Examples + /// + /// ``` + /// let slice = [10, 40, 33, 20]; + /// let mut iter = slice.split(|num| num % 3 == 0); + /// + /// assert_eq!(iter.next().unwrap(), &[10, 40]); + /// assert_eq!(iter.next().unwrap(), &[20]); + /// assert!(iter.next().is_none()); + /// ``` + /// + /// If the first element is matched, an empty slice will be the first item + /// returned by the iterator. Similarly, if the last element in the slice + /// is matched, an empty slice will be the last item returned by the + /// iterator: + /// + /// ``` + /// let slice = [10, 40, 33]; + /// let mut iter = slice.split(|num| num % 3 == 0); + /// + /// assert_eq!(iter.next().unwrap(), &[10, 40]); + /// assert_eq!(iter.next().unwrap(), &[]); + /// assert!(iter.next().is_none()); + /// ``` + /// + /// If two matched elements are directly adjacent, an empty slice will be + /// present between them: + /// + /// ``` + /// let slice = [10, 6, 33, 20]; + /// let mut iter = slice.split(|num| num % 3 == 0); + /// + /// assert_eq!(iter.next().unwrap(), &[10]); + /// assert_eq!(iter.next().unwrap(), &[]); + /// assert_eq!(iter.next().unwrap(), &[20]); + /// assert!(iter.next().is_none()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn split<F>(&self, pred: F) -> Split<T, F> + where F: FnMut(&T) -> bool + { + SliceExt::split(self, pred) + } + + /// Returns an iterator over mutable subslices separated by elements that + /// match `pred`. The matched element is not contained in the subslices. + /// + /// # Examples + /// + /// ``` + /// let mut v = [10, 40, 30, 20, 60, 50]; + /// + /// for group in v.split_mut(|num| *num % 3 == 0) { + /// group[0] = 1; + /// } + /// assert_eq!(v, [1, 40, 30, 1, 60, 1]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn split_mut<F>(&mut self, pred: F) -> SplitMut<T, F> + where F: FnMut(&T) -> bool + { + SliceExt::split_mut(self, pred) + } + + /// Returns an iterator over subslices separated by elements that match + /// `pred`, starting at the end of the slice and working backwards. + /// The matched element is not contained in the subslices. + /// + /// # Examples + /// + /// ``` + /// let slice = [11, 22, 33, 0, 44, 55]; + /// let mut iter = slice.rsplit(|num| *num == 0); + /// + /// assert_eq!(iter.next().unwrap(), &[44, 55]); + /// assert_eq!(iter.next().unwrap(), &[11, 22, 33]); + /// assert_eq!(iter.next(), None); + /// ``` + /// + /// As with `split()`, if the first or last element is matched, an empty + /// slice will be the first (or last) item returned by the iterator. + /// + /// ``` + /// let v = &[0, 1, 1, 2, 3, 5, 8]; + /// let mut it = v.rsplit(|n| *n % 2 == 0); + /// assert_eq!(it.next().unwrap(), &[]); + /// assert_eq!(it.next().unwrap(), &[3, 5]); + /// assert_eq!(it.next().unwrap(), &[1, 1]); + /// assert_eq!(it.next().unwrap(), &[]); + /// assert_eq!(it.next(), None); + /// ``` + #[stable(feature = "slice_rsplit", since = "1.27.0")] + #[inline] + pub fn rsplit<F>(&self, pred: F) -> RSplit<T, F> + where F: FnMut(&T) -> bool + { + SliceExt::rsplit(self, pred) + } + + /// Returns an iterator over mutable subslices separated by elements that + /// match `pred`, starting at the end of the slice and working + /// backwards. The matched element is not contained in the subslices. + /// + /// # Examples + /// + /// ``` + /// let mut v = [100, 400, 300, 200, 600, 500]; + /// + /// let mut count = 0; + /// for group in v.rsplit_mut(|num| *num % 3 == 0) { + /// count += 1; + /// group[0] = count; + /// } + /// assert_eq!(v, [3, 400, 300, 2, 600, 1]); + /// ``` + /// + #[stable(feature = "slice_rsplit", since = "1.27.0")] + #[inline] + pub fn rsplit_mut<F>(&mut self, pred: F) -> RSplitMut<T, F> + where F: FnMut(&T) -> bool + { + SliceExt::rsplit_mut(self, pred) + } + + /// Returns an iterator over subslices separated by elements that match + /// `pred`, limited to returning at most `n` items. The matched element is + /// not contained in the subslices. + /// + /// The last element returned, if any, will contain the remainder of the + /// slice. + /// + /// # Examples + /// + /// Print the slice split once by numbers divisible by 3 (i.e. `[10, 40]`, + /// `[20, 60, 50]`): + /// + /// ``` + /// let v = [10, 40, 30, 20, 60, 50]; + /// + /// for group in v.splitn(2, |num| *num % 3 == 0) { + /// println!("{:?}", group); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn splitn<F>(&self, n: usize, pred: F) -> SplitN<T, F> + where F: FnMut(&T) -> bool + { + SliceExt::splitn(self, n, pred) + } + + /// Returns an iterator over subslices separated by elements that match + /// `pred`, limited to returning at most `n` items. The matched element is + /// not contained in the subslices. + /// + /// The last element returned, if any, will contain the remainder of the + /// slice. + /// + /// # Examples + /// + /// ``` + /// let mut v = [10, 40, 30, 20, 60, 50]; + /// + /// for group in v.splitn_mut(2, |num| *num % 3 == 0) { + /// group[0] = 1; + /// } + /// assert_eq!(v, [1, 40, 30, 1, 60, 50]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn splitn_mut<F>(&mut self, n: usize, pred: F) -> SplitNMut<T, F> + where F: FnMut(&T) -> bool + { + SliceExt::splitn_mut(self, n, pred) + } + + /// Returns an iterator over subslices separated by elements that match + /// `pred` limited to returning at most `n` items. This starts at the end of + /// the slice and works backwards. The matched element is not contained in + /// the subslices. + /// + /// The last element returned, if any, will contain the remainder of the + /// slice. + /// + /// # Examples + /// + /// Print the slice split once, starting from the end, by numbers divisible + /// by 3 (i.e. `[50]`, `[10, 40, 30, 20]`): + /// + /// ``` + /// let v = [10, 40, 30, 20, 60, 50]; + /// + /// for group in v.rsplitn(2, |num| *num % 3 == 0) { + /// println!("{:?}", group); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn rsplitn<F>(&self, n: usize, pred: F) -> RSplitN<T, F> + where F: FnMut(&T) -> bool + { + SliceExt::rsplitn(self, n, pred) + } + + /// Returns an iterator over subslices separated by elements that match + /// `pred` limited to returning at most `n` items. This starts at the end of + /// the slice and works backwards. The matched element is not contained in + /// the subslices. + /// + /// The last element returned, if any, will contain the remainder of the + /// slice. + /// + /// # Examples + /// + /// ``` + /// let mut s = [10, 40, 30, 20, 60, 50]; + /// + /// for group in s.rsplitn_mut(2, |num| *num % 3 == 0) { + /// group[0] = 1; + /// } + /// assert_eq!(s, [1, 40, 30, 20, 60, 1]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn rsplitn_mut<F>(&mut self, n: usize, pred: F) -> RSplitNMut<T, F> + where F: FnMut(&T) -> bool + { + SliceExt::rsplitn_mut(self, n, pred) + } + + /// Returns `true` if the slice contains an element with the given value. + /// + /// # Examples + /// + /// ``` + /// let v = [10, 40, 30]; + /// assert!(v.contains(&30)); + /// assert!(!v.contains(&50)); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn contains(&self, x: &T) -> bool + where T: PartialEq + { + SliceExt::contains(self, x) + } + + /// Returns `true` if `needle` is a prefix of the slice. + /// + /// # Examples + /// + /// ``` + /// let v = [10, 40, 30]; + /// assert!(v.starts_with(&[10])); + /// assert!(v.starts_with(&[10, 40])); + /// assert!(!v.starts_with(&[50])); + /// assert!(!v.starts_with(&[10, 50])); + /// ``` + /// + /// Always returns `true` if `needle` is an empty slice: + /// + /// ``` + /// let v = &[10, 40, 30]; + /// assert!(v.starts_with(&[])); + /// let v: &[u8] = &[]; + /// assert!(v.starts_with(&[])); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn starts_with(&self, needle: &[T]) -> bool + where T: PartialEq + { + SliceExt::starts_with(self, needle) + } + + /// Returns `true` if `needle` is a suffix of the slice. + /// + /// # Examples + /// + /// ``` + /// let v = [10, 40, 30]; + /// assert!(v.ends_with(&[30])); + /// assert!(v.ends_with(&[40, 30])); + /// assert!(!v.ends_with(&[50])); + /// assert!(!v.ends_with(&[50, 30])); + /// ``` + /// + /// Always returns `true` if `needle` is an empty slice: + /// + /// ``` + /// let v = &[10, 40, 30]; + /// assert!(v.ends_with(&[])); + /// let v: &[u8] = &[]; + /// assert!(v.ends_with(&[])); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn ends_with(&self, needle: &[T]) -> bool + where T: PartialEq + { + SliceExt::ends_with(self, needle) + } + + /// Binary searches this sorted slice for a given element. + /// + /// If the value is found then `Ok` is returned, containing the + /// index of the matching element; if the value is not found then + /// `Err` is returned, containing the index where a matching + /// element could be inserted while maintaining sorted order. + /// + /// # Examples + /// + /// Looks up a series of four elements. The first is found, with a + /// uniquely determined position; the second and third are not + /// found; the fourth could match any position in `[1, 4]`. + /// + /// ``` + /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; + /// + /// assert_eq!(s.binary_search(&13), Ok(9)); + /// assert_eq!(s.binary_search(&4), Err(7)); + /// assert_eq!(s.binary_search(&100), Err(13)); + /// let r = s.binary_search(&1); + /// assert!(match r { Ok(1...4) => true, _ => false, }); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn binary_search(&self, x: &T) -> Result<usize, usize> + where T: Ord + { + SliceExt::binary_search(self, x) + } + + /// Binary searches this sorted slice with a comparator function. + /// + /// The comparator function should implement an order consistent + /// with the sort order of the underlying slice, returning an + /// order code that indicates whether its argument is `Less`, + /// `Equal` or `Greater` the desired target. + /// + /// If a matching value is found then returns `Ok`, containing + /// the index for the matched element; if no match is found then + /// `Err` is returned, containing the index where a matching + /// element could be inserted while maintaining sorted order. + /// + /// # Examples + /// + /// Looks up a series of four elements. The first is found, with a + /// uniquely determined position; the second and third are not + /// found; the fourth could match any position in `[1, 4]`. + /// + /// ``` + /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; + /// + /// let seek = 13; + /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Ok(9)); + /// let seek = 4; + /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(7)); + /// let seek = 100; + /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(13)); + /// let seek = 1; + /// let r = s.binary_search_by(|probe| probe.cmp(&seek)); + /// assert!(match r { Ok(1...4) => true, _ => false, }); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn binary_search_by<'a, F>(&'a self, f: F) -> Result<usize, usize> + where F: FnMut(&'a T) -> Ordering + { + SliceExt::binary_search_by(self, f) + } + + /// Binary searches this sorted slice with a key extraction function. + /// + /// Assumes that the slice is sorted by the key, for instance with + /// [`sort_by_key`] using the same key extraction function. + /// + /// If a matching value is found then returns `Ok`, containing the + /// index for the matched element; if no match is found then `Err` + /// is returned, containing the index where a matching element could + /// be inserted while maintaining sorted order. + /// + /// [`sort_by_key`]: #method.sort_by_key + /// + /// # Examples + /// + /// Looks up a series of four elements in a slice of pairs sorted by + /// their second elements. The first is found, with a uniquely + /// determined position; the second and third are not found; the + /// fourth could match any position in `[1, 4]`. + /// + /// ``` + /// let s = [(0, 0), (2, 1), (4, 1), (5, 1), (3, 1), + /// (1, 2), (2, 3), (4, 5), (5, 8), (3, 13), + /// (1, 21), (2, 34), (4, 55)]; + /// + /// assert_eq!(s.binary_search_by_key(&13, |&(a,b)| b), Ok(9)); + /// assert_eq!(s.binary_search_by_key(&4, |&(a,b)| b), Err(7)); + /// assert_eq!(s.binary_search_by_key(&100, |&(a,b)| b), Err(13)); + /// let r = s.binary_search_by_key(&1, |&(a,b)| b); + /// assert!(match r { Ok(1...4) => true, _ => false, }); + /// ``` + #[stable(feature = "slice_binary_search_by_key", since = "1.10.0")] + #[inline] + pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, f: F) -> Result<usize, usize> + where F: FnMut(&'a T) -> B, + B: Ord + { + SliceExt::binary_search_by_key(self, b, f) + } + + /// Sorts the slice, but may not preserve the order of equal elements. + /// + /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate), + /// and `O(n log n)` worst-case. + /// + /// # Current implementation + /// + /// The current algorithm is based on [pattern-defeating quicksort][pdqsort] by Orson Peters, + /// which combines the fast average case of randomized quicksort with the fast worst case of + /// heapsort, while achieving linear time on slices with certain patterns. It uses some + /// randomization to avoid degenerate cases, but with a fixed seed to always provide + /// deterministic behavior. + /// + /// It is typically faster than stable sorting, except in a few special cases, e.g. when the + /// slice consists of several concatenated sorted sequences. + /// + /// # Examples + /// + /// ``` + /// let mut v = [-5, 4, 1, -3, 2]; + /// + /// v.sort_unstable(); + /// assert!(v == [-5, -3, 1, 2, 4]); + /// ``` + /// + /// [pdqsort]: https://github.com/orlp/pdqsort + #[stable(feature = "sort_unstable", since = "1.20.0")] + #[inline] + pub fn sort_unstable(&mut self) + where T: Ord + { + SliceExt::sort_unstable(self); + } + + /// Sorts the slice with a comparator function, but may not preserve the order of equal + /// elements. + /// + /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate), + /// and `O(n log n)` worst-case. + /// + /// # Current implementation + /// + /// The current algorithm is based on [pattern-defeating quicksort][pdqsort] by Orson Peters, + /// which combines the fast average case of randomized quicksort with the fast worst case of + /// heapsort, while achieving linear time on slices with certain patterns. It uses some + /// randomization to avoid degenerate cases, but with a fixed seed to always provide + /// deterministic behavior. + /// + /// It is typically faster than stable sorting, except in a few special cases, e.g. when the + /// slice consists of several concatenated sorted sequences. + /// + /// # Examples + /// + /// ``` + /// let mut v = [5, 4, 1, 3, 2]; + /// v.sort_unstable_by(|a, b| a.cmp(b)); + /// assert!(v == [1, 2, 3, 4, 5]); + /// + /// // reverse sorting + /// v.sort_unstable_by(|a, b| b.cmp(a)); + /// assert!(v == [5, 4, 3, 2, 1]); + /// ``` + /// + /// [pdqsort]: https://github.com/orlp/pdqsort + #[stable(feature = "sort_unstable", since = "1.20.0")] + #[inline] + pub fn sort_unstable_by<F>(&mut self, compare: F) + where F: FnMut(&T, &T) -> Ordering + { + SliceExt::sort_unstable_by(self, compare); + } + + /// Sorts the slice with a key extraction function, but may not preserve the order of equal + /// elements. + /// + /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate), + /// and `O(m n log(m n))` worst-case, where the key function is `O(m)`. + /// + /// # Current implementation + /// + /// The current algorithm is based on [pattern-defeating quicksort][pdqsort] by Orson Peters, + /// which combines the fast average case of randomized quicksort with the fast worst case of + /// heapsort, while achieving linear time on slices with certain patterns. It uses some + /// randomization to avoid degenerate cases, but with a fixed seed to always provide + /// deterministic behavior. + /// + /// # Examples + /// + /// ``` + /// let mut v = [-5i32, 4, 1, -3, 2]; + /// + /// v.sort_unstable_by_key(|k| k.abs()); + /// assert!(v == [1, 2, -3, 4, -5]); + /// ``` + /// + /// [pdqsort]: https://github.com/orlp/pdqsort + #[stable(feature = "sort_unstable", since = "1.20.0")] + #[inline] + pub fn sort_unstable_by_key<K, F>(&mut self, f: F) + where F: FnMut(&T) -> K, K: Ord + { + SliceExt::sort_unstable_by_key(self, f); + } + + /// Rotates the slice in-place such that the first `mid` elements of the + /// slice move to the end while the last `self.len() - mid` elements move to + /// the front. After calling `rotate_left`, the element previously at index + /// `mid` will become the first element in the slice. + /// + /// # Panics + /// + /// This function will panic if `mid` is greater than the length of the + /// slice. Note that `mid == self.len()` does _not_ panic and is a no-op + /// rotation. + /// + /// # Complexity + /// + /// Takes linear (in `self.len()`) time. + /// + /// # Examples + /// + /// ``` + /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f']; + /// a.rotate_left(2); + /// assert_eq!(a, ['c', 'd', 'e', 'f', 'a', 'b']); + /// ``` + /// + /// Rotating a subslice: + /// + /// ``` + /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f']; + /// a[1..5].rotate_left(1); + /// assert_eq!(a, ['a', 'c', 'd', 'e', 'b', 'f']); + /// ``` + #[stable(feature = "slice_rotate", since = "1.26.0")] + pub fn rotate_left(&mut self, mid: usize) { + SliceExt::rotate_left(self, mid); + } + + /// Rotates the slice in-place such that the first `self.len() - k` + /// elements of the slice move to the end while the last `k` elements move + /// to the front. After calling `rotate_right`, the element previously at + /// index `self.len() - k` will become the first element in the slice. + /// + /// # Panics + /// + /// This function will panic if `k` is greater than the length of the + /// slice. Note that `k == self.len()` does _not_ panic and is a no-op + /// rotation. + /// + /// # Complexity + /// + /// Takes linear (in `self.len()`) time. + /// + /// # Examples + /// + /// ``` + /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f']; + /// a.rotate_right(2); + /// assert_eq!(a, ['e', 'f', 'a', 'b', 'c', 'd']); + /// ``` + /// + /// Rotate a subslice: + /// + /// ``` + /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f']; + /// a[1..5].rotate_right(1); + /// assert_eq!(a, ['a', 'e', 'b', 'c', 'd', 'f']); + /// ``` + #[stable(feature = "slice_rotate", since = "1.26.0")] + pub fn rotate_right(&mut self, k: usize) { + SliceExt::rotate_right(self, k); + } + + /// Copies the elements from `src` into `self`. + /// + /// The length of `src` must be the same as `self`. + /// + /// If `src` implements `Copy`, it can be more performant to use + /// [`copy_from_slice`]. + /// + /// # Panics + /// + /// This function will panic if the two slices have different lengths. + /// + /// # Examples + /// + /// Cloning two elements from a slice into another: + /// + /// ``` + /// let src = [1, 2, 3, 4]; + /// let mut dst = [0, 0]; + /// + /// dst.clone_from_slice(&src[2..]); + /// + /// assert_eq!(src, [1, 2, 3, 4]); + /// assert_eq!(dst, [3, 4]); + /// ``` + /// + /// Rust enforces that there can only be one mutable reference with no + /// immutable references to a particular piece of data in a particular + /// scope. Because of this, attempting to use `clone_from_slice` on a + /// single slice will result in a compile failure: + /// + /// ```compile_fail + /// let mut slice = [1, 2, 3, 4, 5]; + /// + /// slice[..2].clone_from_slice(&slice[3..]); // compile fail! + /// ``` + /// + /// To work around this, we can use [`split_at_mut`] to create two distinct + /// sub-slices from a slice: + /// + /// ``` + /// let mut slice = [1, 2, 3, 4, 5]; + /// + /// { + /// let (left, right) = slice.split_at_mut(2); + /// left.clone_from_slice(&right[1..]); + /// } + /// + /// assert_eq!(slice, [4, 5, 3, 4, 5]); + /// ``` + /// + /// [`copy_from_slice`]: #method.copy_from_slice + /// [`split_at_mut`]: #method.split_at_mut + #[stable(feature = "clone_from_slice", since = "1.7.0")] + pub fn clone_from_slice(&mut self, src: &[T]) where T: Clone { + SliceExt::clone_from_slice(self, src) + } + + /// Copies all elements from `src` into `self`, using a memcpy. + /// + /// The length of `src` must be the same as `self`. + /// + /// If `src` does not implement `Copy`, use [`clone_from_slice`]. + /// + /// # Panics + /// + /// This function will panic if the two slices have different lengths. + /// + /// # Examples + /// + /// Copying two elements from a slice into another: + /// + /// ``` + /// let src = [1, 2, 3, 4]; + /// let mut dst = [0, 0]; + /// + /// dst.copy_from_slice(&src[2..]); + /// + /// assert_eq!(src, [1, 2, 3, 4]); + /// assert_eq!(dst, [3, 4]); + /// ``` + /// + /// Rust enforces that there can only be one mutable reference with no + /// immutable references to a particular piece of data in a particular + /// scope. Because of this, attempting to use `copy_from_slice` on a + /// single slice will result in a compile failure: + /// + /// ```compile_fail + /// let mut slice = [1, 2, 3, 4, 5]; + /// + /// slice[..2].copy_from_slice(&slice[3..]); // compile fail! + /// ``` + /// + /// To work around this, we can use [`split_at_mut`] to create two distinct + /// sub-slices from a slice: + /// + /// ``` + /// let mut slice = [1, 2, 3, 4, 5]; + /// + /// { + /// let (left, right) = slice.split_at_mut(2); + /// left.copy_from_slice(&right[1..]); + /// } + /// + /// assert_eq!(slice, [4, 5, 3, 4, 5]); + /// ``` + /// + /// [`clone_from_slice`]: #method.clone_from_slice + /// [`split_at_mut`]: #method.split_at_mut + #[stable(feature = "copy_from_slice", since = "1.9.0")] + pub fn copy_from_slice(&mut self, src: &[T]) where T: Copy { + SliceExt::copy_from_slice(self, src) + } + + /// Swaps all elements in `self` with those in `other`. + /// + /// The length of `other` must be the same as `self`. + /// + /// # Panics + /// + /// This function will panic if the two slices have different lengths. + /// + /// # Example + /// + /// Swapping two elements across slices: + /// + /// ``` + /// let mut slice1 = [0, 0]; + /// let mut slice2 = [1, 2, 3, 4]; + /// + /// slice1.swap_with_slice(&mut slice2[2..]); + /// + /// assert_eq!(slice1, [3, 4]); + /// assert_eq!(slice2, [1, 2, 0, 0]); + /// ``` + /// + /// Rust enforces that there can only be one mutable reference to a + /// particular piece of data in a particular scope. Because of this, + /// attempting to use `swap_with_slice` on a single slice will result in + /// a compile failure: + /// + /// ```compile_fail + /// let mut slice = [1, 2, 3, 4, 5]; + /// slice[..2].swap_with_slice(&mut slice[3..]); // compile fail! + /// ``` + /// + /// To work around this, we can use [`split_at_mut`] to create two distinct + /// mutable sub-slices from a slice: + /// + /// ``` + /// let mut slice = [1, 2, 3, 4, 5]; + /// + /// { + /// let (left, right) = slice.split_at_mut(2); + /// left.swap_with_slice(&mut right[1..]); + /// } + /// + /// assert_eq!(slice, [4, 5, 3, 1, 2]); + /// ``` + /// + /// [`split_at_mut`]: #method.split_at_mut + #[stable(feature = "swap_with_slice", since = "1.27.0")] + pub fn swap_with_slice(&mut self, other: &mut [T]) { + SliceExt::swap_with_slice(self, other) + } +}} + +#[lang = "slice"] +#[cfg(not(test))] +#[cfg(not(stage0))] +impl<T> [T] { + slice_core_methods!(); +} + +// FIXME: remove (inline) this macro +// when updating to a bootstrap compiler that has the new lang items. +#[cfg_attr(stage0, macro_export)] +#[unstable(feature = "core_slice_ext", issue = "32110")] +macro_rules! slice_u8_core_methods { () => { + /// Checks if all bytes in this slice are within the ASCII range. + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[inline] + pub fn is_ascii(&self) -> bool { + self.iter().all(|b| b.is_ascii()) + } + + /// Checks that two slices are an ASCII case-insensitive match. + /// + /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`, + /// but without allocating and copying temporaries. + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[inline] + pub fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool { + self.len() == other.len() && + self.iter().zip(other).all(|(a, b)| { + a.eq_ignore_ascii_case(b) + }) + } + + /// Converts this slice to its ASCII upper case equivalent in-place. + /// + /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', + /// but non-ASCII letters are unchanged. + /// + /// To return a new uppercased value without modifying the existing one, use + /// [`to_ascii_uppercase`]. + /// + /// [`to_ascii_uppercase`]: #method.to_ascii_uppercase + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[inline] + pub fn make_ascii_uppercase(&mut self) { + for byte in self { + byte.make_ascii_uppercase(); + } + } + + /// Converts this slice to its ASCII lower case equivalent in-place. + /// + /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', + /// but non-ASCII letters are unchanged. + /// + /// To return a new lowercased value without modifying the existing one, use + /// [`to_ascii_lowercase`]. + /// + /// [`to_ascii_lowercase`]: #method.to_ascii_lowercase + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[inline] + pub fn make_ascii_lowercase(&mut self) { + for byte in self { + byte.make_ascii_lowercase(); + } + } +}} + +#[lang = "slice_u8"] +#[cfg(not(test))] +#[cfg(not(stage0))] +impl [u8] { + slice_u8_core_methods!(); +} + #[stable(feature = "rust1", since = "1.0.0")] #[rustc_on_unimplemented = "slice indices are of type `usize` or ranges of `usize`"] impl<T, I> ops::Index<I> for [T] diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index f1fe23092de..b39d9feb35b 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -2100,31 +2100,28 @@ mod traits { fn index(self, slice: &str) -> &Self::Output { assert!(self.end != usize::max_value(), "attempted to index str up to maximum usize"); - let end = self.end + 1; - self.get(slice).unwrap_or_else(|| super::slice_error_fail(slice, 0, end)) + (..self.end+1).index(slice) } #[inline] fn index_mut(self, slice: &mut str) -> &mut Self::Output { assert!(self.end != usize::max_value(), "attempted to index str up to maximum usize"); - if slice.is_char_boundary(self.end) { - unsafe { self.get_unchecked_mut(slice) } - } else { - super::slice_error_fail(slice, 0, self.end + 1) - } + (..self.end+1).index_mut(slice) } } } - +public_in_stage0! { +{ /// Methods for string slices #[allow(missing_docs)] #[doc(hidden)] #[unstable(feature = "core_str_ext", reason = "stable interface provided by `impl str` in later crates", issue = "32110")] -pub trait StrExt { +} +trait StrExt { // NB there are no docs here are they're all located on the StrExt trait in // liballoc, not here. @@ -2218,17 +2215,13 @@ pub trait StrExt { fn parse<T: FromStr>(&self) -> Result<T, T::Err>; #[stable(feature = "split_whitespace", since = "1.1.0")] fn split_whitespace<'a>(&'a self) -> SplitWhitespace<'a>; - #[stable(feature = "unicode_methods_on_intrinsics", since = "1.27.0")] - fn is_whitespace(&self) -> bool; - #[stable(feature = "unicode_methods_on_intrinsics", since = "1.27.0")] - fn is_alphanumeric(&self) -> bool; #[stable(feature = "rust1", since = "1.0.0")] fn trim(&self) -> &str; #[stable(feature = "rust1", since = "1.0.0")] fn trim_left(&self) -> &str; #[stable(feature = "rust1", since = "1.0.0")] fn trim_right(&self) -> &str; -} +}} // truncate `&str` to length at most equal to `max` // return `true` if it were truncated, and the new str. @@ -2555,16 +2548,6 @@ impl StrExt for str { } #[inline] - fn is_whitespace(&self) -> bool { - self.chars().all(|c| c.is_whitespace()) - } - - #[inline] - fn is_alphanumeric(&self) -> bool { - self.chars().all(|c| c.is_alphanumeric()) - } - - #[inline] fn trim(&self) -> &str { self.trim_matches(|c: char| c.is_whitespace()) } @@ -2580,6 +2563,1685 @@ impl StrExt for str { } } +// FIXME: remove (inline) this macro and the SliceExt trait +// when updating to a bootstrap compiler that has the new lang items. +#[cfg_attr(stage0, macro_export)] +#[unstable(feature = "core_str_ext", issue = "32110")] +macro_rules! str_core_methods { () => { + /// Returns the length of `self`. + /// + /// This length is in bytes, not [`char`]s or graphemes. In other words, + /// it may not be what a human considers the length of the string. + /// + /// [`char`]: primitive.char.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let len = "foo".len(); + /// assert_eq!(3, len); + /// + /// let len = "ƒoo".len(); // fancy f! + /// assert_eq!(4, len); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn len(&self) -> usize { + StrExt::len(self) + } + + /// Returns `true` if `self` has a length of zero bytes. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = ""; + /// assert!(s.is_empty()); + /// + /// let s = "not empty"; + /// assert!(!s.is_empty()); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_empty(&self) -> bool { + StrExt::is_empty(self) + } + + /// Checks that `index`-th byte lies at the start and/or end of a + /// UTF-8 code point sequence. + /// + /// The start and end of the string (when `index == self.len()`) are + /// considered to be + /// boundaries. + /// + /// Returns `false` if `index` is greater than `self.len()`. + /// + /// # Examples + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// assert!(s.is_char_boundary(0)); + /// // start of `老` + /// assert!(s.is_char_boundary(6)); + /// assert!(s.is_char_boundary(s.len())); + /// + /// // second byte of `ö` + /// assert!(!s.is_char_boundary(2)); + /// + /// // third byte of `老` + /// assert!(!s.is_char_boundary(8)); + /// ``` + #[stable(feature = "is_char_boundary", since = "1.9.0")] + #[inline] + pub fn is_char_boundary(&self, index: usize) -> bool { + StrExt::is_char_boundary(self, index) + } + + /// Converts a string slice to a byte slice. To convert the byte slice back + /// into a string slice, use the [`str::from_utf8`] function. + /// + /// [`str::from_utf8`]: ./str/fn.from_utf8.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let bytes = "bors".as_bytes(); + /// assert_eq!(b"bors", bytes); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline(always)] + pub fn as_bytes(&self) -> &[u8] { + StrExt::as_bytes(self) + } + + /// Converts a mutable string slice to a mutable byte slice. To convert the + /// mutable byte slice back into a mutable string slice, use the + /// [`str::from_utf8_mut`] function. + /// + /// [`str::from_utf8_mut`]: ./str/fn.from_utf8_mut.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut s = String::from("Hello"); + /// let bytes = unsafe { s.as_bytes_mut() }; + /// + /// assert_eq!(b"Hello", bytes); + /// ``` + /// + /// Mutability: + /// + /// ``` + /// let mut s = String::from("🗻∈🌏"); + /// + /// unsafe { + /// let bytes = s.as_bytes_mut(); + /// + /// bytes[0] = 0xF0; + /// bytes[1] = 0x9F; + /// bytes[2] = 0x8D; + /// bytes[3] = 0x94; + /// } + /// + /// assert_eq!("🍔∈🌏", s); + /// ``` + #[stable(feature = "str_mut_extras", since = "1.20.0")] + #[inline(always)] + pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] { + StrExt::as_bytes_mut(self) + } + + /// Converts a string slice to a raw pointer. + /// + /// As string slices are a slice of bytes, the raw pointer points to a + /// [`u8`]. This pointer will be pointing to the first byte of the string + /// slice. + /// + /// [`u8`]: primitive.u8.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = "Hello"; + /// let ptr = s.as_ptr(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn as_ptr(&self) -> *const u8 { + StrExt::as_ptr(self) + } + + /// Returns a subslice of `str`. + /// + /// This is the non-panicking alternative to indexing the `str`. Returns + /// [`None`] whenever equivalent indexing operation would panic. + /// + /// [`None`]: option/enum.Option.html#variant.None + /// + /// # Examples + /// + /// ``` + /// let v = String::from("🗻∈🌏"); + /// + /// assert_eq!(Some("🗻"), v.get(0..4)); + /// + /// // indices not on UTF-8 sequence boundaries + /// assert!(v.get(1..).is_none()); + /// assert!(v.get(..8).is_none()); + /// + /// // out of bounds + /// assert!(v.get(..42).is_none()); + /// ``` + #[stable(feature = "str_checked_slicing", since = "1.20.0")] + #[inline] + pub fn get<I: SliceIndex<str>>(&self, i: I) -> Option<&I::Output> { + StrExt::get(self, i) + } + + /// Returns a mutable subslice of `str`. + /// + /// This is the non-panicking alternative to indexing the `str`. Returns + /// [`None`] whenever equivalent indexing operation would panic. + /// + /// [`None`]: option/enum.Option.html#variant.None + /// + /// # Examples + /// + /// ``` + /// let mut v = String::from("hello"); + /// // correct length + /// assert!(v.get_mut(0..5).is_some()); + /// // out of bounds + /// assert!(v.get_mut(..42).is_none()); + /// assert_eq!(Some("he"), v.get_mut(0..2).map(|v| &*v)); + /// + /// assert_eq!("hello", v); + /// { + /// let s = v.get_mut(0..2); + /// let s = s.map(|s| { + /// s.make_ascii_uppercase(); + /// &*s + /// }); + /// assert_eq!(Some("HE"), s); + /// } + /// assert_eq!("HEllo", v); + /// ``` + #[stable(feature = "str_checked_slicing", since = "1.20.0")] + #[inline] + pub fn get_mut<I: SliceIndex<str>>(&mut self, i: I) -> Option<&mut I::Output> { + StrExt::get_mut(self, i) + } + + /// Returns a unchecked subslice of `str`. + /// + /// This is the unchecked alternative to indexing the `str`. + /// + /// # Safety + /// + /// Callers of this function are responsible that these preconditions are + /// satisfied: + /// + /// * The starting index must come before the ending index; + /// * Indexes must be within bounds of the original slice; + /// * Indexes must lie on UTF-8 sequence boundaries. + /// + /// Failing that, the returned string slice may reference invalid memory or + /// violate the invariants communicated by the `str` type. + /// + /// # Examples + /// + /// ``` + /// let v = "🗻∈🌏"; + /// unsafe { + /// assert_eq!("🗻", v.get_unchecked(0..4)); + /// assert_eq!("∈", v.get_unchecked(4..7)); + /// assert_eq!("🌏", v.get_unchecked(7..11)); + /// } + /// ``` + #[stable(feature = "str_checked_slicing", since = "1.20.0")] + #[inline] + pub unsafe fn get_unchecked<I: SliceIndex<str>>(&self, i: I) -> &I::Output { + StrExt::get_unchecked(self, i) + } + + /// Returns a mutable, unchecked subslice of `str`. + /// + /// This is the unchecked alternative to indexing the `str`. + /// + /// # Safety + /// + /// Callers of this function are responsible that these preconditions are + /// satisfied: + /// + /// * The starting index must come before the ending index; + /// * Indexes must be within bounds of the original slice; + /// * Indexes must lie on UTF-8 sequence boundaries. + /// + /// Failing that, the returned string slice may reference invalid memory or + /// violate the invariants communicated by the `str` type. + /// + /// # Examples + /// + /// ``` + /// let mut v = String::from("🗻∈🌏"); + /// unsafe { + /// assert_eq!("🗻", v.get_unchecked_mut(0..4)); + /// assert_eq!("∈", v.get_unchecked_mut(4..7)); + /// assert_eq!("🌏", v.get_unchecked_mut(7..11)); + /// } + /// ``` + #[stable(feature = "str_checked_slicing", since = "1.20.0")] + #[inline] + pub unsafe fn get_unchecked_mut<I: SliceIndex<str>>(&mut self, i: I) -> &mut I::Output { + StrExt::get_unchecked_mut(self, i) + } + + /// Creates a string slice from another string slice, bypassing safety + /// checks. + /// + /// This is generally not recommended, use with caution! For a safe + /// alternative see [`str`] and [`Index`]. + /// + /// [`str`]: primitive.str.html + /// [`Index`]: ops/trait.Index.html + /// + /// This new slice goes from `begin` to `end`, including `begin` but + /// excluding `end`. + /// + /// To get a mutable string slice instead, see the + /// [`slice_mut_unchecked`] method. + /// + /// [`slice_mut_unchecked`]: #method.slice_mut_unchecked + /// + /// # Safety + /// + /// Callers of this function are responsible that three preconditions are + /// satisfied: + /// + /// * `begin` must come before `end`. + /// * `begin` and `end` must be byte positions within the string slice. + /// * `begin` and `end` must lie on UTF-8 sequence boundaries. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// unsafe { + /// assert_eq!("Löwe 老虎 Léopard", s.slice_unchecked(0, 21)); + /// } + /// + /// let s = "Hello, world!"; + /// + /// unsafe { + /// assert_eq!("world", s.slice_unchecked(7, 12)); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str { + StrExt::slice_unchecked(self, begin, end) + } + + /// Creates a string slice from another string slice, bypassing safety + /// checks. + /// This is generally not recommended, use with caution! For a safe + /// alternative see [`str`] and [`IndexMut`]. + /// + /// [`str`]: primitive.str.html + /// [`IndexMut`]: ops/trait.IndexMut.html + /// + /// This new slice goes from `begin` to `end`, including `begin` but + /// excluding `end`. + /// + /// To get an immutable string slice instead, see the + /// [`slice_unchecked`] method. + /// + /// [`slice_unchecked`]: #method.slice_unchecked + /// + /// # Safety + /// + /// Callers of this function are responsible that three preconditions are + /// satisfied: + /// + /// * `begin` must come before `end`. + /// * `begin` and `end` must be byte positions within the string slice. + /// * `begin` and `end` must lie on UTF-8 sequence boundaries. + #[stable(feature = "str_slice_mut", since = "1.5.0")] + #[inline] + pub unsafe fn slice_mut_unchecked(&mut self, begin: usize, end: usize) -> &mut str { + StrExt::slice_mut_unchecked(self, begin, end) + } + + /// Divide one string slice into two at an index. + /// + /// The argument, `mid`, should be a byte offset from the start of the + /// string. It must also be on the boundary of a UTF-8 code point. + /// + /// The two slices returned go from the start of the string slice to `mid`, + /// and from `mid` to the end of the string slice. + /// + /// To get mutable string slices instead, see the [`split_at_mut`] + /// method. + /// + /// [`split_at_mut`]: #method.split_at_mut + /// + /// # Panics + /// + /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is + /// beyond the last code point of the string slice. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = "Per Martin-Löf"; + /// + /// let (first, last) = s.split_at(3); + /// + /// assert_eq!("Per", first); + /// assert_eq!(" Martin-Löf", last); + /// ``` + #[inline] + #[stable(feature = "str_split_at", since = "1.4.0")] + pub fn split_at(&self, mid: usize) -> (&str, &str) { + StrExt::split_at(self, mid) + } + + /// Divide one mutable string slice into two at an index. + /// + /// The argument, `mid`, should be a byte offset from the start of the + /// string. It must also be on the boundary of a UTF-8 code point. + /// + /// The two slices returned go from the start of the string slice to `mid`, + /// and from `mid` to the end of the string slice. + /// + /// To get immutable string slices instead, see the [`split_at`] method. + /// + /// [`split_at`]: #method.split_at + /// + /// # Panics + /// + /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is + /// beyond the last code point of the string slice. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut s = "Per Martin-Löf".to_string(); + /// { + /// let (first, last) = s.split_at_mut(3); + /// first.make_ascii_uppercase(); + /// assert_eq!("PER", first); + /// assert_eq!(" Martin-Löf", last); + /// } + /// assert_eq!("PER Martin-Löf", s); + /// ``` + #[inline] + #[stable(feature = "str_split_at", since = "1.4.0")] + pub fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str) { + StrExt::split_at_mut(self, mid) + } + + /// Returns an iterator over the [`char`]s of a string slice. + /// + /// As a string slice consists of valid UTF-8, we can iterate through a + /// string slice by [`char`]. This method returns such an iterator. + /// + /// It's important to remember that [`char`] represents a Unicode Scalar + /// Value, and may not match your idea of what a 'character' is. Iteration + /// over grapheme clusters may be what you actually want. + /// + /// [`char`]: primitive.char.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let word = "goodbye"; + /// + /// let count = word.chars().count(); + /// assert_eq!(7, count); + /// + /// let mut chars = word.chars(); + /// + /// assert_eq!(Some('g'), chars.next()); + /// assert_eq!(Some('o'), chars.next()); + /// assert_eq!(Some('o'), chars.next()); + /// assert_eq!(Some('d'), chars.next()); + /// assert_eq!(Some('b'), chars.next()); + /// assert_eq!(Some('y'), chars.next()); + /// assert_eq!(Some('e'), chars.next()); + /// + /// assert_eq!(None, chars.next()); + /// ``` + /// + /// Remember, [`char`]s may not match your human intuition about characters: + /// + /// ``` + /// let y = "y̆"; + /// + /// let mut chars = y.chars(); + /// + /// assert_eq!(Some('y'), chars.next()); // not 'y̆' + /// assert_eq!(Some('\u{0306}'), chars.next()); + /// + /// assert_eq!(None, chars.next()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn chars(&self) -> Chars { + StrExt::chars(self) + } + /// Returns an iterator over the [`char`]s of a string slice, and their + /// positions. + /// + /// As a string slice consists of valid UTF-8, we can iterate through a + /// string slice by [`char`]. This method returns an iterator of both + /// these [`char`]s, as well as their byte positions. + /// + /// The iterator yields tuples. The position is first, the [`char`] is + /// second. + /// + /// [`char`]: primitive.char.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let word = "goodbye"; + /// + /// let count = word.char_indices().count(); + /// assert_eq!(7, count); + /// + /// let mut char_indices = word.char_indices(); + /// + /// assert_eq!(Some((0, 'g')), char_indices.next()); + /// assert_eq!(Some((1, 'o')), char_indices.next()); + /// assert_eq!(Some((2, 'o')), char_indices.next()); + /// assert_eq!(Some((3, 'd')), char_indices.next()); + /// assert_eq!(Some((4, 'b')), char_indices.next()); + /// assert_eq!(Some((5, 'y')), char_indices.next()); + /// assert_eq!(Some((6, 'e')), char_indices.next()); + /// + /// assert_eq!(None, char_indices.next()); + /// ``` + /// + /// Remember, [`char`]s may not match your human intuition about characters: + /// + /// ``` + /// let yes = "y̆es"; + /// + /// let mut char_indices = yes.char_indices(); + /// + /// assert_eq!(Some((0, 'y')), char_indices.next()); // not (0, 'y̆') + /// assert_eq!(Some((1, '\u{0306}')), char_indices.next()); + /// + /// // note the 3 here - the last character took up two bytes + /// assert_eq!(Some((3, 'e')), char_indices.next()); + /// assert_eq!(Some((4, 's')), char_indices.next()); + /// + /// assert_eq!(None, char_indices.next()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn char_indices(&self) -> CharIndices { + StrExt::char_indices(self) + } + + /// An iterator over the bytes of a string slice. + /// + /// As a string slice consists of a sequence of bytes, we can iterate + /// through a string slice by byte. This method returns such an iterator. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut bytes = "bors".bytes(); + /// + /// assert_eq!(Some(b'b'), bytes.next()); + /// assert_eq!(Some(b'o'), bytes.next()); + /// assert_eq!(Some(b'r'), bytes.next()); + /// assert_eq!(Some(b's'), bytes.next()); + /// + /// assert_eq!(None, bytes.next()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn bytes(&self) -> Bytes { + StrExt::bytes(self) + } + + /// Split a string slice by whitespace. + /// + /// The iterator returned will return string slices that are sub-slices of + /// the original string slice, separated by any amount of whitespace. + /// + /// 'Whitespace' is defined according to the terms of the Unicode Derived + /// Core Property `White_Space`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut iter = "A few words".split_whitespace(); + /// + /// assert_eq!(Some("A"), iter.next()); + /// assert_eq!(Some("few"), iter.next()); + /// assert_eq!(Some("words"), iter.next()); + /// + /// assert_eq!(None, iter.next()); + /// ``` + /// + /// All kinds of whitespace are considered: + /// + /// ``` + /// let mut iter = " Mary had\ta\u{2009}little \n\t lamb".split_whitespace(); + /// assert_eq!(Some("Mary"), iter.next()); + /// assert_eq!(Some("had"), iter.next()); + /// assert_eq!(Some("a"), iter.next()); + /// assert_eq!(Some("little"), iter.next()); + /// assert_eq!(Some("lamb"), iter.next()); + /// + /// assert_eq!(None, iter.next()); + /// ``` + #[stable(feature = "split_whitespace", since = "1.1.0")] + #[inline] + pub fn split_whitespace(&self) -> SplitWhitespace { + StrExt::split_whitespace(self) + } + + /// An iterator over the lines of a string, as string slices. + /// + /// Lines are ended with either a newline (`\n`) or a carriage return with + /// a line feed (`\r\n`). + /// + /// The final line ending is optional. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let text = "foo\r\nbar\n\nbaz\n"; + /// let mut lines = text.lines(); + /// + /// assert_eq!(Some("foo"), lines.next()); + /// assert_eq!(Some("bar"), lines.next()); + /// assert_eq!(Some(""), lines.next()); + /// assert_eq!(Some("baz"), lines.next()); + /// + /// assert_eq!(None, lines.next()); + /// ``` + /// + /// The final line ending isn't required: + /// + /// ``` + /// let text = "foo\nbar\n\r\nbaz"; + /// let mut lines = text.lines(); + /// + /// assert_eq!(Some("foo"), lines.next()); + /// assert_eq!(Some("bar"), lines.next()); + /// assert_eq!(Some(""), lines.next()); + /// assert_eq!(Some("baz"), lines.next()); + /// + /// assert_eq!(None, lines.next()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn lines(&self) -> Lines { + StrExt::lines(self) + } + + /// An iterator over the lines of a string. + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_deprecated(since = "1.4.0", reason = "use lines() instead now")] + #[inline] + #[allow(deprecated)] + pub fn lines_any(&self) -> LinesAny { + StrExt::lines_any(self) + } + + /// Returns an iterator of `u16` over the string encoded as UTF-16. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let text = "Zażółć gęślą jaźń"; + /// + /// let utf8_len = text.len(); + /// let utf16_len = text.encode_utf16().count(); + /// + /// assert!(utf16_len <= utf8_len); + /// ``` + #[stable(feature = "encode_utf16", since = "1.8.0")] + pub fn encode_utf16(&self) -> EncodeUtf16 { + EncodeUtf16::new(self) + } + + /// Returns `true` if the given pattern matches a sub-slice of + /// this string slice. + /// + /// Returns `false` if it does not. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let bananas = "bananas"; + /// + /// assert!(bananas.contains("nana")); + /// assert!(!bananas.contains("apples")); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool { + StrExt::contains(self, pat) + } + + /// Returns `true` if the given pattern matches a prefix of this + /// string slice. + /// + /// Returns `false` if it does not. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let bananas = "bananas"; + /// + /// assert!(bananas.starts_with("bana")); + /// assert!(!bananas.starts_with("nana")); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn starts_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool { + StrExt::starts_with(self, pat) + } + + /// Returns `true` if the given pattern matches a suffix of this + /// string slice. + /// + /// Returns `false` if it does not. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let bananas = "bananas"; + /// + /// assert!(bananas.ends_with("anas")); + /// assert!(!bananas.ends_with("nana")); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn ends_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool + where P::Searcher: ReverseSearcher<'a> + { + StrExt::ends_with(self, pat) + } + + /// Returns the byte index of the first character of this string slice that + /// matches the pattern. + /// + /// Returns [`None`] if the pattern doesn't match. + /// + /// The pattern can be a `&str`, [`char`], or a closure that determines if + /// a character matches. + /// + /// [`char`]: primitive.char.html + /// [`None`]: option/enum.Option.html#variant.None + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// assert_eq!(s.find('L'), Some(0)); + /// assert_eq!(s.find('é'), Some(14)); + /// assert_eq!(s.find("Léopard"), Some(13)); + /// ``` + /// + /// More complex patterns using point-free style and closures: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// assert_eq!(s.find(char::is_whitespace), Some(5)); + /// assert_eq!(s.find(char::is_lowercase), Some(1)); + /// assert_eq!(s.find(|c: char| c.is_whitespace() || c.is_lowercase()), Some(1)); + /// assert_eq!(s.find(|c: char| (c < 'o') && (c > 'a')), Some(4)); + /// ``` + /// + /// Not finding the pattern: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// let x: &[_] = &['1', '2']; + /// + /// assert_eq!(s.find(x), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> { + StrExt::find(self, pat) + } + + /// Returns the byte index of the last character of this string slice that + /// matches the pattern. + /// + /// Returns [`None`] if the pattern doesn't match. + /// + /// The pattern can be a `&str`, [`char`], or a closure that determines if + /// a character matches. + /// + /// [`char`]: primitive.char.html + /// [`None`]: option/enum.Option.html#variant.None + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// assert_eq!(s.rfind('L'), Some(13)); + /// assert_eq!(s.rfind('é'), Some(14)); + /// ``` + /// + /// More complex patterns with closures: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// assert_eq!(s.rfind(char::is_whitespace), Some(12)); + /// assert_eq!(s.rfind(char::is_lowercase), Some(20)); + /// ``` + /// + /// Not finding the pattern: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// let x: &[_] = &['1', '2']; + /// + /// assert_eq!(s.rfind(x), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> + where P::Searcher: ReverseSearcher<'a> + { + StrExt::rfind(self, pat) + } + + /// An iterator over substrings of this string slice, separated by + /// characters matched by a pattern. + /// + /// The pattern can be a `&str`, [`char`], or a closure that determines the + /// split. + /// + /// # Iterator behavior + /// + /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern + /// allows a reverse search and forward/reverse search yields the same + /// elements. This is true for, eg, [`char`] but not for `&str`. + /// + /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html + /// + /// If the pattern allows a reverse search but its results might differ + /// from a forward search, the [`rsplit`] method can be used. + /// + /// [`char`]: primitive.char.html + /// [`rsplit`]: #method.rsplit + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// let v: Vec<&str> = "Mary had a little lamb".split(' ').collect(); + /// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]); + /// + /// let v: Vec<&str> = "".split('X').collect(); + /// assert_eq!(v, [""]); + /// + /// let v: Vec<&str> = "lionXXtigerXleopard".split('X').collect(); + /// assert_eq!(v, ["lion", "", "tiger", "leopard"]); + /// + /// let v: Vec<&str> = "lion::tiger::leopard".split("::").collect(); + /// assert_eq!(v, ["lion", "tiger", "leopard"]); + /// + /// let v: Vec<&str> = "abc1def2ghi".split(char::is_numeric).collect(); + /// assert_eq!(v, ["abc", "def", "ghi"]); + /// + /// let v: Vec<&str> = "lionXtigerXleopard".split(char::is_uppercase).collect(); + /// assert_eq!(v, ["lion", "tiger", "leopard"]); + /// ``` + /// + /// A more complex pattern, using a closure: + /// + /// ``` + /// let v: Vec<&str> = "abc1defXghi".split(|c| c == '1' || c == 'X').collect(); + /// assert_eq!(v, ["abc", "def", "ghi"]); + /// ``` + /// + /// If a string contains multiple contiguous separators, you will end up + /// with empty strings in the output: + /// + /// ``` + /// let x = "||||a||b|c".to_string(); + /// let d: Vec<_> = x.split('|').collect(); + /// + /// assert_eq!(d, &["", "", "", "", "a", "", "b", "c"]); + /// ``` + /// + /// Contiguous separators are separated by the empty string. + /// + /// ``` + /// let x = "(///)".to_string(); + /// let d: Vec<_> = x.split('/').collect(); + /// + /// assert_eq!(d, &["(", "", "", ")"]); + /// ``` + /// + /// Separators at the start or end of a string are neighbored + /// by empty strings. + /// + /// ``` + /// let d: Vec<_> = "010".split("0").collect(); + /// assert_eq!(d, &["", "1", ""]); + /// ``` + /// + /// When the empty string is used as a separator, it separates + /// every character in the string, along with the beginning + /// and end of the string. + /// + /// ``` + /// let f: Vec<_> = "rust".split("").collect(); + /// assert_eq!(f, &["", "r", "u", "s", "t", ""]); + /// ``` + /// + /// Contiguous separators can lead to possibly surprising behavior + /// when whitespace is used as the separator. This code is correct: + /// + /// ``` + /// let x = " a b c".to_string(); + /// let d: Vec<_> = x.split(' ').collect(); + /// + /// assert_eq!(d, &["", "", "", "", "a", "", "b", "c"]); + /// ``` + /// + /// It does _not_ give you: + /// + /// ```,ignore + /// assert_eq!(d, &["a", "b", "c"]); + /// ``` + /// + /// Use [`split_whitespace`] for this behavior. + /// + /// [`split_whitespace`]: #method.split_whitespace + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> { + StrExt::split(self, pat) + } + + /// An iterator over substrings of the given string slice, separated by + /// characters matched by a pattern and yielded in reverse order. + /// + /// The pattern can be a `&str`, [`char`], or a closure that determines the + /// split. + /// + /// [`char`]: primitive.char.html + /// + /// # Iterator behavior + /// + /// The returned iterator requires that the pattern supports a reverse + /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse + /// search yields the same elements. + /// + /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html + /// + /// For iterating from the front, the [`split`] method can be used. + /// + /// [`split`]: #method.split + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// let v: Vec<&str> = "Mary had a little lamb".rsplit(' ').collect(); + /// assert_eq!(v, ["lamb", "little", "a", "had", "Mary"]); + /// + /// let v: Vec<&str> = "".rsplit('X').collect(); + /// assert_eq!(v, [""]); + /// + /// let v: Vec<&str> = "lionXXtigerXleopard".rsplit('X').collect(); + /// assert_eq!(v, ["leopard", "tiger", "", "lion"]); + /// + /// let v: Vec<&str> = "lion::tiger::leopard".rsplit("::").collect(); + /// assert_eq!(v, ["leopard", "tiger", "lion"]); + /// ``` + /// + /// A more complex pattern, using a closure: + /// + /// ``` + /// let v: Vec<&str> = "abc1defXghi".rsplit(|c| c == '1' || c == 'X').collect(); + /// assert_eq!(v, ["ghi", "def", "abc"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn rsplit<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplit<'a, P> + where P::Searcher: ReverseSearcher<'a> + { + StrExt::rsplit(self, pat) + } + + /// An iterator over substrings of the given string slice, separated by + /// characters matched by a pattern. + /// + /// The pattern can be a `&str`, [`char`], or a closure that determines the + /// split. + /// + /// Equivalent to [`split`], except that the trailing substring + /// is skipped if empty. + /// + /// [`split`]: #method.split + /// + /// This method can be used for string data that is _terminated_, + /// rather than _separated_ by a pattern. + /// + /// # Iterator behavior + /// + /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern + /// allows a reverse search and forward/reverse search yields the same + /// elements. This is true for, eg, [`char`] but not for `&str`. + /// + /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html + /// [`char`]: primitive.char.html + /// + /// If the pattern allows a reverse search but its results might differ + /// from a forward search, the [`rsplit_terminator`] method can be used. + /// + /// [`rsplit_terminator`]: #method.rsplit_terminator + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let v: Vec<&str> = "A.B.".split_terminator('.').collect(); + /// assert_eq!(v, ["A", "B"]); + /// + /// let v: Vec<&str> = "A..B..".split_terminator(".").collect(); + /// assert_eq!(v, ["A", "", "B", ""]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator<'a, P> { + StrExt::split_terminator(self, pat) + } + + /// An iterator over substrings of `self`, separated by characters + /// matched by a pattern and yielded in reverse order. + /// + /// The pattern can be a simple `&str`, [`char`], or a closure that + /// determines the split. + /// Additional libraries might provide more complex patterns like + /// regular expressions. + /// + /// [`char`]: primitive.char.html + /// + /// Equivalent to [`split`], except that the trailing substring is + /// skipped if empty. + /// + /// [`split`]: #method.split + /// + /// This method can be used for string data that is _terminated_, + /// rather than _separated_ by a pattern. + /// + /// # Iterator behavior + /// + /// The returned iterator requires that the pattern supports a + /// reverse search, and it will be double ended if a forward/reverse + /// search yields the same elements. + /// + /// For iterating from the front, the [`split_terminator`] method can be + /// used. + /// + /// [`split_terminator`]: #method.split_terminator + /// + /// # Examples + /// + /// ``` + /// let v: Vec<&str> = "A.B.".rsplit_terminator('.').collect(); + /// assert_eq!(v, ["B", "A"]); + /// + /// let v: Vec<&str> = "A..B..".rsplit_terminator(".").collect(); + /// assert_eq!(v, ["", "B", "", "A"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn rsplit_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplitTerminator<'a, P> + where P::Searcher: ReverseSearcher<'a> + { + StrExt::rsplit_terminator(self, pat) + } + + /// An iterator over substrings of the given string slice, separated by a + /// pattern, restricted to returning at most `n` items. + /// + /// If `n` substrings are returned, the last substring (the `n`th substring) + /// will contain the remainder of the string. + /// + /// The pattern can be a `&str`, [`char`], or a closure that determines the + /// split. + /// + /// [`char`]: primitive.char.html + /// + /// # Iterator behavior + /// + /// The returned iterator will not be double ended, because it is + /// not efficient to support. + /// + /// If the pattern allows a reverse search, the [`rsplitn`] method can be + /// used. + /// + /// [`rsplitn`]: #method.rsplitn + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// let v: Vec<&str> = "Mary had a little lambda".splitn(3, ' ').collect(); + /// assert_eq!(v, ["Mary", "had", "a little lambda"]); + /// + /// let v: Vec<&str> = "lionXXtigerXleopard".splitn(3, "X").collect(); + /// assert_eq!(v, ["lion", "", "tigerXleopard"]); + /// + /// let v: Vec<&str> = "abcXdef".splitn(1, 'X').collect(); + /// assert_eq!(v, ["abcXdef"]); + /// + /// let v: Vec<&str> = "".splitn(1, 'X').collect(); + /// assert_eq!(v, [""]); + /// ``` + /// + /// A more complex pattern, using a closure: + /// + /// ``` + /// let v: Vec<&str> = "abc1defXghi".splitn(2, |c| c == '1' || c == 'X').collect(); + /// assert_eq!(v, ["abc", "defXghi"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn splitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> SplitN<'a, P> { + StrExt::splitn(self, n, pat) + } + + /// An iterator over substrings of this string slice, separated by a + /// pattern, starting from the end of the string, restricted to returning + /// at most `n` items. + /// + /// If `n` substrings are returned, the last substring (the `n`th substring) + /// will contain the remainder of the string. + /// + /// The pattern can be a `&str`, [`char`], or a closure that + /// determines the split. + /// + /// [`char`]: primitive.char.html + /// + /// # Iterator behavior + /// + /// The returned iterator will not be double ended, because it is not + /// efficient to support. + /// + /// For splitting from the front, the [`splitn`] method can be used. + /// + /// [`splitn`]: #method.splitn + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(3, ' ').collect(); + /// assert_eq!(v, ["lamb", "little", "Mary had a"]); + /// + /// let v: Vec<&str> = "lionXXtigerXleopard".rsplitn(3, 'X').collect(); + /// assert_eq!(v, ["leopard", "tiger", "lionX"]); + /// + /// let v: Vec<&str> = "lion::tiger::leopard".rsplitn(2, "::").collect(); + /// assert_eq!(v, ["leopard", "lion::tiger"]); + /// ``` + /// + /// A more complex pattern, using a closure: + /// + /// ``` + /// let v: Vec<&str> = "abc1defXghi".rsplitn(2, |c| c == '1' || c == 'X').collect(); + /// assert_eq!(v, ["ghi", "abc1def"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn rsplitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> RSplitN<'a, P> + where P::Searcher: ReverseSearcher<'a> + { + StrExt::rsplitn(self, n, pat) + } + + /// An iterator over the disjoint matches of a pattern within the given string + /// slice. + /// + /// The pattern can be a `&str`, [`char`], or a closure that + /// determines if a character matches. + /// + /// [`char`]: primitive.char.html + /// + /// # Iterator behavior + /// + /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern + /// allows a reverse search and forward/reverse search yields the same + /// elements. This is true for, eg, [`char`] but not for `&str`. + /// + /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html + /// [`char`]: primitive.char.html + /// + /// If the pattern allows a reverse search but its results might differ + /// from a forward search, the [`rmatches`] method can be used. + /// + /// [`rmatches`]: #method.rmatches + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let v: Vec<&str> = "abcXXXabcYYYabc".matches("abc").collect(); + /// assert_eq!(v, ["abc", "abc", "abc"]); + /// + /// let v: Vec<&str> = "1abc2abc3".matches(char::is_numeric).collect(); + /// assert_eq!(v, ["1", "2", "3"]); + /// ``` + #[stable(feature = "str_matches", since = "1.2.0")] + #[inline] + pub fn matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> Matches<'a, P> { + StrExt::matches(self, pat) + } + + /// An iterator over the disjoint matches of a pattern within this string slice, + /// yielded in reverse order. + /// + /// The pattern can be a `&str`, [`char`], or a closure that determines if + /// a character matches. + /// + /// [`char`]: primitive.char.html + /// + /// # Iterator behavior + /// + /// The returned iterator requires that the pattern supports a reverse + /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse + /// search yields the same elements. + /// + /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html + /// + /// For iterating from the front, the [`matches`] method can be used. + /// + /// [`matches`]: #method.matches + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let v: Vec<&str> = "abcXXXabcYYYabc".rmatches("abc").collect(); + /// assert_eq!(v, ["abc", "abc", "abc"]); + /// + /// let v: Vec<&str> = "1abc2abc3".rmatches(char::is_numeric).collect(); + /// assert_eq!(v, ["3", "2", "1"]); + /// ``` + #[stable(feature = "str_matches", since = "1.2.0")] + #[inline] + pub fn rmatches<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatches<'a, P> + where P::Searcher: ReverseSearcher<'a> + { + StrExt::rmatches(self, pat) + } + + /// An iterator over the disjoint matches of a pattern within this string + /// slice as well as the index that the match starts at. + /// + /// For matches of `pat` within `self` that overlap, only the indices + /// corresponding to the first match are returned. + /// + /// The pattern can be a `&str`, [`char`], or a closure that determines + /// if a character matches. + /// + /// [`char`]: primitive.char.html + /// + /// # Iterator behavior + /// + /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern + /// allows a reverse search and forward/reverse search yields the same + /// elements. This is true for, eg, [`char`] but not for `&str`. + /// + /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html + /// + /// If the pattern allows a reverse search but its results might differ + /// from a forward search, the [`rmatch_indices`] method can be used. + /// + /// [`rmatch_indices`]: #method.rmatch_indices + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let v: Vec<_> = "abcXXXabcYYYabc".match_indices("abc").collect(); + /// assert_eq!(v, [(0, "abc"), (6, "abc"), (12, "abc")]); + /// + /// let v: Vec<_> = "1abcabc2".match_indices("abc").collect(); + /// assert_eq!(v, [(1, "abc"), (4, "abc")]); + /// + /// let v: Vec<_> = "ababa".match_indices("aba").collect(); + /// assert_eq!(v, [(0, "aba")]); // only the first `aba` + /// ``` + #[stable(feature = "str_match_indices", since = "1.5.0")] + #[inline] + pub fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P> { + StrExt::match_indices(self, pat) + } + + /// An iterator over the disjoint matches of a pattern within `self`, + /// yielded in reverse order along with the index of the match. + /// + /// For matches of `pat` within `self` that overlap, only the indices + /// corresponding to the last match are returned. + /// + /// The pattern can be a `&str`, [`char`], or a closure that determines if a + /// character matches. + /// + /// [`char`]: primitive.char.html + /// + /// # Iterator behavior + /// + /// The returned iterator requires that the pattern supports a reverse + /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse + /// search yields the same elements. + /// + /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html + /// + /// For iterating from the front, the [`match_indices`] method can be used. + /// + /// [`match_indices`]: #method.match_indices + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let v: Vec<_> = "abcXXXabcYYYabc".rmatch_indices("abc").collect(); + /// assert_eq!(v, [(12, "abc"), (6, "abc"), (0, "abc")]); + /// + /// let v: Vec<_> = "1abcabc2".rmatch_indices("abc").collect(); + /// assert_eq!(v, [(4, "abc"), (1, "abc")]); + /// + /// let v: Vec<_> = "ababa".rmatch_indices("aba").collect(); + /// assert_eq!(v, [(2, "aba")]); // only the last `aba` + /// ``` + #[stable(feature = "str_match_indices", since = "1.5.0")] + #[inline] + pub fn rmatch_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatchIndices<'a, P> + where P::Searcher: ReverseSearcher<'a> + { + StrExt::rmatch_indices(self, pat) + } + + /// Returns a string slice with leading and trailing whitespace removed. + /// + /// 'Whitespace' is defined according to the terms of the Unicode Derived + /// Core Property `White_Space`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = " Hello\tworld\t"; + /// + /// assert_eq!("Hello\tworld", s.trim()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn trim(&self) -> &str { + StrExt::trim(self) + } + + /// Returns a string slice with leading whitespace removed. + /// + /// 'Whitespace' is defined according to the terms of the Unicode Derived + /// Core Property `White_Space`. + /// + /// # Text directionality + /// + /// A string is a sequence of bytes. 'Left' in this context means the first + /// position of that byte string; for a language like Arabic or Hebrew + /// which are 'right to left' rather than 'left to right', this will be + /// the _right_ side, not the left. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = " Hello\tworld\t"; + /// + /// assert_eq!("Hello\tworld\t", s.trim_left()); + /// ``` + /// + /// Directionality: + /// + /// ``` + /// let s = " English"; + /// assert!(Some('E') == s.trim_left().chars().next()); + /// + /// let s = " עברית"; + /// assert!(Some('ע') == s.trim_left().chars().next()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn trim_left(&self) -> &str { + StrExt::trim_left(self) + } + + /// Returns a string slice with trailing whitespace removed. + /// + /// 'Whitespace' is defined according to the terms of the Unicode Derived + /// Core Property `White_Space`. + /// + /// # Text directionality + /// + /// A string is a sequence of bytes. 'Right' in this context means the last + /// position of that byte string; for a language like Arabic or Hebrew + /// which are 'right to left' rather than 'left to right', this will be + /// the _left_ side, not the right. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = " Hello\tworld\t"; + /// + /// assert_eq!(" Hello\tworld", s.trim_right()); + /// ``` + /// + /// Directionality: + /// + /// ``` + /// let s = "English "; + /// assert!(Some('h') == s.trim_right().chars().rev().next()); + /// + /// let s = "עברית "; + /// assert!(Some('ת') == s.trim_right().chars().rev().next()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn trim_right(&self) -> &str { + StrExt::trim_right(self) + } + + /// Returns a string slice with all prefixes and suffixes that match a + /// pattern repeatedly removed. + /// + /// The pattern can be a [`char`] or a closure that determines if a + /// character matches. + /// + /// [`char`]: primitive.char.html + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar"); + /// assert_eq!("123foo1bar123".trim_matches(char::is_numeric), "foo1bar"); + /// + /// let x: &[_] = &['1', '2']; + /// assert_eq!("12foo1bar12".trim_matches(x), "foo1bar"); + /// ``` + /// + /// A more complex pattern, using a closure: + /// + /// ``` + /// assert_eq!("1foo1barXX".trim_matches(|c| c == '1' || c == 'X'), "foo1bar"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn trim_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str + where P::Searcher: DoubleEndedSearcher<'a> + { + StrExt::trim_matches(self, pat) + } + + /// Returns a string slice with all prefixes that match a pattern + /// repeatedly removed. + /// + /// The pattern can be a `&str`, [`char`], or a closure that determines if + /// a character matches. + /// + /// [`char`]: primitive.char.html + /// + /// # Text directionality + /// + /// A string is a sequence of bytes. 'Left' in this context means the first + /// position of that byte string; for a language like Arabic or Hebrew + /// which are 'right to left' rather than 'left to right', this will be + /// the _right_ side, not the left. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11"); + /// assert_eq!("123foo1bar123".trim_left_matches(char::is_numeric), "foo1bar123"); + /// + /// let x: &[_] = &['1', '2']; + /// assert_eq!("12foo1bar12".trim_left_matches(x), "foo1bar12"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str { + StrExt::trim_left_matches(self, pat) + } + + /// Returns a string slice with all suffixes that match a pattern + /// repeatedly removed. + /// + /// The pattern can be a `&str`, [`char`], or a closure that + /// determines if a character matches. + /// + /// [`char`]: primitive.char.html + /// + /// # Text directionality + /// + /// A string is a sequence of bytes. 'Right' in this context means the last + /// position of that byte string; for a language like Arabic or Hebrew + /// which are 'right to left' rather than 'left to right', this will be + /// the _left_ side, not the right. + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar"); + /// assert_eq!("123foo1bar123".trim_right_matches(char::is_numeric), "123foo1bar"); + /// + /// let x: &[_] = &['1', '2']; + /// assert_eq!("12foo1bar12".trim_right_matches(x), "12foo1bar"); + /// ``` + /// + /// A more complex pattern, using a closure: + /// + /// ``` + /// assert_eq!("1fooX".trim_right_matches(|c| c == '1' || c == 'X'), "1foo"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str + where P::Searcher: ReverseSearcher<'a> + { + StrExt::trim_right_matches(self, pat) + } + + /// Parses this string slice into another type. + /// + /// Because `parse` is so general, it can cause problems with type + /// inference. As such, `parse` is one of the few times you'll see + /// the syntax affectionately known as the 'turbofish': `::<>`. This + /// helps the inference algorithm understand specifically which type + /// you're trying to parse into. + /// + /// `parse` can parse any type that implements the [`FromStr`] trait. + /// + /// [`FromStr`]: str/trait.FromStr.html + /// + /// # Errors + /// + /// Will return [`Err`] if it's not possible to parse this string slice into + /// the desired type. + /// + /// [`Err`]: str/trait.FromStr.html#associatedtype.Err + /// + /// # Examples + /// + /// Basic usage + /// + /// ``` + /// let four: u32 = "4".parse().unwrap(); + /// + /// assert_eq!(4, four); + /// ``` + /// + /// Using the 'turbofish' instead of annotating `four`: + /// + /// ``` + /// let four = "4".parse::<u32>(); + /// + /// assert_eq!(Ok(4), four); + /// ``` + /// + /// Failing to parse: + /// + /// ``` + /// let nope = "j".parse::<u32>(); + /// + /// assert!(nope.is_err()); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn parse<F: FromStr>(&self) -> Result<F, F::Err> { + StrExt::parse(self) + } + + /// Checks if all characters in this string are within the ASCII range. + /// + /// # Examples + /// + /// ``` + /// let ascii = "hello!\n"; + /// let non_ascii = "Grüße, Jürgen ❤"; + /// + /// assert!(ascii.is_ascii()); + /// assert!(!non_ascii.is_ascii()); + /// ``` + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[inline] + pub fn is_ascii(&self) -> bool { + // We can treat each byte as character here: all multibyte characters + // start with a byte that is not in the ascii range, so we will stop + // there already. + self.bytes().all(|b| b.is_ascii()) + } + + /// Checks that two strings are an ASCII case-insensitive match. + /// + /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`, + /// but without allocating and copying temporaries. + /// + /// # Examples + /// + /// ``` + /// assert!("Ferris".eq_ignore_ascii_case("FERRIS")); + /// assert!("Ferrös".eq_ignore_ascii_case("FERRöS")); + /// assert!(!"Ferrös".eq_ignore_ascii_case("FERRÖS")); + /// ``` + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[inline] + pub fn eq_ignore_ascii_case(&self, other: &str) -> bool { + self.as_bytes().eq_ignore_ascii_case(other.as_bytes()) + } + + /// Converts this string to its ASCII upper case equivalent in-place. + /// + /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', + /// but non-ASCII letters are unchanged. + /// + /// To return a new uppercased value without modifying the existing one, use + /// [`to_ascii_uppercase`]. + /// + /// [`to_ascii_uppercase`]: #method.to_ascii_uppercase + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + pub fn make_ascii_uppercase(&mut self) { + let me = unsafe { self.as_bytes_mut() }; + me.make_ascii_uppercase() + } + + /// Converts this string to its ASCII lower case equivalent in-place. + /// + /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', + /// but non-ASCII letters are unchanged. + /// + /// To return a new lowercased value without modifying the existing one, use + /// [`to_ascii_lowercase`]. + /// + /// [`to_ascii_lowercase`]: #method.to_ascii_lowercase + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + pub fn make_ascii_lowercase(&mut self) { + let me = unsafe { self.as_bytes_mut() }; + me.make_ascii_lowercase() + } +}} + +#[lang = "str"] +#[cfg(not(test))] +#[cfg(not(stage0))] +impl str { + str_core_methods!(); +} + + #[stable(feature = "rust1", since = "1.0.0")] impl AsRef<[u8]> for str { #[inline] @@ -2665,3 +4327,72 @@ impl<'a> DoubleEndedIterator for SplitWhitespace<'a> { #[stable(feature = "fused", since = "1.26.0")] impl<'a> FusedIterator for SplitWhitespace<'a> {} + +/// An iterator of [`u16`] over the string encoded as UTF-16. +/// +/// [`u16`]: ../../std/primitive.u16.html +/// +/// This struct is created by the [`encode_utf16`] method on [`str`]. +/// See its documentation for more. +/// +/// [`encode_utf16`]: ../../std/primitive.str.html#method.encode_utf16 +/// [`str`]: ../../std/primitive.str.html +#[derive(Clone)] +#[stable(feature = "encode_utf16", since = "1.8.0")] +pub struct EncodeUtf16<'a> { + chars: Chars<'a>, + extra: u16, +} + +// FIXME: remove (inline) this method +// when updating to a bootstrap compiler that has the new lang items. +// For grepping purpose: #[cfg(stage0)] +impl<'a> EncodeUtf16<'a> { + #[unstable(feature = "core_str_ext", issue = "32110")] + #[doc(hidden)] + pub fn new(s: &'a str) -> Self { + EncodeUtf16 { chars: s.chars(), extra: 0 } + } +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl<'a> fmt::Debug for EncodeUtf16<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("EncodeUtf16 { .. }") + } +} + +#[stable(feature = "encode_utf16", since = "1.8.0")] +impl<'a> Iterator for EncodeUtf16<'a> { + type Item = u16; + + #[inline] + fn next(&mut self) -> Option<u16> { + if self.extra != 0 { + let tmp = self.extra; + self.extra = 0; + return Some(tmp); + } + + let mut buf = [0; 2]; + self.chars.next().map(|ch| { + let n = ch.encode_utf16(&mut buf).len(); + if n == 2 { + self.extra = buf[1]; + } + buf[0] + }) + } + + #[inline] + fn size_hint(&self) -> (usize, Option<usize>) { + let (low, high) = self.chars.size_hint(); + // every char gets either one u16 or two u16, + // so this iterator is between 1 or 2 times as + // long as the underlying iterator. + (low, high.and_then(|n| n.checked_mul(2))) + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl<'a> FusedIterator for EncodeUtf16<'a> {} diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index cf3842dbe27..7aba8b51cff 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -990,9 +990,7 @@ macro_rules! atomic_int { #[$stable_debug] impl fmt::Debug for $atomic_type { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_tuple(stringify!($atomic_type)) - .field(&self.load(Ordering::SeqCst)) - .finish() + fmt::Debug::fmt(&self.load(Ordering::SeqCst), f) } } @@ -2090,7 +2088,7 @@ pub fn compiler_fence(order: Ordering) { #[stable(feature = "atomic_debug", since = "1.3.0")] impl fmt::Debug for AtomicBool { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_tuple("AtomicBool").field(&self.load(Ordering::SeqCst)).finish() + fmt::Debug::fmt(&self.load(Ordering::SeqCst), f) } } @@ -2098,7 +2096,7 @@ impl fmt::Debug for AtomicBool { #[stable(feature = "atomic_debug", since = "1.3.0")] impl<T> fmt::Debug for AtomicPtr<T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_tuple("AtomicPtr").field(&self.load(Ordering::SeqCst)).finish() + fmt::Debug::fmt(&self.load(Ordering::SeqCst), f) } } diff --git a/src/libcore/tests/cell.rs b/src/libcore/tests/cell.rs index cc0ef6a6f17..962fb2f0e02 100644 --- a/src/libcore/tests/cell.rs +++ b/src/libcore/tests/cell.rs @@ -27,6 +27,17 @@ fn smoketest_cell() { } #[test] +fn cell_update() { + let x = Cell::new(10); + + assert_eq!(x.update(|x| x + 5), 15); + assert_eq!(x.get(), 15); + + assert_eq!(x.update(|x| x / 3), 5); + assert_eq!(x.get(), 5); +} + +#[test] fn cell_has_sensible_show() { let x = Cell::new("foo bar"); assert!(format!("{:?}", x).contains(x.get())); diff --git a/src/libcore/tests/char.rs b/src/libcore/tests/char.rs index 4e10ceac878..ab90763abf8 100644 --- a/src/libcore/tests/char.rs +++ b/src/libcore/tests/char.rs @@ -364,6 +364,7 @@ fn eu_iterator_specializations() { } #[test] +#[allow(deprecated)] fn test_decode_utf8() { macro_rules! assert_decode_utf8 { ($input_bytes: expr, $expected_str: expr) => { diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index bb875c7219a..e4d27717938 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -10,13 +10,16 @@ #![feature(ascii_ctype)] #![feature(box_syntax)] +#![feature(cell_update)] #![feature(core_float)] #![feature(core_private_bignum)] #![feature(core_private_diy_float)] #![feature(dec2flt)] #![feature(decode_utf8)] +#![feature(euclidean_division)] #![feature(exact_size_is_empty)] #![feature(fixed_size_array)] +#![feature(float_internals)] #![feature(flt2dec)] #![feature(fmt_internals)] #![feature(hashmap_internals)] @@ -36,6 +39,7 @@ #![feature(str_internals)] #![feature(test)] #![feature(trusted_len)] +#![feature(try_from)] #![feature(try_trait)] #![feature(exact_chunks)] #![cfg_attr(stage0, feature(atomic_nand))] diff --git a/src/libcore/tests/num/int_macros.rs b/src/libcore/tests/num/int_macros.rs index 8d791283ab8..71d2e794538 100644 --- a/src/libcore/tests/num/int_macros.rs +++ b/src/libcore/tests/num/int_macros.rs @@ -31,6 +31,11 @@ mod tests { } #[test] + fn test_mod_euc() { + assert!((-1 as $T).mod_euc(MIN) == MAX); + } + + #[test] pub fn test_abs() { assert!((1 as $T).abs() == 1 as $T); assert!((0 as $T).abs() == 0 as $T); diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 1b907073238..18bf54297af 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -556,7 +556,6 @@ define_dep_nodes!( <'tcx> [input] DefSpan(DefId), [] LookupStability(DefId), [] LookupDeprecationEntry(DefId), - [] ItemBodyNestedBodies(DefId), [] ConstIsRvaluePromotableToStatic(DefId), [] RvaluePromotableMap(DefId), [] ImplParent(DefId), @@ -567,6 +566,7 @@ define_dep_nodes!( <'tcx> [] ItemAttrs(DefId), [] TransFnAttrs(DefId), [] FnArgNames(DefId), + [] RenderedConst(DefId), [] DylibDepFormats(CrateNum), [] IsPanicRuntime(CrateNum), [] IsCompilerBuiltins(CrateNum), @@ -615,7 +615,6 @@ define_dep_nodes!( <'tcx> [input] GetLangItems, [] DefinedLangItems(CrateNum), [] MissingLangItems(CrateNum), - [] ExternConstBody(DefId), [] VisibleParentMap, [input] MissingExternCrateItem(CrateNum), [input] UsedCrateSource(CrateNum), @@ -656,6 +655,7 @@ define_dep_nodes!( <'tcx> [input] Features, [] ProgramClausesFor(DefId), + [] ProgramClausesForEnv(ParamEnv<'tcx>), [] WasmImportModuleMap(CrateNum), [] ForeignModules(CrateNum), diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index d60c22064d3..22ab1b15c8b 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -12,11 +12,10 @@ use errors::DiagnosticBuilder; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; -use rustc_data_structures::sync::Lrc; -use std::cell::{Ref, RefCell}; +use rustc_data_structures::sync::{Lrc, RwLock, ReadGuard, Lock}; use std::env; use std::hash::Hash; -use ty::TyCtxt; +use ty::{self, TyCtxt}; use util::common::{ProfileQueriesMsg, profq_msg}; use ich::{StableHashingContext, StableHashingContextProvider, Fingerprint}; @@ -24,7 +23,6 @@ use ich::{StableHashingContext, StableHashingContextProvider, Fingerprint}; use super::debug::EdgeFilter; use super::dep_node::{DepNode, DepKind, WorkProductId}; use super::query::DepGraphQuery; -use super::raii; use super::safe::DepGraphSafe; use super::serialized::{SerializedDepGraph, SerializedDepNodeIndex}; use super::prev::PreviousDepGraph; @@ -37,7 +35,7 @@ pub struct DepGraph { // result value fingerprints. Do not rely on the length of this vector // being the same as the number of nodes in the graph. The vector can // contain an arbitrary number of zero-entries at the end. - fingerprints: Lrc<RefCell<IndexVec<DepNodeIndex, Fingerprint>>> + fingerprints: Lrc<Lock<IndexVec<DepNodeIndex, Fingerprint>>> } @@ -67,27 +65,27 @@ struct DepGraphData { /// tracking. The `current` field is the dependency graph of only the /// current compilation session: We don't merge the previous dep-graph into /// current one anymore. - current: RefCell<CurrentDepGraph>, + current: Lock<CurrentDepGraph>, /// The dep-graph from the previous compilation session. It contains all /// nodes and edges as well as all fingerprints of nodes that have them. previous: PreviousDepGraph, - colors: RefCell<DepNodeColorMap>, + colors: Lock<DepNodeColorMap>, /// When we load, there may be `.o` files, cached mir, or other such /// things available to us. If we find that they are not dirty, we /// load the path to the file storing those work-products here into /// this map. We can later look for and extract that data. - previous_work_products: RefCell<FxHashMap<WorkProductId, WorkProduct>>, + previous_work_products: RwLock<FxHashMap<WorkProductId, WorkProduct>>, /// Work-products that we generate in this run. - work_products: RefCell<FxHashMap<WorkProductId, WorkProduct>>, + work_products: RwLock<FxHashMap<WorkProductId, WorkProduct>>, - dep_node_debug: RefCell<FxHashMap<DepNode, String>>, + dep_node_debug: Lock<FxHashMap<DepNode, String>>, // Used for testing, only populated when -Zquery-dep-graph is specified. - loaded_from_cache: RefCell<FxHashMap<DepNodeIndex, bool>>, + loaded_from_cache: Lock<FxHashMap<DepNodeIndex, bool>>, } impl DepGraph { @@ -102,22 +100,22 @@ impl DepGraph { (prev_graph_node_count * 115) / 100); DepGraph { data: Some(Lrc::new(DepGraphData { - previous_work_products: RefCell::new(FxHashMap()), - work_products: RefCell::new(FxHashMap()), - dep_node_debug: RefCell::new(FxHashMap()), - current: RefCell::new(CurrentDepGraph::new()), + previous_work_products: RwLock::new(FxHashMap()), + work_products: RwLock::new(FxHashMap()), + dep_node_debug: Lock::new(FxHashMap()), + current: Lock::new(CurrentDepGraph::new()), previous: prev_graph, - colors: RefCell::new(DepNodeColorMap::new(prev_graph_node_count)), - loaded_from_cache: RefCell::new(FxHashMap()), + colors: Lock::new(DepNodeColorMap::new(prev_graph_node_count)), + loaded_from_cache: Lock::new(FxHashMap()), })), - fingerprints: Lrc::new(RefCell::new(fingerprints)), + fingerprints: Lrc::new(Lock::new(fingerprints)), } } pub fn new_disabled() -> DepGraph { DepGraph { data: None, - fingerprints: Lrc::new(RefCell::new(IndexVec::new())), + fingerprints: Lrc::new(Lock::new(IndexVec::new())), } } @@ -144,21 +142,32 @@ impl DepGraph { pub fn assert_ignored(&self) { - if let Some(ref data) = self.data { - match data.current.borrow().task_stack.last() { - Some(&OpenTask::Ignore) | None => { - // ignored + if let Some(..) = self.data { + ty::tls::with_context_opt(|icx| { + let icx = if let Some(icx) = icx { icx } else { return }; + match *icx.task { + OpenTask::Ignore => { + // ignored + } + _ => panic!("expected an ignore context") } - _ => panic!("expected an ignore context") - } + }) } } pub fn with_ignore<OP,R>(&self, op: OP) -> R where OP: FnOnce() -> R { - let _task = self.data.as_ref().map(|data| raii::IgnoreTask::new(&data.current)); - op() + ty::tls::with_context(|icx| { + let icx = ty::tls::ImplicitCtxt { + task: &OpenTask::Ignore, + ..icx.clone() + }; + + ty::tls::enter_context(&icx, |_| { + op() + }) + }) } /// Starts a new dep-graph task. Dep-graph tasks are specified @@ -197,24 +206,51 @@ impl DepGraph { where C: DepGraphSafe + StableHashingContextProvider<'gcx>, R: HashStable<StableHashingContext<'gcx>>, { - self.with_task_impl(key, cx, arg, task, - |data, key| data.borrow_mut().push_task(key), - |data, key| data.borrow_mut().pop_task(key)) + self.with_task_impl(key, cx, arg, false, task, + |key| OpenTask::Regular(Lock::new(RegularOpenTask { + node: key, + reads: Vec::new(), + read_set: FxHashSet(), + })), + |data, key, task| data.borrow_mut().complete_task(key, task)) } - fn with_task_impl<'gcx, C, A, R>(&self, - key: DepNode, - cx: C, - arg: A, - task: fn(C, A) -> R, - push: fn(&RefCell<CurrentDepGraph>, DepNode), - pop: fn(&RefCell<CurrentDepGraph>, DepNode) -> DepNodeIndex) - -> (R, DepNodeIndex) + /// Creates a new dep-graph input with value `input` + pub fn input_task<'gcx, C, R>(&self, + key: DepNode, + cx: C, + input: R) + -> (R, DepNodeIndex) where C: DepGraphSafe + StableHashingContextProvider<'gcx>, R: HashStable<StableHashingContext<'gcx>>, { + fn identity_fn<C, A>(_: C, arg: A) -> A { + arg + } + + self.with_task_impl(key, cx, input, true, identity_fn, + |_| OpenTask::Ignore, + |data, key, _| data.borrow_mut().alloc_node(key, Vec::new())) + } + + fn with_task_impl<'gcx, C, A, R>( + &self, + key: DepNode, + cx: C, + arg: A, + no_tcx: bool, + task: fn(C, A) -> R, + create_task: fn(DepNode) -> OpenTask, + finish_task_and_alloc_depnode: fn(&Lock<CurrentDepGraph>, + DepNode, + OpenTask) -> DepNodeIndex + ) -> (R, DepNodeIndex) + where + C: DepGraphSafe + StableHashingContextProvider<'gcx>, + R: HashStable<StableHashingContext<'gcx>>, + { if let Some(ref data) = self.data { - push(&data.current, key); + let open_task = create_task(key); // In incremental mode, hash the result of the task. We don't // do anything with the hash yet, but we are computing it @@ -227,13 +263,26 @@ impl DepGraph { profq_msg(hcx.sess(), ProfileQueriesMsg::TaskBegin(key.clone())) }; - let result = task(cx, arg); + let result = if no_tcx { + task(cx, arg) + } else { + ty::tls::with_context(|icx| { + let icx = ty::tls::ImplicitCtxt { + task: &open_task, + ..icx.clone() + }; + + ty::tls::enter_context(&icx, |_| { + task(cx, arg) + }) + }) + }; if cfg!(debug_assertions) { profq_msg(hcx.sess(), ProfileQueriesMsg::TaskEnd) }; - let dep_node_index = pop(&data.current, key); + let dep_node_index = finish_task_and_alloc_depnode(&data.current, key, open_task); let mut stable_hasher = StableHasher::new(); result.hash_stable(&mut hcx, &mut stable_hasher); @@ -302,11 +351,28 @@ impl DepGraph { where OP: FnOnce() -> R { if let Some(ref data) = self.data { - data.current.borrow_mut().push_anon_task(); - let result = op(); + let (result, open_task) = ty::tls::with_context(|icx| { + let task = OpenTask::Anon(Lock::new(AnonOpenTask { + reads: Vec::new(), + read_set: FxHashSet(), + })); + + let r = { + let icx = ty::tls::ImplicitCtxt { + task: &task, + ..icx.clone() + }; + + ty::tls::enter_context(&icx, |_| { + op() + }) + }; + + (r, task) + }); let dep_node_index = data.current .borrow_mut() - .pop_anon_task(dep_kind); + .pop_anon_task(dep_kind, open_task); (result, dep_node_index) } else { (op(), DepNodeIndex::INVALID) @@ -324,9 +390,9 @@ impl DepGraph { where C: DepGraphSafe + StableHashingContextProvider<'gcx>, R: HashStable<StableHashingContext<'gcx>>, { - self.with_task_impl(key, cx, arg, task, - |data, key| data.borrow_mut().push_eval_always_task(key), - |data, key| data.borrow_mut().pop_eval_always_task(key)) + self.with_task_impl(key, cx, arg, false, task, + |key| OpenTask::EvalAlways { node: key }, + |data, key, task| data.borrow_mut().complete_eval_always_task(key, task)) } #[inline] @@ -432,13 +498,13 @@ impl DepGraph { /// Access the map of work-products created during this run. Only /// used during saving of the dep-graph. - pub fn work_products(&self) -> Ref<FxHashMap<WorkProductId, WorkProduct>> { + pub fn work_products(&self) -> ReadGuard<FxHashMap<WorkProductId, WorkProduct>> { self.data.as_ref().unwrap().work_products.borrow() } /// Access the map of work-products created during the cached run. Only /// used during saving of the dep-graph. - pub fn previous_work_products(&self) -> Ref<FxHashMap<WorkProductId, WorkProduct>> { + pub fn previous_work_products(&self) -> ReadGuard<FxHashMap<WorkProductId, WorkProduct>> { self.data.as_ref().unwrap().previous_work_products.borrow() } @@ -528,6 +594,7 @@ impl DepGraph { debug!("try_mark_green({:?}) - BEGIN", dep_node); let data = self.data.as_ref().unwrap(); + #[cfg(not(parallel_queries))] debug_assert!(!data.current.borrow().node_to_node_index.contains_key(dep_node)); if dep_node.kind.is_input() { @@ -668,16 +735,24 @@ impl DepGraph { } } - // If we got here without hitting a `return` that means that all // dependencies of this DepNode could be marked as green. Therefore we - // can also mark this DepNode as green. We do so by... + // can also mark this DepNode as green. - // ... allocating an entry for it in the current dependency graph and - // adding all the appropriate edges imported from the previous graph ... - let dep_node_index = data.current - .borrow_mut() - .alloc_node(*dep_node, current_deps); + // There may be multiple threads trying to mark the same dep node green concurrently + + let (dep_node_index, did_allocation) = { + let mut current = data.current.borrow_mut(); + + if let Some(&dep_node_index) = current.node_to_node_index.get(&dep_node) { + // Someone else allocated it before us + (dep_node_index, false) + } else { + // We allocating an entry for the node in the current dependency graph and + // adding all the appropriate edges imported from the previous graph + (current.alloc_node(*dep_node, current_deps), true) + } + }; // ... copying the fingerprint from the previous graph too, so we don't // have to recompute it ... @@ -689,6 +764,8 @@ impl DepGraph { fingerprints.resize(dep_node_index.index() + 1, Fingerprint::ZERO); } + // Multiple threads can all write the same fingerprint here + #[cfg(not(parallel_queries))] debug_assert!(fingerprints[dep_node_index] == Fingerprint::ZERO, "DepGraph::try_mark_green() - Duplicate fingerprint \ insertion for {:?}", dep_node); @@ -697,7 +774,14 @@ impl DepGraph { } // ... emitting any stored diagnostic ... - { + if did_allocation { + // Only the thread which did the allocation emits the error messages + + // FIXME: Ensure that these are printed before returning for all threads. + // Currently threads where did_allocation = false can continue on + // and emit other diagnostics before these diagnostics are emitted. + // Such diagnostics should be emitted after these. + // See https://github.com/rust-lang/rust/issues/48685 let diagnostics = tcx.on_disk_query_result_cache .load_diagnostics(tcx, prev_dep_node_index); @@ -716,6 +800,8 @@ impl DepGraph { // ... and finally storing a "Green" entry in the color map. let mut colors = data.colors.borrow_mut(); + // Multiple threads can all write the same color here + #[cfg(not(parallel_queries))] debug_assert!(colors.get(prev_dep_node_index).is_none(), "DepGraph::try_mark_green() - Duplicate DepNodeColor \ insertion for {:?}", dep_node); @@ -839,7 +925,6 @@ pub(super) struct CurrentDepGraph { nodes: IndexVec<DepNodeIndex, DepNode>, edges: IndexVec<DepNodeIndex, Vec<DepNodeIndex>>, node_to_node_index: FxHashMap<DepNode, DepNodeIndex>, - task_stack: Vec<OpenTask>, forbidden_edge: Option<EdgeFilter>, // Anonymous DepNodes are nodes the ID of which we compute from the list of @@ -888,38 +973,19 @@ impl CurrentDepGraph { edges: IndexVec::new(), node_to_node_index: FxHashMap(), anon_id_seed: stable_hasher.finish(), - task_stack: Vec::new(), forbidden_edge, total_read_count: 0, total_duplicate_read_count: 0, } } - pub(super) fn push_ignore(&mut self) { - self.task_stack.push(OpenTask::Ignore); - } - - pub(super) fn pop_ignore(&mut self) { - let popped_node = self.task_stack.pop().unwrap(); - debug_assert_eq!(popped_node, OpenTask::Ignore); - } - - pub(super) fn push_task(&mut self, key: DepNode) { - self.task_stack.push(OpenTask::Regular { - node: key, - reads: Vec::new(), - read_set: FxHashSet(), - }); - } - - pub(super) fn pop_task(&mut self, key: DepNode) -> DepNodeIndex { - let popped_node = self.task_stack.pop().unwrap(); - - if let OpenTask::Regular { - node, - read_set: _, - reads - } = popped_node { + fn complete_task(&mut self, key: DepNode, task: OpenTask) -> DepNodeIndex { + if let OpenTask::Regular(task) = task { + let RegularOpenTask { + node, + read_set: _, + reads + } = task.into_inner(); assert_eq!(node, key); // If this is an input node, we expect that it either has no @@ -946,24 +1012,16 @@ impl CurrentDepGraph { self.alloc_node(node, reads) } else { - bug!("pop_task() - Expected regular task to be popped") + bug!("complete_task() - Expected regular task to be popped") } } - fn push_anon_task(&mut self) { - self.task_stack.push(OpenTask::Anon { - reads: Vec::new(), - read_set: FxHashSet(), - }); - } - - fn pop_anon_task(&mut self, kind: DepKind) -> DepNodeIndex { - let popped_node = self.task_stack.pop().unwrap(); - - if let OpenTask::Anon { - read_set: _, - reads - } = popped_node { + fn pop_anon_task(&mut self, kind: DepKind, task: OpenTask) -> DepNodeIndex { + if let OpenTask::Anon(task) = task { + let AnonOpenTask { + read_set: _, + reads + } = task.into_inner(); debug_assert!(!kind.is_input()); let mut fingerprint = self.anon_id_seed; @@ -997,62 +1055,54 @@ impl CurrentDepGraph { } } - fn push_eval_always_task(&mut self, key: DepNode) { - self.task_stack.push(OpenTask::EvalAlways { node: key }); - } - - fn pop_eval_always_task(&mut self, key: DepNode) -> DepNodeIndex { - let popped_node = self.task_stack.pop().unwrap(); - + fn complete_eval_always_task(&mut self, key: DepNode, task: OpenTask) -> DepNodeIndex { if let OpenTask::EvalAlways { node, - } = popped_node { + } = task { debug_assert_eq!(node, key); let krate_idx = self.node_to_node_index[&DepNode::new_no_params(DepKind::Krate)]; self.alloc_node(node, vec![krate_idx]) } else { - bug!("pop_eval_always_task() - Expected eval always task to be popped"); + bug!("complete_eval_always_task() - Expected eval always task to be popped"); } } fn read_index(&mut self, source: DepNodeIndex) { - match self.task_stack.last_mut() { - Some(&mut OpenTask::Regular { - ref mut reads, - ref mut read_set, - node: ref target, - }) => { - self.total_read_count += 1; - if read_set.insert(source) { - reads.push(source); - - if cfg!(debug_assertions) { - if let Some(ref forbidden_edge) = self.forbidden_edge { - let source = self.nodes[source]; - if forbidden_edge.test(&source, &target) { - bug!("forbidden edge {:?} -> {:?} created", - source, - target) + ty::tls::with_context_opt(|icx| { + let icx = if let Some(icx) = icx { icx } else { return }; + match *icx.task { + OpenTask::Regular(ref task) => { + let mut task = task.lock(); + self.total_read_count += 1; + if task.read_set.insert(source) { + task.reads.push(source); + + if cfg!(debug_assertions) { + if let Some(ref forbidden_edge) = self.forbidden_edge { + let target = &task.node; + let source = self.nodes[source]; + if forbidden_edge.test(&source, &target) { + bug!("forbidden edge {:?} -> {:?} created", + source, + target) + } } } + } else { + self.total_duplicate_read_count += 1; } - } else { - self.total_duplicate_read_count += 1; } - } - Some(&mut OpenTask::Anon { - ref mut reads, - ref mut read_set, - }) => { - if read_set.insert(source) { - reads.push(source); + OpenTask::Anon(ref task) => { + let mut task = task.lock(); + if task.read_set.insert(source) { + task.reads.push(source); + } + } + OpenTask::Ignore | OpenTask::EvalAlways { .. } => { + // ignore } } - Some(&mut OpenTask::Ignore) | - Some(&mut OpenTask::EvalAlways { .. }) | None => { - // ignore - } - } + }) } fn alloc_node(&mut self, @@ -1070,17 +1120,20 @@ impl CurrentDepGraph { } } -#[derive(Clone, Debug, PartialEq)] -enum OpenTask { - Regular { - node: DepNode, - reads: Vec<DepNodeIndex>, - read_set: FxHashSet<DepNodeIndex>, - }, - Anon { - reads: Vec<DepNodeIndex>, - read_set: FxHashSet<DepNodeIndex>, - }, +pub struct RegularOpenTask { + node: DepNode, + reads: Vec<DepNodeIndex>, + read_set: FxHashSet<DepNodeIndex>, +} + +pub struct AnonOpenTask { + reads: Vec<DepNodeIndex>, + read_set: FxHashSet<DepNodeIndex>, +} + +pub enum OpenTask { + Regular(Lock<RegularOpenTask>), + Anon(Lock<AnonOpenTask>), Ignore, EvalAlways { node: DepNode, diff --git a/src/librustc/dep_graph/mod.rs b/src/librustc/dep_graph/mod.rs index a472183698a..8a6f66911ec 100644 --- a/src/librustc/dep_graph/mod.rs +++ b/src/librustc/dep_graph/mod.rs @@ -14,13 +14,12 @@ mod dep_tracking_map; mod graph; mod prev; mod query; -mod raii; mod safe; mod serialized; pub use self::dep_tracking_map::{DepTrackingMap, DepTrackingMapConfig}; pub use self::dep_node::{DepNode, DepKind, DepConstructor, WorkProductId, label_strs}; -pub use self::graph::{DepGraph, WorkProduct, DepNodeIndex, DepNodeColor}; +pub use self::graph::{DepGraph, WorkProduct, DepNodeIndex, DepNodeColor, OpenTask}; pub use self::graph::WorkProductFileKind; pub use self::prev::PreviousDepGraph; pub use self::query::DepGraphQuery; diff --git a/src/librustc/dep_graph/raii.rs b/src/librustc/dep_graph/raii.rs deleted file mode 100644 index 5728bcc7d27..00000000000 --- a/src/librustc/dep_graph/raii.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use super::graph::CurrentDepGraph; - -use std::cell::RefCell; - -pub struct IgnoreTask<'graph> { - graph: &'graph RefCell<CurrentDepGraph>, -} - -impl<'graph> IgnoreTask<'graph> { - pub(super) fn new(graph: &'graph RefCell<CurrentDepGraph>) -> IgnoreTask<'graph> { - graph.borrow_mut().push_ignore(); - IgnoreTask { - graph, - } - } -} - -impl<'graph> Drop for IgnoreTask<'graph> { - fn drop(&mut self) { - self.graph.borrow_mut().pop_ignore(); - } -} - diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index f77275926eb..38de8548f30 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -79,26 +79,23 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { body_ids: _, } = *krate; - root_mod_sig_dep_index = dep_graph.with_task( + root_mod_sig_dep_index = dep_graph.input_task( root_mod_def_path_hash.to_dep_node(DepKind::Hir), &hcx, HirItemLike { item_like: (module, attrs, span), hash_bodies: false }, - identity_fn ).1; - root_mod_full_dep_index = dep_graph.with_task( + root_mod_full_dep_index = dep_graph.input_task( root_mod_def_path_hash.to_dep_node(DepKind::HirBody), &hcx, HirItemLike { item_like: (module, attrs, span), hash_bodies: true }, - identity_fn ).1; } { - dep_graph.with_task( + dep_graph.input_task( DepNode::new_no_params(DepKind::AllLocalTraitImpls), &hcx, &krate.trait_impls, - identity_fn ); } @@ -169,12 +166,11 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { let (_, crate_dep_node_index) = self .dep_graph - .with_task(DepNode::new_no_params(DepKind::Krate), + .input_task(DepNode::new_no_params(DepKind::Krate), &self.hcx, (((node_hashes, upstream_crates), source_file_names), (commandline_args_hash, - crate_disambiguator.to_fingerprint())), - identity_fn); + crate_disambiguator.to_fingerprint()))); let svh = Svh::new(self.dep_graph .fingerprint_of(crate_dep_node_index) @@ -267,18 +263,16 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { let def_path_hash = self.definitions.def_path_hash(dep_node_owner); - self.current_signature_dep_index = self.dep_graph.with_task( + self.current_signature_dep_index = self.dep_graph.input_task( def_path_hash.to_dep_node(DepKind::Hir), &self.hcx, HirItemLike { item_like, hash_bodies: false }, - identity_fn ).1; - self.current_full_dep_index = self.dep_graph.with_task( + self.current_full_dep_index = self.dep_graph.input_task( def_path_hash.to_dep_node(DepKind::HirBody), &self.hcx, HirItemLike { item_like, hash_bodies: true }, - identity_fn ).1; self.hir_body_nodes.push((def_path_hash, self.current_full_dep_index)); @@ -520,12 +514,6 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } } -// We use this with DepGraph::with_task(). Since we are handling only input -// values here, the "task" computing them just passes them through. -fn identity_fn<T>(_: &StableHashingContext, item_like: T) -> T { - item_like -} - // This is a wrapper structure that allows determining if span values within // the wrapped item should be hashed or not. struct HirItemLike<T> { diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index 4bd857c73e6..bfe21549e45 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -107,8 +107,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { // information we encapsulate into let def_data = match i.node { ItemKind::Impl(..) => DefPathData::Impl, + ItemKind::Trait(..) => DefPathData::Trait(i.ident.name.as_str()), ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | - ItemKind::Trait(..) | ItemKind::TraitAlias(..) | + ItemKind::TraitAlias(..) | ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) => DefPathData::TypeNs(i.ident.name.as_str()), ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => { @@ -222,7 +223,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { let def_data = match ti.node { TraitItemKind::Method(..) | TraitItemKind::Const(..) => DefPathData::ValueNs(ti.ident.name.as_str()), - TraitItemKind::Type(..) => DefPathData::TypeNs(ti.ident.name.as_str()), + TraitItemKind::Type(..) => DefPathData::AssocTypeInTrait(ti.ident.name.as_str()), TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id, false), }; @@ -240,7 +241,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { let def_data = match ii.node { ImplItemKind::Method(..) | ImplItemKind::Const(..) => DefPathData::ValueNs(ii.ident.name.as_str()), - ImplItemKind::Type(..) => DefPathData::TypeNs(ii.ident.name.as_str()), + ImplItemKind::Type(..) => DefPathData::AssocTypeInImpl(ii.ident.name.as_str()), ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id, false), }; diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 1a2840de447..12f146ef491 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -212,6 +212,9 @@ impl DefKey { ::std::mem::discriminant(data).hash(&mut hasher); match *data { DefPathData::TypeNs(name) | + DefPathData::Trait(name) | + DefPathData::AssocTypeInTrait(name) | + DefPathData::AssocTypeInImpl(name) | DefPathData::ValueNs(name) | DefPathData::Module(name) | DefPathData::MacroDef(name) | @@ -358,6 +361,12 @@ pub enum DefPathData { // Different kinds of items and item-like things: /// An impl Impl, + /// A trait + Trait(InternedString), + /// An associated type **declaration** (i.e., in a trait) + AssocTypeInTrait(InternedString), + /// An associated type **value** (i.e., in an impl) + AssocTypeInImpl(InternedString), /// Something in the type NS TypeNs(InternedString), /// Something in the value NS @@ -639,6 +648,9 @@ impl DefPathData { use self::DefPathData::*; match *self { TypeNs(name) | + Trait(name) | + AssocTypeInTrait(name) | + AssocTypeInImpl(name) | ValueNs(name) | Module(name) | MacroDef(name) | @@ -663,6 +675,9 @@ impl DefPathData { use self::DefPathData::*; let s = match *self { TypeNs(name) | + Trait(name) | + AssocTypeInTrait(name) | + AssocTypeInImpl(name) | ValueNs(name) | Module(name) | MacroDef(name) | diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index b88185c3154..9520ed32af9 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -30,14 +30,11 @@ use syntax_pos::Span; use hir::*; use hir::print::Nested; use hir::svh::Svh; -use util::nodemap::{DefIdMap, FxHashMap}; +use util::nodemap::FxHashMap; -use arena::SyncTypedArena; use std::io; use ty::TyCtxt; -use rustc_data_structures::sync::Lock; - pub mod blocks; mod collector; mod def_collector; @@ -219,7 +216,6 @@ impl<'hir> MapEntry<'hir> { pub struct Forest { krate: Crate, pub dep_graph: DepGraph, - inlined_bodies: SyncTypedArena<Body> } impl Forest { @@ -227,7 +223,6 @@ impl Forest { Forest { krate, dep_graph: dep_graph.clone(), - inlined_bodies: SyncTypedArena::new() } } @@ -264,9 +259,6 @@ pub struct Map<'hir> { definitions: &'hir Definitions, - /// Bodies inlined from other crates are cached here. - inlined_bodies: Lock<DefIdMap<&'hir Body>>, - /// The reverse mapping of `node_to_hir_id`. hir_to_node_id: FxHashMap<HirId, NodeId>, } @@ -923,21 +915,6 @@ impl<'hir> Map<'hir> { } } - pub fn get_inlined_body_untracked(&self, def_id: DefId) -> Option<&'hir Body> { - self.inlined_bodies.borrow().get(&def_id).cloned() - } - - pub fn intern_inlined_body(&self, def_id: DefId, body: Body) -> &'hir Body { - let mut inlined_bodies = self.inlined_bodies.borrow_mut(); - if let Some(&b) = inlined_bodies.get(&def_id) { - debug_assert_eq!(&body, b); - return b; - } - let body = self.forest.inlined_bodies.alloc(body); - inlined_bodies.insert(def_id, body); - body - } - /// Returns the name associated with the given NodeId's AST. pub fn name(&self, id: NodeId) -> Name { match self.get(id) { @@ -1195,7 +1172,6 @@ pub fn map_crate<'hir>(sess: &::session::Session, map, hir_to_node_id, definitions, - inlined_bodies: Lock::new(DefIdMap()), }; hir_id_validator::check_crate(&map); diff --git a/src/librustc/ich/impls_cstore.rs b/src/librustc/ich/impls_cstore.rs index d885bd43bc8..96d7cb6b041 100644 --- a/src/librustc/ich/impls_cstore.rs +++ b/src/librustc/ich/impls_cstore.rs @@ -11,8 +11,6 @@ //! This module contains `HashStable` implementations for various data types //! from rustc::middle::cstore in no particular order. -use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; - use middle; impl_stable_hash_for!(enum middle::cstore::DepKind { @@ -64,29 +62,3 @@ impl_stable_hash_for!(struct middle::cstore::CrateSource { rlib, rmeta }); - -impl<HCX> HashStable<HCX> for middle::cstore::ExternBodyNestedBodies { - fn hash_stable<W: StableHasherResult>(&self, - hcx: &mut HCX, - hasher: &mut StableHasher<W>) { - let middle::cstore::ExternBodyNestedBodies { - nested_bodies: _, - fingerprint, - } = *self; - - fingerprint.hash_stable(hcx, hasher); - } -} - -impl<'a, HCX> HashStable<HCX> for middle::cstore::ExternConstBody<'a> { - fn hash_stable<W: StableHasherResult>(&self, - hcx: &mut HCX, - hasher: &mut StableHasher<W>) { - let middle::cstore::ExternConstBody { - body: _, - fingerprint, - } = *self; - - fingerprint.hash_stable(hcx, hasher); - } -} diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 70c152b40c0..5ab8d6eb7b3 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -262,8 +262,7 @@ impl<'a, 'gcx, T> HashStable<StableHashingContext<'a>> for ty::Binder<T> fn hash_stable<W: StableHasherResult>(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher<W>) { - let ty::Binder(ref inner) = *self; - inner.hash_stable(hcx, hasher); + self.skip_binder().hash_stable(hcx, hasher); } } @@ -1352,10 +1351,6 @@ impl_stable_hash_for!( } ); -impl_stable_hash_for!(struct infer::canonical::QueryRegionConstraints<'tcx> { - region_outlives, ty_outlives -}); - impl_stable_hash_for!(enum infer::canonical::Certainty { Proven, Ambiguous }); @@ -1417,6 +1412,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for traits::Goal<'tcx> { quantifier.hash_stable(hcx, hasher); goal.hash_stable(hcx, hasher); }, + CannotProve => { }, } } } diff --git a/src/librustc/infer/canonical.rs b/src/librustc/infer/canonical.rs index 8ea6eb005a1..4bb191a878f 100644 --- a/src/librustc/infer/canonical.rs +++ b/src/librustc/infer/canonical.rs @@ -42,7 +42,6 @@ use traits::{Obligation, ObligationCause, PredicateObligation}; use ty::{self, CanonicalVar, Lift, Region, Slice, Ty, TyCtxt, TypeFlags}; use ty::subst::{Kind, UnpackedKind}; use ty::fold::{TypeFoldable, TypeFolder}; -use util::captures::Captures; use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::fx::FxHashMap; @@ -121,7 +120,7 @@ pub enum CanonicalTyVarKind { #[derive(Clone, Debug)] pub struct QueryResult<'tcx, R> { pub var_values: CanonicalVarValues<'tcx>, - pub region_constraints: QueryRegionConstraints<'tcx>, + pub region_constraints: Vec<QueryRegionConstraint<'tcx>>, pub certainty: Certainty, pub value: R, } @@ -181,12 +180,7 @@ impl<'tcx, R> Canonical<'tcx, QueryResult<'tcx, R>> { } } -/// Subset of `RegionConstraintData` produced by trait query. -#[derive(Clone, Debug, Default)] -pub struct QueryRegionConstraints<'tcx> { - pub region_outlives: Vec<(Region<'tcx>, Region<'tcx>)>, - pub ty_outlives: Vec<(Ty<'tcx>, Region<'tcx>)>, -} +pub type QueryRegionConstraint<'tcx> = ty::Binder<ty::OutlivesPredicate<Kind<'tcx>, Region<'tcx>>>; /// Trait implemented by values that can be canonicalized. It mainly /// serves to identify the interning table we will use. @@ -382,35 +376,31 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { &'a self, cause: &'a ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, - unsubstituted_region_constraints: &'a QueryRegionConstraints<'tcx>, + unsubstituted_region_constraints: &'a [QueryRegionConstraint<'tcx>], result_subst: &'a CanonicalVarValues<'tcx>, - ) -> impl Iterator<Item = PredicateObligation<'tcx>> + Captures<'gcx> + 'a { - let QueryRegionConstraints { - region_outlives, - ty_outlives, - } = unsubstituted_region_constraints; - - let region_obligations = region_outlives.iter().map(move |(r1, r2)| { - let r1 = substitute_value(self.tcx, result_subst, r1); - let r2 = substitute_value(self.tcx, result_subst, r2); - Obligation::new( - cause.clone(), - param_env, - ty::Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(r1, r2))), - ) - }); - - let ty_obligations = ty_outlives.iter().map(move |(t1, r2)| { - let t1 = substitute_value(self.tcx, result_subst, t1); + ) -> impl Iterator<Item = PredicateObligation<'tcx>> + 'a { + Box::new(unsubstituted_region_constraints.iter().map(move |constraint| { + let ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below + let k1 = substitute_value(self.tcx, result_subst, k1); let r2 = substitute_value(self.tcx, result_subst, r2); - Obligation::new( - cause.clone(), - param_env, - ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(t1, r2))), - ) - }); - - region_obligations.chain(ty_obligations) + match k1.unpack() { + UnpackedKind::Lifetime(r1) => + Obligation::new( + cause.clone(), + param_env, + ty::Predicate::RegionOutlives( + ty::Binder::dummy(ty::OutlivesPredicate(r1, r2))), + ), + + UnpackedKind::Type(t1) => + Obligation::new( + cause.clone(), + param_env, + ty::Predicate::TypeOutlives( + ty::Binder::dummy(ty::OutlivesPredicate(t1, r2))), + ), + } + })) as Box<dyn Iterator<Item = _>> } /// Given two sets of values for the same set of canonical variables, unify them. @@ -914,19 +904,6 @@ BraceStructTypeFoldableImpl! { } BraceStructTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for QueryRegionConstraints<'tcx> { - region_outlives, ty_outlives - } -} - -BraceStructLiftImpl! { - impl<'a, 'tcx> Lift<'tcx> for QueryRegionConstraints<'a> { - type Lifted = QueryRegionConstraints<'tcx>; - region_outlives, ty_outlives - } -} - -BraceStructTypeFoldableImpl! { impl<'tcx, R> TypeFoldable<'tcx> for QueryResult<'tcx, R> { var_values, region_constraints, certainty, value } where R: TypeFoldable<'tcx>, diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index c2167751a27..096aed85f55 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -302,7 +302,7 @@ struct Generalizer<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> { /// Result from a generalization operation. This includes /// not only the generalized type, but also a bool flag -/// indicating whether further WF checks are needed.q +/// indicating whether further WF checks are needed. struct Generalization<'tcx> { ty: Ty<'tcx>, @@ -351,7 +351,7 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, ' -> RelateResult<'tcx, ty::Binder<T>> where T: Relate<'tcx> { - Ok(ty::Binder(self.relate(a.skip_binder(), b.skip_binder())?)) + Ok(ty::Binder::bind(self.relate(a.skip_binder(), b.skip_binder())?)) } fn relate_item_substs(&mut self, diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index d8a2c95ab59..588f75f809c 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -916,7 +916,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { }; if let (Some(def_id), Some(ret_ty)) = (def_id, ret_ty) { - if exp_is_struct && exp_found.expected == ret_ty.0 { + if exp_is_struct && &exp_found.expected == ret_ty.skip_binder() { let message = format!( "did you mean `{}(/* fields */)`?", self.tcx.item_path_str(def_id) diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index d44f2ec9549..c23836071ff 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -80,7 +80,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { debug!("higher_ranked_sub: OK result={:?}", result); - Ok(ty::Binder(result)) + Ok(ty::Binder::bind(result)) }); } @@ -239,7 +239,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { b, result1); - Ok(ty::Binder(result1)) + Ok(ty::Binder::bind(result1)) }); fn generalize_region<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, @@ -335,7 +335,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { b, result1); - Ok(ty::Binder(result1)) + Ok(ty::Binder::bind(result1)) }); fn generalize_region<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, diff --git a/src/librustc/infer/sub.rs b/src/librustc/infer/sub.rs index f891f692c7d..58eae5e6a5b 100644 --- a/src/librustc/infer/sub.rs +++ b/src/librustc/infer/sub.rs @@ -98,7 +98,7 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> self.fields.trace.cause.clone(), self.fields.param_env, ty::Predicate::Subtype( - ty::Binder(ty::SubtypePredicate { + ty::Binder::dummy(ty::SubtypePredicate { a_is_expected: self.a_is_expected, a, b, diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index a2cefe488c6..bb495049483 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -52,6 +52,7 @@ #![cfg_attr(windows, feature(libc))] #![feature(macro_lifetime_matcher)] #![feature(macro_vis_matcher)] +#![feature(never_type)] #![feature(exhaustive_patterns)] #![feature(non_exhaustive)] #![feature(nonzero)] diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 97cfcf0f607..109edffcde3 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -255,6 +255,13 @@ declare_lint! { } declare_lint! { + pub ABSOLUTE_PATH_STARTING_WITH_MODULE, + Allow, + "fully qualified paths that start with a module name \ + instead of `crate`, `self`, or an extern crate name" +} + +declare_lint! { pub ILLEGAL_FLOATING_POINT_LITERAL_PATTERN, Warn, "floating-point literals cannot be used in patterns" @@ -314,6 +321,7 @@ impl LintPass for HardwiredLints { TYVAR_BEHIND_RAW_POINTER, ELIDED_LIFETIME_IN_PATH, BARE_TRAIT_OBJECT, + ABSOLUTE_PATH_STARTING_WITH_MODULE, UNSTABLE_NAME_COLLISION, ) } @@ -324,7 +332,8 @@ impl LintPass for HardwiredLints { #[derive(PartialEq, RustcEncodable, RustcDecodable, Debug)] pub enum BuiltinLintDiagnostics { Normal, - BareTraitObject(Span, /* is_global */ bool) + BareTraitObject(Span, /* is_global */ bool), + AbsPathWithModule(Span), } impl BuiltinLintDiagnostics { @@ -339,6 +348,23 @@ impl BuiltinLintDiagnostics { }; db.span_suggestion(span, "use `dyn`", sugg); } + BuiltinLintDiagnostics::AbsPathWithModule(span) => { + let sugg = match sess.codemap().span_to_snippet(span) { + Ok(ref s) => { + // FIXME(Manishearth) ideally the emitting code + // can tell us whether or not this is global + let opt_colon = if s.trim_left().starts_with("::") { + "" + } else { + "::" + }; + + format!("crate{}{}", opt_colon, s) + } + Err(_) => format!("crate::<path>") + }; + db.span_suggestion(span, "use `crate`", sugg); + } } } } diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 292ec184dfa..60e197e614a 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -22,19 +22,16 @@ //! are *mostly* used as a part of that interface, but these should //! probably get a better home if someone can find one. -use hir; use hir::def; use hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use hir::map as hir_map; use hir::map::definitions::{Definitions, DefKey, DefPathTable}; use hir::svh::Svh; -use ich; use ty::{self, TyCtxt}; use session::{Session, CrateDisambiguator}; use session::search_paths::PathKind; use std::any::Any; -use std::collections::BTreeMap; use std::path::{Path, PathBuf}; use syntax::ast; use syntax::ext::base::SyntaxExtension; @@ -209,26 +206,6 @@ pub trait MetadataLoader { -> Result<MetadataRef, String>; } -#[derive(Clone)] -pub struct ExternConstBody<'tcx> { - pub body: &'tcx hir::Body, - - // It would require a lot of infrastructure to enable stable-hashing Bodies - // from other crates, so we hash on export and just store the fingerprint - // with them. - pub fingerprint: ich::Fingerprint, -} - -#[derive(Clone)] -pub struct ExternBodyNestedBodies { - pub nested_bodies: Lrc<BTreeMap<hir::BodyId, hir::Body>>, - - // It would require a lot of infrastructure to enable stable-hashing Bodies - // from other crates, so we hash on export and just store the fingerprint - // with them. - pub fingerprint: ich::Fingerprint, -} - /// A store of Rust crates, through with their metadata /// can be accessed. /// diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 3b37031cf46..95e92e21b09 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -214,6 +214,9 @@ language_item_table! { StrImplItem, "str", str_impl; SliceImplItem, "slice", slice_impl; SliceU8ImplItem, "slice_u8", slice_u8_impl; + StrAllocImplItem, "str_alloc", str_alloc_impl; + SliceAllocImplItem, "slice_alloc", slice_alloc_impl; + SliceU8AllocImplItem, "slice_u8_alloc", slice_u8_alloc_impl; ConstPtrImplItem, "const_ptr", const_ptr_impl; MutPtrImplItem, "mut_ptr", mut_ptr_impl; I8ImplItem, "i8", i8_impl; @@ -230,6 +233,8 @@ language_item_table! { UsizeImplItem, "usize", usize_impl; F32ImplItem, "f32", f32_impl; F64ImplItem, "f64", f64_impl; + F32RuntimeImplItem, "f32_runtime", f32_runtime_impl; + F64RuntimeImplItem, "f64_runtime", f64_runtime_impl; SizedTraitLangItem, "sized", sized_trait; UnsizeTraitLangItem, "unsize", unsize_trait; @@ -298,7 +303,8 @@ language_item_table! { ExchangeMallocFnLangItem, "exchange_malloc", exchange_malloc_fn; BoxFreeFnLangItem, "box_free", box_free_fn; - DropInPlaceFnLangItem, "drop_in_place", drop_in_place_fn; + DropInPlaceFnLangItem, "drop_in_place", drop_in_place_fn; + OomLangItem, "oom", oom; StartFnLangItem, "start", start_fn; diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 11dc2a81885..17c114bc3b3 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -184,6 +184,7 @@ impl<'a, 'tcx> Visitor<'tcx> for IrMaps<'a, 'tcx> { b: hir::BodyId, s: Span, id: NodeId) { visit_fn(self, fk, fd, b, s, id); } + fn visit_local(&mut self, l: &'tcx hir::Local) { visit_local(self, l); } fn visit_expr(&mut self, ex: &'tcx Expr) { visit_expr(self, ex); } fn visit_arm(&mut self, a: &'tcx hir::Arm) { visit_arm(self, a); } @@ -361,6 +362,16 @@ fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>, // swap in a new set of IR maps for this function body: let mut fn_maps = IrMaps::new(ir.tcx); + // Don't run unused pass for #[derive()] + if let FnKind::Method(..) = fk { + let parent = ir.tcx.hir.get_parent(id); + if let Some(hir::map::Node::NodeItem(i)) = ir.tcx.hir.find(parent) { + if i.attrs.iter().any(|a| a.check_name("automatically_derived")) { + return; + } + } + } + debug!("creating fn_maps: {:?}", &fn_maps as *const IrMaps); let body = ir.tcx.hir.body(body_id); diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 42483c83f4b..5f4efbeeaa8 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -22,6 +22,7 @@ use ty; use std::fmt; use std::mem; +use rustc_data_structures::small_vec::SmallVec; use rustc_data_structures::sync::Lrc; use syntax::codemap; use syntax::ast; @@ -677,96 +678,75 @@ impl<'tcx> ScopeTree { -> Scope { if scope_a == scope_b { return scope_a; } - // [1] The initial values for `a_buf` and `b_buf` are not used. - // The `ancestors_of` function will return some prefix that - // is re-initialized with new values (or else fallback to a - // heap-allocated vector). - let mut a_buf: [Scope; 32] = [scope_a /* [1] */; 32]; - let mut a_vec: Vec<Scope> = vec![]; - let mut b_buf: [Scope; 32] = [scope_b /* [1] */; 32]; - let mut b_vec: Vec<Scope> = vec![]; - let parent_map = &self.parent_map; - let a_ancestors = ancestors_of(parent_map, scope_a, &mut a_buf, &mut a_vec); - let b_ancestors = ancestors_of(parent_map, scope_b, &mut b_buf, &mut b_vec); - let mut a_index = a_ancestors.len() - 1; - let mut b_index = b_ancestors.len() - 1; - - // Here, [ab]_ancestors is a vector going from narrow to broad. - // The end of each vector will be the item where the scope is - // defined; if there are any common ancestors, then the tails of - // the vector will be the same. So basically we want to walk - // backwards from the tail of each vector and find the first point - // where they diverge. If one vector is a suffix of the other, - // then the corresponding scope is a superscope of the other. - - if a_ancestors[a_index] != b_ancestors[b_index] { - // In this case, the two regions belong to completely - // different functions. Compare those fn for lexical - // nesting. The reasoning behind this is subtle. See the - // "Modeling closures" section of the README in - // infer::region_constraints for more details. - let a_root_scope = a_ancestors[a_index]; - let b_root_scope = a_ancestors[a_index]; - return match (a_root_scope.data(), b_root_scope.data()) { - (ScopeData::Destruction(a_root_id), - ScopeData::Destruction(b_root_id)) => { - if self.closure_is_enclosed_by(a_root_id, b_root_id) { - // `a` is enclosed by `b`, hence `b` is the ancestor of everything in `a` - scope_b - } else if self.closure_is_enclosed_by(b_root_id, a_root_id) { - // `b` is enclosed by `a`, hence `a` is the ancestor of everything in `b` - scope_a - } else { - // neither fn encloses the other - bug!() - } + // Process the lists in tandem from the innermost scope, recording the + // scopes seen so far. The first scope that comes up for a second time + // is the nearest common ancestor. + // + // Note: another way to compute the nearest common ancestor is to get + // the full scope chain for both scopes and then compare the chains to + // find the first scope in a common tail. But getting a parent scope + // requires a hash table lookup, and we often have very long scope + // chains (10s or 100s of scopes) that only differ by a few elements at + // the start. So this algorithm is faster. + let mut ma = Some(scope_a); + let mut mb = Some(scope_b); + let mut seen: SmallVec<[Scope; 32]> = SmallVec::new(); + loop { + if let Some(a) = ma { + if seen.iter().position(|s| *s == a).is_some() { + return a; } - _ => { - // root ids are always Node right now - bug!() + seen.push(a); + ma = self.parent_map.get(&a).map(|s| *s); + } + + if let Some(b) = mb { + if seen.iter().position(|s| *s == b).is_some() { + return b; } - }; - } + seen.push(b); + mb = self.parent_map.get(&b).map(|s| *s); + } - loop { - // Loop invariant: a_ancestors[a_index] == b_ancestors[b_index] - // for all indices between a_index and the end of the array - if a_index == 0 { return scope_a; } - if b_index == 0 { return scope_b; } - a_index -= 1; - b_index -= 1; - if a_ancestors[a_index] != b_ancestors[b_index] { - return a_ancestors[a_index + 1]; + if ma.is_none() && mb.is_none() { + break; } - } + }; - fn ancestors_of<'a, 'tcx>(parent_map: &FxHashMap<Scope, Scope>, - scope: Scope, - buf: &'a mut [Scope; 32], - vec: &'a mut Vec<Scope>) - -> &'a [Scope] { - // debug!("ancestors_of(scope={:?})", scope); + fn outermost_scope(parent_map: &FxHashMap<Scope, Scope>, scope: Scope) -> Scope { let mut scope = scope; - - let mut i = 0; - while i < 32 { - buf[i] = scope; - match parent_map.get(&scope) { - Some(&superscope) => scope = superscope, - _ => return &buf[..i+1] - } - i += 1; + loop { + match parent_map.get(&scope) { + Some(&superscope) => scope = superscope, + None => break scope, + } } + } - *vec = Vec::with_capacity(64); - vec.extend_from_slice(buf); - loop { - vec.push(scope); - match parent_map.get(&scope) { - Some(&superscope) => scope = superscope, - _ => return &*vec + // In this (rare) case, the two regions belong to completely different + // functions. Compare those fn for lexical nesting. The reasoning + // behind this is subtle. See the "Modeling closures" section of the + // README in infer::region_constraints for more details. + let a_root_scope = outermost_scope(&self.parent_map, scope_a); + let b_root_scope = outermost_scope(&self.parent_map, scope_b); + match (a_root_scope.data(), b_root_scope.data()) { + (ScopeData::Destruction(a_root_id), + ScopeData::Destruction(b_root_id)) => { + if self.closure_is_enclosed_by(a_root_id, b_root_id) { + // `a` is enclosed by `b`, hence `b` is the ancestor of everything in `a` + scope_b + } else if self.closure_is_enclosed_by(b_root_id, a_root_id) { + // `b` is enclosed by `a`, hence `a` is the ancestor of everything in `b` + scope_a + } else { + // neither fn encloses the other + bug!() } } + _ => { + // root ids are always Node right now + bug!() + } } } diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs index e19f4483f65..a2bceb19102 100644 --- a/src/librustc/middle/weak_lang_items.rs +++ b/src/librustc/middle/weak_lang_items.rs @@ -151,4 +151,5 @@ weak_lang_items! { panic_fmt, PanicFmtLangItem, rust_begin_unwind; eh_personality, EhPersonalityLangItem, rust_eh_personality; eh_unwind_resume, EhUnwindResumeLangItem, rust_eh_unwind_resume; + oom, OomLangItem, rust_oom; } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 59823390a0a..456e83f4700 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -16,6 +16,8 @@ pub use self::CrateType::*; pub use self::Passes::*; pub use self::DebugInfoLevel::*; +use std::str::FromStr; + use session::{early_error, early_warn, Session}; use session::search_paths::SearchPaths; @@ -28,7 +30,7 @@ use middle::cstore; use syntax::ast::{self, IntTy, UintTy}; use syntax::codemap::{FileName, FilePathMapping}; -use syntax::edition::Edition; +use syntax::edition::{Edition, EDITION_NAME_LIST, DEFAULT_EDITION}; use syntax::parse::token; use syntax::parse; use syntax::symbol::Symbol; @@ -410,6 +412,7 @@ top_level_options!( // Remap source path prefixes in all output (messages, object files, debug, etc) remap_path_prefix: Vec<(PathBuf, PathBuf)> [UNTRACKED], + edition: Edition [TRACKED], } ); @@ -589,6 +592,7 @@ pub fn basic_options() -> Options { cli_forced_codegen_units: None, cli_forced_thinlto_off: false, remap_path_prefix: Vec::new(), + edition: DEFAULT_EDITION, } } @@ -773,8 +777,6 @@ macro_rules! options { Some("`string` or `string=string`"); pub const parse_lto: Option<&'static str> = Some("one of `thin`, `fat`, or omitted"); - pub const parse_edition: Option<&'static str> = - Some("one of: `2015`, `2018`"); } #[allow(dead_code)] @@ -782,7 +784,6 @@ macro_rules! options { use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer, Lto}; use rustc_back::{LinkerFlavor, PanicStrategy, RelroLevel}; use std::path::PathBuf; - use syntax::edition::Edition; $( pub fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool { @@ -985,20 +986,6 @@ macro_rules! options { true } - fn parse_edition(slot: &mut Edition, v: Option<&str>) -> bool { - match v { - Some(s) => { - let edition = s.parse(); - if let Ok(parsed) = edition { - *slot = parsed; - true - } else { - false - } - } - _ => false, - } - } } ) } @@ -1259,6 +1246,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, useful for profiling / PGO."), relro_level: Option<RelroLevel> = (None, parse_relro_level, [TRACKED], "choose which RELRO level to use"), + nll_subminimal_causes: bool = (false, parse_bool, [UNTRACKED], + "when tracking region error causes, accept subminimal results for faster execution."), disable_nll_user_type_assert: bool = (false, parse_bool, [UNTRACKED], "disable user provided type assertion in NLL"), trans_time_graph: bool = (false, parse_bool, [UNTRACKED], @@ -1290,10 +1279,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, `everybody_loops` (all function bodies replaced with `loop {}`), `hir` (the HIR), `hir,identified`, or `hir,typed` (HIR with types for each node)."), - edition: Edition = (Edition::Edition2015, parse_edition, [TRACKED], - "The edition to build Rust with. Newer editions may include features - that require breaking changes. The default edition is 2015 (the first - edition). Crates compiled with different editions can be linked together."), run_dsymutil: Option<bool> = (None, parse_opt_bool, [TRACKED], "run `dsymutil` and delete intermediate object files"), ui_testing: bool = (false, parse_bool, [UNTRACKED], @@ -1304,6 +1289,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "tell the linker to strip debuginfo when building without debuginfo enabled."), share_generics: Option<bool> = (None, parse_opt_bool, [TRACKED], "make the current crate share its generic instantiations"), + chalk: bool = (false, parse_bool, [TRACKED], + "enable the experimental Chalk-based trait solving engine"), } pub fn default_lib_output() -> CrateType { @@ -1654,6 +1641,12 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> { `expanded,identified` (fully parenthesized, AST nodes with IDs).", "TYPE", ), + opt::opt_s( + "", + "edition", + "Specify which edition of the compiler to use when compiling code.", + EDITION_NAME_LIST, + ), opt::multi_s( "", "remap-path-prefix", @@ -1713,6 +1706,34 @@ pub fn build_session_options_and_crate_config( ), }; + let edition = match matches.opt_str("edition") { + Some(arg) => match Edition::from_str(&arg){ + Ok(edition) => edition, + Err(_) => early_error( + ErrorOutputType::default(), + &format!( + "argument for --edition must be one of: \ + {}. (instead was `{}`)", + EDITION_NAME_LIST, + arg + ), + ), + } + None => DEFAULT_EDITION, + }; + + if !edition.is_stable() && !nightly_options::is_nightly_build() { + early_error( + ErrorOutputType::default(), + &format!( + "Edition {} is unstable an only\ + available for nightly builds of rustc.", + edition, + ) + ) + } + + // We need the opts_present check because the driver will send us Matches // with only stable options if no unstable options are used. Since error-format // is unstable, it will not be present. We have to use opts_present not @@ -2169,6 +2190,7 @@ pub fn build_session_options_and_crate_config( cli_forced_codegen_units: codegen_units, cli_forced_thinlto_off: disable_thinlto, remap_path_prefix, + edition, }, cfg, ) @@ -2298,11 +2320,12 @@ mod dep_tracking { use std::hash::Hash; use std::path::PathBuf; use std::collections::hash_map::DefaultHasher; - use super::{CrateType, DebugInfoLevel, Edition, ErrorOutputType, Lto, OptLevel, OutputTypes, + use super::{CrateType, DebugInfoLevel, ErrorOutputType, Lto, OptLevel, OutputTypes, Passes, Sanitizer}; use syntax::feature_gate::UnstableFeatures; use rustc_back::{PanicStrategy, RelroLevel}; use rustc_back::target::TargetTriple; + use syntax::edition::Edition; pub trait DepTrackingHash { fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType); @@ -2361,8 +2384,8 @@ mod dep_tracking { impl_dep_tracking_hash_via_hash!(cstore::NativeLibraryKind); impl_dep_tracking_hash_via_hash!(Sanitizer); impl_dep_tracking_hash_via_hash!(Option<Sanitizer>); - impl_dep_tracking_hash_via_hash!(Edition); impl_dep_tracking_hash_via_hash!(TargetTriple); + impl_dep_tracking_hash_via_hash!(Edition); impl_dep_tracking_hash_for_sortable_vec_of!(String); impl_dep_tracking_hash_for_sortable_vec_of!(PathBuf); @@ -2435,6 +2458,7 @@ mod tests { use super::{Externs, OutputType, OutputTypes}; use rustc_back::{PanicStrategy, RelroLevel}; use syntax::symbol::Symbol; + use syntax::edition::{Edition, DEFAULT_EDITION}; use syntax; fn optgroups() -> getopts::Options { @@ -3079,4 +3103,17 @@ mod tests { opts.debugging_opts.relro_level = Some(RelroLevel::Full); assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); } + + #[test] + fn test_edition_parsing() { + // test default edition + let options = super::basic_options(); + assert!(options.edition == DEFAULT_EDITION); + + let matches = optgroups() + .parse(&["--edition=2018".to_string()]) + .unwrap(); + let (sessopts, _) = build_session_options_and_crate_config(&matches); + assert!(sessopts.edition == Edition::Edition2018) + } } diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 2993234f266..3bd2bb3c8be 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -156,7 +156,7 @@ pub struct Session { /// Loaded up early on in the initialization of this `Session` to avoid /// false positives about a job server in our environment. - pub jobserver_from_env: Option<Client>, + pub jobserver: Client, /// Metadata about the allocators for the current crate being compiled pub has_global_allocator: Once<bool>, @@ -934,11 +934,11 @@ impl Session { /// Are we allowed to use features from the Rust 2018 edition? pub fn rust_2018(&self) -> bool { - self.opts.debugging_opts.edition >= Edition::Edition2018 + self.opts.edition >= Edition::Edition2018 } pub fn edition(&self) -> Edition { - self.opts.debugging_opts.edition + self.opts.edition } } @@ -1128,14 +1128,23 @@ pub fn build_session_( // positives, or in other words we try to execute this before we open // any file descriptors ourselves. // + // Pick a "reasonable maximum" if we don't otherwise have + // a jobserver in our environment, capping out at 32 so we + // don't take everything down by hogging the process run queue. + // The fixed number is used to have deterministic compilation + // across machines. + // // Also note that we stick this in a global because there could be // multiple `Session` instances in this process, and the jobserver is // per-process. - jobserver_from_env: unsafe { - static mut GLOBAL_JOBSERVER: *mut Option<Client> = 0 as *mut _; + jobserver: unsafe { + static mut GLOBAL_JOBSERVER: *mut Client = 0 as *mut _; static INIT: std::sync::Once = std::sync::ONCE_INIT; INIT.call_once(|| { - GLOBAL_JOBSERVER = Box::into_raw(Box::new(Client::from_env())); + let client = Client::from_env().unwrap_or_else(|| { + Client::new(32).expect("failed to create jobserver") + }); + GLOBAL_JOBSERVER = Box::into_raw(Box::new(client)); }); (*GLOBAL_JOBSERVER).clone() }, diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 2af4c3f9fd4..a7669b942e3 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -537,7 +537,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { &data.parent_trait_ref); match self.get_parent_trait_ref(&data.parent_code) { Some(t) => Some(t), - None => Some(format!("{}", parent_trait_ref.0.self_ty())), + None => Some(format!("{}", parent_trait_ref.skip_binder().self_ty())), } } _ => None, @@ -862,7 +862,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'tcx>, trait_ref: &ty::Binder<ty::TraitRef<'tcx>>) { - let ty::Binder(trait_ref) = trait_ref; + let trait_ref = trait_ref.skip_binder(); let span = obligation.cause.span; if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) { @@ -1102,7 +1102,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ::syntax::abi::Abi::Rust ) }; - format!("{}", ty::Binder(sig)) + format!("{}", ty::Binder::bind(sig)) } let argument_is_closure = expected_ref.skip_binder().substs.type_at(0).is_closure(); @@ -1436,7 +1436,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } ObligationCauseCode::BuiltinDerivedObligation(ref data) => { let parent_trait_ref = self.resolve_type_vars_if_possible(&data.parent_trait_ref); - let ty = parent_trait_ref.0.self_ty(); + let ty = parent_trait_ref.skip_binder().self_ty(); err.note(&format!("required because it appears within the type `{}`", ty)); obligated_types.push(ty); @@ -1453,7 +1453,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { err.note( &format!("required because of the requirements on the impl of `{}` for `{}`", parent_trait_ref, - parent_trait_ref.0.self_ty())); + parent_trait_ref.skip_binder().self_ty())); let parent_predicate = parent_trait_ref.to_predicate(); self.note_obligation_cause_code(err, &parent_predicate, @@ -1484,7 +1484,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code { let parent_trait_ref = self.resolve_type_vars_if_possible(&data.parent_trait_ref); for obligated_type in obligated_types { - if obligated_type == &parent_trait_ref.0.self_ty() { + if obligated_type == &parent_trait_ref.skip_binder().self_ty() { return true; } } diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 8d2398d3409..728d9f1a027 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -282,13 +282,16 @@ pub enum QuantifierKind { #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub enum Goal<'tcx> { - Implies(&'tcx Slice<Clause<'tcx>>, &'tcx Goal<'tcx>), + Implies(Clauses<'tcx>, &'tcx Goal<'tcx>), And(&'tcx Goal<'tcx>, &'tcx Goal<'tcx>), Not(&'tcx Goal<'tcx>), DomainGoal(DomainGoal<'tcx>), - Quantified(QuantifierKind, ty::Binder<&'tcx Goal<'tcx>>) + Quantified(QuantifierKind, ty::Binder<&'tcx Goal<'tcx>>), + CannotProve, } +pub type Goals<'tcx> = &'tcx Slice<Goal<'tcx>>; + impl<'tcx> Goal<'tcx> { pub fn from_poly_domain_goal<'a>( domain_goal: PolyDomainGoal<'tcx>, @@ -318,6 +321,9 @@ pub enum Clause<'tcx> { ForAll(ty::Binder<ProgramClause<'tcx>>), } +/// Multiple clauses. +pub type Clauses<'tcx> = &'tcx Slice<Clause<'tcx>>; + /// A "program clause" has the form `D :- G1, ..., Gn`. It is saying /// that the domain goal `D` is true if `G1...Gn` are provable. This /// is equivalent to the implication `G1..Gn => D`; we usually write @@ -330,7 +336,7 @@ pub struct ProgramClause<'tcx> { pub goal: DomainGoal<'tcx>, /// ...if we can prove these hypotheses (there may be no hypotheses at all): - pub hypotheses: &'tcx Slice<Goal<'tcx>>, + pub hypotheses: Goals<'tcx>, } pub type Selection<'tcx> = Vtable<'tcx, PredicateObligation<'tcx>>; @@ -849,16 +855,19 @@ fn vtable_methods<'a, 'tcx>( // the method may have some early-bound lifetimes, add // regions for those - let substs = Substs::for_item(tcx, def_id, - |_, _| tcx.types.re_erased, - |def, _| trait_ref.substs().type_for_def(def)); + let substs = trait_ref.map_bound(|trait_ref| { + Substs::for_item( + tcx, def_id, + |_, _| tcx.types.re_erased, + |def, _| trait_ref.substs.type_for_def(def)) + }); // the trait type may have higher-ranked lifetimes in it; // so erase them if they appear, so that we get the type // at some particular call site let substs = tcx.normalize_erasing_late_bound_regions( ty::ParamEnv::reveal_all(), - &ty::Binder(substs), + &substs ); // It's possible that the method relies on where clauses that @@ -991,7 +1000,7 @@ impl<'tcx> FulfillmentError<'tcx> { impl<'tcx> TraitObligation<'tcx> { fn self_ty(&self) -> ty::Binder<Ty<'tcx>> { - ty::Binder(self.predicate.skip_binder().self_ty()) + self.predicate.map_bound(|p| p.self_ty()) } } diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 52a0a897595..c0d5a337cee 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -149,7 +149,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { trait_def_id: DefId, supertraits_only: bool) -> bool { - let trait_ref = ty::Binder(ty::TraitRef { + let trait_ref = ty::Binder::dummy(ty::TraitRef { def_id: trait_def_id, substs: Substs::identity_for_item(self, trait_def_id) }); @@ -199,7 +199,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { .any(|predicate| { match predicate { ty::Predicate::Trait(ref trait_pred) if trait_pred.def_id() == sized_def_id => { - trait_pred.0.self_ty().is_self() + trait_pred.skip_binder().self_ty().is_self() } ty::Predicate::Projection(..) | ty::Predicate::Trait(..) | @@ -352,7 +352,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // Compute supertraits of current trait lazily. if supertraits.is_none() { - let trait_ref = ty::Binder(ty::TraitRef { + let trait_ref = ty::Binder::bind(ty::TraitRef { def_id: trait_def_id, substs: Substs::identity_for_item(self, trait_def_id) }); @@ -367,7 +367,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // direct equality here because all of these types // are part of the formal parameter listing, and // hence there should be no inference variables. - let projection_trait_ref = ty::Binder(data.trait_ref(self)); + let projection_trait_ref = ty::Binder::bind(data.trait_ref(self)); let is_supertrait_of_current_trait = supertraits.as_ref().unwrap().contains(&projection_trait_ref); diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 9f21ea14d0f..1c7942139e9 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -478,7 +478,7 @@ pub fn normalize_projection_type<'a, 'b, 'gcx, 'tcx>( let def_id = projection_ty.item_def_id; let ty_var = selcx.infcx().next_ty_var( TypeVariableOrigin::NormalizeProjectionType(tcx.def_span(def_id))); - let projection = ty::Binder(ty::ProjectionPredicate { + let projection = ty::Binder::dummy(ty::ProjectionPredicate { projection_ty, ty: ty_var }); @@ -982,8 +982,7 @@ fn assemble_candidates_from_predicates<'cx, 'gcx, 'tcx, I>( predicate); match predicate { ty::Predicate::Projection(data) => { - let same_def_id = - data.0.projection_ty.item_def_id == obligation.predicate.item_def_id; + let same_def_id = data.projection_def_id() == obligation.predicate.item_def_id; let is_match = same_def_id && infcx.probe(|_| { let data_poly_trait_ref = @@ -1241,7 +1240,7 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>( // item with the correct name let env_predicates = env_predicates.filter_map(|p| match p { ty::Predicate::Projection(data) => - if data.0.projection_ty.item_def_id == obligation.predicate.item_def_id { + if data.projection_def_id() == obligation.predicate.item_def_id { Some(data) } else { None @@ -1302,28 +1301,28 @@ fn confirm_generator_candidate<'cx, 'gcx, 'tcx>( let gen_def_id = tcx.lang_items().gen_trait().unwrap(); - // Note: we unwrap the binder here but re-create it below (1) - let ty::Binder((trait_ref, yield_ty, return_ty)) = + let predicate = tcx.generator_trait_ref_and_outputs(gen_def_id, obligation.predicate.self_ty(), - gen_sig); - - let name = tcx.associated_item(obligation.predicate.item_def_id).name; - let ty = if name == Symbol::intern("Return") { - return_ty - } else if name == Symbol::intern("Yield") { - yield_ty - } else { - bug!() - }; + gen_sig) + .map_bound(|(trait_ref, yield_ty, return_ty)| { + let name = tcx.associated_item(obligation.predicate.item_def_id).name; + let ty = if name == Symbol::intern("Return") { + return_ty + } else if name == Symbol::intern("Yield") { + yield_ty + } else { + bug!() + }; - let predicate = ty::Binder(ty::ProjectionPredicate { // (1) recreate binder here - projection_ty: ty::ProjectionTy { - substs: trait_ref.substs, - item_def_id: obligation.predicate.item_def_id, - }, - ty: ty - }); + ty::ProjectionPredicate { + projection_ty: ty::ProjectionTy { + substs: trait_ref.substs, + item_def_id: obligation.predicate.item_def_id, + }, + ty: ty + } + }); confirm_param_env_candidate(selcx, obligation, predicate) .with_addl_obligations(vtable.nested) @@ -1400,21 +1399,21 @@ fn confirm_callable_candidate<'cx, 'gcx, 'tcx>( // the `Output` associated type is declared on `FnOnce` let fn_once_def_id = tcx.lang_items().fn_once_trait().unwrap(); - // Note: we unwrap the binder here but re-create it below (1) - let ty::Binder((trait_ref, ret_type)) = + let predicate = tcx.closure_trait_ref_and_return_type(fn_once_def_id, obligation.predicate.self_ty(), fn_sig, - flag); - - let predicate = ty::Binder(ty::ProjectionPredicate { // (1) recreate binder here - projection_ty: ty::ProjectionTy::from_ref_and_name( - tcx, - trait_ref, - Symbol::intern(FN_OUTPUT_NAME), - ), - ty: ret_type - }); + flag) + .map_bound(|(trait_ref, ret_type)| { + ty::ProjectionPredicate { + projection_ty: ty::ProjectionTy::from_ref_and_name( + tcx, + trait_ref, + Symbol::intern(FN_OUTPUT_NAME), + ), + ty: ret_type + } + }); confirm_param_env_candidate(selcx, obligation, predicate) } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 51493f26194..cfc14b7bfe4 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -786,7 +786,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // This suffices to allow chains like `FnMut` implemented in // terms of `Fn` etc, but we could probably make this more // precise still. - let unbound_input_types = stack.fresh_trait_ref.input_types().any(|ty| ty.is_fresh()); + let unbound_input_types = + stack.fresh_trait_ref.skip_binder().input_types().any(|ty| ty.is_fresh()); // this check was an imperfect workaround for a bug n the old // intercrate mode, it should be removed when that goes away. if unbound_input_types && @@ -1274,7 +1275,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { -> Option<SelectionResult<'tcx, SelectionCandidate<'tcx>>> { let tcx = self.tcx(); - let trait_ref = &cache_fresh_trait_pred.0.trait_ref; + let trait_ref = &cache_fresh_trait_pred.skip_binder().trait_ref; if self.can_use_global_caches(param_env) { let cache = tcx.selection_cache.hashmap.borrow(); if let Some(cached) = cache.get(&trait_ref) { @@ -1294,7 +1295,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { candidate: SelectionResult<'tcx, SelectionCandidate<'tcx>>) { let tcx = self.tcx(); - let trait_ref = cache_fresh_trait_pred.0.trait_ref; + let trait_ref = cache_fresh_trait_pred.skip_binder().trait_ref; if self.can_use_global_caches(param_env) { let mut cache = tcx.selection_cache.hashmap.borrow_mut(); if let Some(trait_ref) = tcx.lift_to_global(&trait_ref) { @@ -1357,7 +1358,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let lang_items = self.tcx().lang_items(); if lang_items.copy_trait() == Some(def_id) { debug!("obligation self ty is {:?}", - obligation.predicate.0.self_ty()); + obligation.predicate.skip_binder().self_ty()); // User-defined copy impls are permitted, but only for // structs and enums. @@ -1409,7 +1410,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // before we go into the whole skolemization thing, just // quickly check if the self-type is a projection at all. - match obligation.predicate.0.trait_ref.self_ty().sty { + match obligation.predicate.skip_binder().trait_ref.self_ty().sty { ty::TyProjection(_) | ty::TyAnon(..) => {} ty::TyInfer(ty::TyVar(_)) => { span_bug!(obligation.cause.span, @@ -1507,7 +1508,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { { assert!(!skol_trait_ref.has_escaping_regions()); if let Err(_) = self.infcx.at(&obligation.cause, obligation.param_env) - .sup(ty::Binder(skol_trait_ref), trait_bound) { + .sup(ty::Binder::dummy(skol_trait_ref), trait_bound) { return false; } @@ -1605,7 +1606,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { candidates: &mut SelectionCandidateSet<'tcx>) -> Result<(),SelectionError<'tcx>> { - let kind = match self.tcx().lang_items().fn_trait_kind(obligation.predicate.0.def_id()) { + let kind = match self.tcx().lang_items().fn_trait_kind(obligation.predicate.def_id()) { Some(k) => k, None => { return Ok(()); } }; @@ -1661,12 +1662,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // provide an impl, but only for suitable `fn` pointers ty::TyFnDef(..) | ty::TyFnPtr(_) => { - if let ty::Binder(ty::FnSig { + if let ty::FnSig { unsafety: hir::Unsafety::Normal, abi: Abi::Rust, variadic: false, .. - }) = self_ty.fn_sig(self.tcx()) { + } = self_ty.fn_sig(self.tcx()).skip_binder() { candidates.vec.push(FnPointerCandidate); } } @@ -1687,7 +1688,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { self.tcx().for_each_relevant_impl( obligation.predicate.def_id(), - obligation.predicate.0.trait_ref.self_ty(), + obligation.predicate.skip_binder().trait_ref.self_ty(), |impl_def_id| { self.probe(|this, snapshot| { /* [1] */ match this.match_impl(impl_def_id, obligation, snapshot) { @@ -2046,19 +2047,19 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ty::TyGeneratorWitness(..) | ty::TyArray(..) | ty::TyClosure(..) | ty::TyNever | ty::TyError => { // safe for everything - Where(ty::Binder(Vec::new())) + Where(ty::Binder::dummy(Vec::new())) } ty::TyStr | ty::TySlice(_) | ty::TyDynamic(..) | ty::TyForeign(..) => Never, ty::TyTuple(tys) => { - Where(ty::Binder(tys.last().into_iter().cloned().collect())) + Where(ty::Binder::bind(tys.last().into_iter().cloned().collect())) } ty::TyAdt(def, substs) => { let sized_crit = def.sized_constraint(self.tcx()); // (*) binder moved here - Where(ty::Binder( + Where(ty::Binder::bind( sized_crit.iter().map(|ty| ty.subst(self.tcx(), substs)).collect() )) } @@ -2088,7 +2089,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { match self_ty.sty { ty::TyInfer(ty::IntVar(_)) | ty::TyInfer(ty::FloatVar(_)) | ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyError => { - Where(ty::Binder(Vec::new())) + Where(ty::Binder::dummy(Vec::new())) } ty::TyUint(_) | ty::TyInt(_) | ty::TyBool | ty::TyFloat(_) | @@ -2106,12 +2107,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ty::TyArray(element_ty, _) => { // (*) binder moved here - Where(ty::Binder(vec![element_ty])) + Where(ty::Binder::bind(vec![element_ty])) } ty::TyTuple(tys) => { // (*) binder moved here - Where(ty::Binder(tys.to_vec())) + Where(ty::Binder::bind(tys.to_vec())) } ty::TyClosure(def_id, substs) => { @@ -2119,7 +2120,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let is_copy_trait = Some(trait_id) == self.tcx().lang_items().copy_trait(); let is_clone_trait = Some(trait_id) == self.tcx().lang_items().clone_trait(); if is_copy_trait || is_clone_trait { - Where(ty::Binder(substs.upvar_tys(def_id, self.tcx()).collect())) + Where(ty::Binder::bind(substs.upvar_tys(def_id, self.tcx()).collect())) } else { Never } @@ -2260,7 +2261,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // 3. Re-bind the regions back to `for<'a> &'a int : Copy` types.skip_binder().into_iter().flat_map(|ty| { // binder moved -\ - let ty: ty::Binder<Ty<'tcx>> = ty::Binder(ty); // <----------/ + let ty: ty::Binder<Ty<'tcx>> = ty::Binder::bind(ty); // <----/ self.in_snapshot(|this, snapshot| { let (skol_ty, skol_map) = @@ -2450,18 +2451,19 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { /// 1. For each constituent type `Y` in `X`, `Y : Foo` holds /// 2. For each where-clause `C` declared on `Foo`, `[Self => X] C` holds. fn confirm_auto_impl_candidate(&mut self, - obligation: &TraitObligation<'tcx>, - trait_def_id: DefId) - -> VtableAutoImplData<PredicateObligation<'tcx>> + obligation: &TraitObligation<'tcx>, + trait_def_id: DefId) + -> VtableAutoImplData<PredicateObligation<'tcx>> { debug!("confirm_auto_impl_candidate({:?}, {:?})", obligation, trait_def_id); - // binder is moved below - let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty()); - let types = self.constituent_types_for_ty(self_ty); - self.vtable_auto_impl(obligation, trait_def_id, ty::Binder(types)) + let types = obligation.predicate.map_bound(|inner| { + let self_ty = self.infcx.shallow_resolve(inner.self_ty()); + self.constituent_types_for_ty(self_ty) + }); + self.vtable_auto_impl(obligation, trait_def_id, types) } /// See `confirm_auto_impl_candidate` @@ -2726,7 +2728,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { { debug!("confirm_closure_candidate({:?})", obligation); - let kind = match self.tcx().lang_items().fn_trait_kind(obligation.predicate.0.def_id()) { + let kind = match self.tcx().lang_items().fn_trait_kind(obligation.predicate.def_id()) { Some(k) => k, None => bug!("closure candidate for non-fn trait {:?}", obligation) }; @@ -2835,14 +2837,15 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // Trait+Kx+'a -> Trait+Ky+'b (upcasts). (&ty::TyDynamic(ref data_a, r_a), &ty::TyDynamic(ref data_b, r_b)) => { // See assemble_candidates_for_unsizing for more info. - // Binders reintroduced below in call to mk_existential_predicates. - let principal = data_a.skip_binder().principal(); - let iter = principal.into_iter().map(ty::ExistentialPredicate::Trait) - .chain(data_a.skip_binder().projection_bounds() - .map(|x| ty::ExistentialPredicate::Projection(x))) - .chain(data_b.auto_traits().map(ty::ExistentialPredicate::AutoTrait)); - let new_trait = tcx.mk_dynamic( - ty::Binder(tcx.mk_existential_predicates(iter)), r_b); + let existential_predicates = data_a.map_bound(|data_a| { + let principal = data_a.principal(); + let iter = principal.into_iter().map(ty::ExistentialPredicate::Trait) + .chain(data_a.projection_bounds() + .map(|x| ty::ExistentialPredicate::Projection(x))) + .chain(data_b.auto_traits().map(ty::ExistentialPredicate::AutoTrait)); + tcx.mk_existential_predicates(iter) + }); + let new_trait = tcx.mk_dynamic(existential_predicates, r_b); let InferOk { obligations, .. } = self.infcx.at(&obligation.cause, obligation.param_env) .eq(target, new_trait) @@ -2857,7 +2860,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { nested.push(Obligation::with_depth(cause, obligation.recursion_depth + 1, obligation.param_env, - ty::Binder(outlives).to_predicate())); + ty::Binder::bind(outlives).to_predicate())); } // T -> Trait. @@ -2900,7 +2903,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // If the type is `Foo+'a`, ensures that the type // being cast to `Foo+'a` outlives `'a`: let outlives = ty::OutlivesPredicate(source, r); - push(ty::Binder(outlives).to_predicate()); + push(ty::Binder::dummy(outlives).to_predicate()); } // [T; n] -> [T]. @@ -3201,18 +3204,19 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { -> ty::PolyTraitRef<'tcx> { let closure_type = self.infcx.closure_sig(closure_def_id, substs); - let ty::Binder((trait_ref, _)) = - self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(), - obligation.predicate.0.self_ty(), // (1) - closure_type, - util::TupleArgumentsFlag::No); + // (1) Feels icky to skip the binder here, but OTOH we know // that the self-type is an unboxed closure type and hence is // in fact unparameterized (or at least does not reference any // regions bound in the obligation). Still probably some // refactoring could make this nicer. - ty::Binder(trait_ref) + self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(), + obligation.predicate + .skip_binder().self_ty(), // (1) + closure_type, + util::TupleArgumentsFlag::No) + .map_bound(|(trait_ref, _)| trait_ref) } fn generator_trait_ref_unnormalized(&mut self, @@ -3222,17 +3226,18 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { -> ty::PolyTraitRef<'tcx> { let gen_sig = substs.generator_poly_sig(closure_def_id, self.tcx()); - let ty::Binder((trait_ref, ..)) = - self.tcx().generator_trait_ref_and_outputs(obligation.predicate.def_id(), - obligation.predicate.0.self_ty(), // (1) - gen_sig); + // (1) Feels icky to skip the binder here, but OTOH we know // that the self-type is an generator type and hence is // in fact unparameterized (or at least does not reference any // regions bound in the obligation). Still probably some // refactoring could make this nicer. - ty::Binder(trait_ref) + self.tcx().generator_trait_ref_and_outputs(obligation.predicate.def_id(), + obligation.predicate + .skip_binder().self_ty(), // (1) + gen_sig) + .map_bound(|(trait_ref, ..)| trait_ref) } /// Returns the obligations that are implied by instantiating an diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 31c5bf1bbad..1e3e4160de1 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -491,6 +491,7 @@ impl<'tcx> fmt::Display for traits::Goal<'tcx> { // FIXME: appropriate binder names write!(fmt, "{}<> {{ {} }}", qkind, goal.skip_binder()) } + CannotProve => write!(fmt, "CannotProve"), } } } @@ -557,6 +558,7 @@ EnumTypeFoldableImpl! { (traits::Goal::Not)(goal), (traits::Goal::DomainGoal)(domain_goal), (traits::Goal::Quantified)(qkind, goal), + (traits::Goal::CannotProve), } } diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 9e38911f53c..3c62f04afc5 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -209,13 +209,13 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> { None } else { Some(ty::Predicate::RegionOutlives( - ty::Binder(ty::OutlivesPredicate(r, r_min)))) + ty::Binder::dummy(ty::OutlivesPredicate(r, r_min)))) }, Component::Param(p) => { let ty = tcx.mk_param(p.idx, p.name); Some(ty::Predicate::TypeOutlives( - ty::Binder(ty::OutlivesPredicate(ty, r_min)))) + ty::Binder::dummy(ty::OutlivesPredicate(ty, r_min)))) }, Component::UnresolvedInferenceVariable(_) => { @@ -514,7 +514,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { def_id: fn_trait_def_id, substs: self.mk_substs_trait(self_ty, &[arguments_tuple]), }; - ty::Binder((trait_ref, sig.skip_binder().output())) + ty::Binder::bind((trait_ref, sig.skip_binder().output())) } pub fn generator_trait_ref_and_outputs(self, @@ -527,7 +527,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { def_id: fn_trait_def_id, substs: self.mk_substs_trait(self_ty, &[]), }; - ty::Binder((trait_ref, sig.skip_binder().yield_ty, sig.skip_binder().return_ty)) + ty::Binder::bind((trait_ref, sig.skip_binder().yield_ty, sig.skip_binder().return_ty)) } pub fn impl_is_default(self, node_item_def_id: DefId) -> bool { diff --git a/src/librustc/ty/_match.rs b/src/librustc/ty/_match.rs index f86c1cf0dd6..047bfcc8c6f 100644 --- a/src/librustc/ty/_match.rs +++ b/src/librustc/ty/_match.rs @@ -92,6 +92,6 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Match<'a, 'gcx, 'tcx> { -> RelateResult<'tcx, ty::Binder<T>> where T: Relate<'tcx> { - Ok(ty::Binder(self.relate(a.skip_binder(), b.skip_binder())?)) + Ok(ty::Binder::bind(self.relate(a.skip_binder(), b.skip_binder())?)) } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 28ad5edbd2d..c35f515a99e 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -38,7 +38,7 @@ use ty::subst::{Kind, Substs}; use ty::ReprOptions; use ty::Instance; use traits; -use traits::{Clause, Goal}; +use traits::{Clause, Clauses, Goal, Goals}; use ty::{self, Ty, TypeAndMut}; use ty::{TyS, TypeVariants, Slice}; use ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorInterior, Region, Const}; @@ -1562,6 +1562,7 @@ impl<'gcx: 'tcx, 'tcx> GlobalCtxt<'gcx> { tcx, query: icx.query.clone(), layout_depth: icx.layout_depth, + task: icx.task, }; ty::tls::enter_context(&new_icx, |new_icx| { f(new_icx.tcx) @@ -1741,6 +1742,7 @@ pub mod tls { use errors::{Diagnostic, TRACK_DIAGNOSTICS}; use rustc_data_structures::OnDrop; use rustc_data_structures::sync::Lrc; + use dep_graph::OpenTask; /// This is the implicit state of rustc. It contains the current /// TyCtxt and query. It is updated when creating a local interner or @@ -1759,6 +1761,10 @@ pub mod tls { /// Used to prevent layout from recursing too deeply. pub layout_depth: usize, + + /// The current dep graph task. This is used to add dependencies to queries + /// when executing them + pub task: &'a OpenTask, } // A thread local value which stores a pointer to the current ImplicitCtxt @@ -1845,6 +1851,7 @@ pub mod tls { tcx, query: None, layout_depth: 0, + task: &OpenTask::Ignore, }; enter_context(&icx, |_| { f(tcx) @@ -2374,6 +2381,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.intern_tup(&[]) } + pub fn mk_diverging_default(self) -> Ty<'tcx> { + if self.features().never_type { + self.types.never + } else { + self.intern_tup(&[]) + } + } + pub fn mk_bool(self) -> Ty<'tcx> { self.mk_ty(TyBool) } @@ -2509,7 +2524,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - pub fn intern_clauses(self, ts: &[Clause<'tcx>]) -> &'tcx Slice<Clause<'tcx>> { + pub fn intern_clauses(self, ts: &[Clause<'tcx>]) -> Clauses<'tcx> { if ts.len() == 0 { Slice::empty() } else { @@ -2517,7 +2532,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - pub fn intern_goals(self, ts: &[Goal<'tcx>]) -> &'tcx Slice<Goal<'tcx>> { + pub fn intern_goals(self, ts: &[Goal<'tcx>]) -> Goals<'tcx> { if ts.len() == 0 { Slice::empty() } else { @@ -2571,13 +2586,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.mk_substs(iter::once(s).chain(t.into_iter().cloned()).map(Kind::from)) } - pub fn mk_clauses<I: InternAs<[Clause<'tcx>], - &'tcx Slice<Clause<'tcx>>>>(self, iter: I) -> I::Output { + pub fn mk_clauses<I: InternAs<[Clause<'tcx>], Clauses<'tcx>>>(self, iter: I) -> I::Output { iter.intern_with(|xs| self.intern_clauses(xs)) } - pub fn mk_goals<I: InternAs<[Goal<'tcx>], - &'tcx Slice<Goal<'tcx>>>>(self, iter: I) -> I::Output { + pub fn mk_goals<I: InternAs<[Goal<'tcx>], Goals<'tcx>>>(self, iter: I) -> I::Output { iter.intern_with(|xs| self.intern_goals(xs)) } diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 8071cd0c639..eb06852c65d 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -394,7 +394,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } }); - Binder(value) + Binder::bind(value) } /// Returns a set of all late-bound regions that are constrained @@ -446,7 +446,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { where T : TypeFoldable<'tcx>, { let mut counter = 0; - Binder(self.replace_late_bound_regions(sig, |_| { + Binder::bind(self.replace_late_bound_regions(sig, |_| { counter += 1; self.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrAnon(counter))) }).0) diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 76f7a0b59a2..02a03bc542a 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -259,7 +259,7 @@ fn resolve_associated_item<'a, 'tcx>( def_id, trait_id, rcvr_substs); let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs); - let vtbl = tcx.trans_fulfill_obligation((param_env, ty::Binder(trait_ref))); + let vtbl = tcx.trans_fulfill_obligation((param_env, ty::Binder::bind(trait_ref))); // Now that we know which impl is being used, we can dispatch to // the actual function: diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 8189064db69..2819141c81b 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -204,6 +204,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // finer-grained distinctions, e.g. between enum/struct). data @ DefPathData::Misc | data @ DefPathData::TypeNs(..) | + data @ DefPathData::Trait(..) | + data @ DefPathData::AssocTypeInTrait(..) | + data @ DefPathData::AssocTypeInImpl(..) | data @ DefPathData::ValueNs(..) | data @ DefPathData::Module(..) | data @ DefPathData::TypeParam(..) | diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs index 664c84f5986..735fe06560f 100644 --- a/src/librustc/ty/maps/config.rs +++ b/src/librustc/ty/maps/config.rs @@ -283,12 +283,6 @@ impl<'tcx> QueryDescription<'tcx> for queries::trait_of_item<'tcx> { } } -impl<'tcx> QueryDescription<'tcx> for queries::item_body_nested_bodies<'tcx> { - fn describe(tcx: TyCtxt, def_id: DefId) -> String { - format!("nested item bodies of `{}`", tcx.item_path_str(def_id)) - } -} - impl<'tcx> QueryDescription<'tcx> for queries::const_is_rvalue_promotable_to_static<'tcx> { fn describe(tcx: TyCtxt, def_id: DefId) -> String { format!("const checking if rvalue is promotable to static `{}`", @@ -723,6 +717,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::program_clauses_for<'tcx> { } } +impl<'tcx> QueryDescription<'tcx> for queries::program_clauses_for_env<'tcx> { + fn describe(_tcx: TyCtxt, _: ty::ParamEnv<'tcx>) -> String { + format!("generating chalk-style clauses for param env") + } +} + impl<'tcx> QueryDescription<'tcx> for queries::wasm_import_module_map<'tcx> { fn describe(_tcx: TyCtxt, _: CrateNum) -> String { format!("wasm import module map") diff --git a/src/librustc/ty/maps/keys.rs b/src/librustc/ty/maps/keys.rs index b8167ec9186..72f2cb49abc 100644 --- a/src/librustc/ty/maps/keys.rs +++ b/src/librustc/ty/maps/keys.rs @@ -154,6 +154,15 @@ impl<'tcx> Key for Ty<'tcx> { } } +impl<'tcx> Key for ty::ParamEnv<'tcx> { + fn map_crate(&self) -> CrateNum { + LOCAL_CRATE + } + fn default_span(&self, _: TyCtxt) -> Span { + DUMMY_SP + } +} + impl<'tcx, T: Key> Key for ty::ParamEnvAnd<'tcx, T> { fn map_crate(&self) -> CrateNum { self.value.map_crate() diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index 2325b1893d9..92d23d4338f 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -17,9 +17,8 @@ use hir::svh::Svh; use infer::canonical::{self, Canonical}; use lint; use middle::borrowck::BorrowCheckResult; -use middle::cstore::{ExternCrate, LinkagePreference, NativeLibrary, - ExternBodyNestedBodies, ForeignModule}; -use middle::cstore::{NativeLibraryKind, DepKind, CrateSource, ExternConstBody}; +use middle::cstore::{ExternCrate, LinkagePreference, NativeLibrary, ForeignModule}; +use middle::cstore::{NativeLibraryKind, DepKind, CrateSource}; use middle::privacy::AccessLevels; use middle::reachable::ReachableSet; use middle::region; @@ -38,8 +37,8 @@ use traits::query::{CanonicalProjectionGoal, CanonicalTyGoal, NoSolution}; use traits::query::dropck_outlives::{DtorckConstraint, DropckOutlivesResult}; use traits::query::normalize::NormalizationResult; use traits::specialization_graph; -use traits::Clause; -use ty::{self, CrateInherentImpls, ParamEnvAnd, Slice, Ty, TyCtxt}; +use traits::Clauses; +use ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt}; use ty::steal::Steal; use ty::subst::Substs; use util::nodemap::{DefIdSet, DefIdMap, ItemLocalSet}; @@ -254,9 +253,11 @@ define_maps! { <'tcx> [] fn item_attrs: ItemAttrs(DefId) -> Lrc<[ast::Attribute]>, [] fn trans_fn_attrs: trans_fn_attrs(DefId) -> TransFnAttrs, [] fn fn_arg_names: FnArgNames(DefId) -> Vec<ast::Name>, + /// Gets the rendered value of the specified constant or associated constant. + /// Used by rustdoc. + [] fn rendered_const: RenderedConst(DefId) -> String, [] fn impl_parent: ImplParent(DefId) -> Option<DefId>, [] fn trait_of_item: TraitOfItem(DefId) -> Option<DefId>, - [] fn item_body_nested_bodies: ItemBodyNestedBodies(DefId) -> ExternBodyNestedBodies, [] fn const_is_rvalue_promotable_to_static: ConstIsRvaluePromotableToStatic(DefId) -> bool, [] fn rvalue_promotable_map: RvaluePromotableMap(DefId) -> Lrc<ItemLocalSet>, [] fn is_mir_available: IsMirAvailable(DefId) -> bool, @@ -376,7 +377,6 @@ define_maps! { <'tcx> [] fn get_lang_items: get_lang_items_node(CrateNum) -> Lrc<LanguageItems>, [] fn defined_lang_items: DefinedLangItems(CrateNum) -> Lrc<Vec<(DefId, usize)>>, [] fn missing_lang_items: MissingLangItems(CrateNum) -> Lrc<Vec<LangItem>>, - [] fn extern_const_body: ExternConstBody(DefId) -> ExternConstBody<'tcx>, [] fn visible_parent_map: visible_parent_map_node(CrateNum) -> Lrc<DefIdMap<DefId>>, [] fn missing_extern_crate_item: MissingExternCrateItem(CrateNum) -> bool, @@ -445,7 +445,11 @@ define_maps! { <'tcx> [] fn features_query: features_node(CrateNum) -> Lrc<feature_gate::Features>, - [] fn program_clauses_for: ProgramClausesFor(DefId) -> Lrc<&'tcx Slice<Clause<'tcx>>>, + [] fn program_clauses_for: ProgramClausesFor(DefId) -> Clauses<'tcx>, + + [] fn program_clauses_for_env: ProgramClausesForEnv( + ty::ParamEnv<'tcx> + ) -> Clauses<'tcx>, [] fn wasm_custom_sections: WasmCustomSections(CrateNum) -> Lrc<Vec<DefId>>, [] fn wasm_import_module_map: WasmImportModuleMap(CrateNum) diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 4f6925938c8..61a4eb58531 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -530,6 +530,7 @@ macro_rules! define_maps { tcx, query: Some(job.clone()), layout_depth: icx.layout_depth, + task: icx.task, }; // Use the ImplicitCtxt while we execute the query @@ -978,6 +979,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::DropckOutlives | DepKind::SubstituteNormalizeAndTestPredicates | DepKind::InstanceDefSizeEstimate | + DepKind::ProgramClausesForEnv | // This one should never occur in this context DepKind::Null => { @@ -1048,7 +1050,6 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::LookupDeprecationEntry => { force!(lookup_deprecation_entry, def_id!()); } - DepKind::ItemBodyNestedBodies => { force!(item_body_nested_bodies, def_id!()); } DepKind::ConstIsRvaluePromotableToStatic => { force!(const_is_rvalue_promotable_to_static, def_id!()); } @@ -1063,6 +1064,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::ItemAttrs => { force!(item_attrs, def_id!()); } DepKind::TransFnAttrs => { force!(trans_fn_attrs, def_id!()); } DepKind::FnArgNames => { force!(fn_arg_names, def_id!()); } + DepKind::RenderedConst => { force!(rendered_const, def_id!()); } DepKind::DylibDepFormats => { force!(dylib_dependency_formats, krate!()); } DepKind::IsPanicRuntime => { force!(is_panic_runtime, krate!()); } DepKind::IsCompilerBuiltins => { force!(is_compiler_builtins, krate!()); } @@ -1119,7 +1121,6 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::GetLangItems => { force!(get_lang_items, LOCAL_CRATE); } DepKind::DefinedLangItems => { force!(defined_lang_items, krate!()); } DepKind::MissingLangItems => { force!(missing_lang_items, krate!()); } - DepKind::ExternConstBody => { force!(extern_const_body, def_id!()); } DepKind::VisibleParentMap => { force!(visible_parent_map, LOCAL_CRATE); } DepKind::MissingExternCrateItem => { force!(missing_extern_crate_item, krate!()); diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 2a10720f074..de043668410 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1048,18 +1048,18 @@ impl<'a, 'gcx, 'tcx> Predicate<'tcx> { // from the substitution and the value being substituted into, and // this trick achieves that). - let substs = &trait_ref.0.substs; + let substs = &trait_ref.skip_binder().substs; match *self { - Predicate::Trait(ty::Binder(ref data)) => - Predicate::Trait(ty::Binder(data.subst(tcx, substs))), - Predicate::Subtype(ty::Binder(ref data)) => - Predicate::Subtype(ty::Binder(data.subst(tcx, substs))), - Predicate::RegionOutlives(ty::Binder(ref data)) => - Predicate::RegionOutlives(ty::Binder(data.subst(tcx, substs))), - Predicate::TypeOutlives(ty::Binder(ref data)) => - Predicate::TypeOutlives(ty::Binder(data.subst(tcx, substs))), - Predicate::Projection(ty::Binder(ref data)) => - Predicate::Projection(ty::Binder(data.subst(tcx, substs))), + Predicate::Trait(ref binder) => + Predicate::Trait(binder.map_bound(|data| data.subst(tcx, substs))), + Predicate::Subtype(ref binder) => + Predicate::Subtype(binder.map_bound(|data| data.subst(tcx, substs))), + Predicate::RegionOutlives(ref binder) => + Predicate::RegionOutlives(binder.map_bound(|data| data.subst(tcx, substs))), + Predicate::TypeOutlives(ref binder) => + Predicate::TypeOutlives(binder.map_bound(|data| data.subst(tcx, substs))), + Predicate::Projection(ref binder) => + Predicate::Projection(binder.map_bound(|data| data.subst(tcx, substs))), Predicate::WellFormed(data) => Predicate::WellFormed(data.subst(tcx, substs)), Predicate::ObjectSafe(trait_def_id) => @@ -1095,7 +1095,7 @@ impl<'tcx> TraitPredicate<'tcx> { impl<'tcx> PolyTraitPredicate<'tcx> { pub fn def_id(&self) -> DefId { // ok to skip binder since trait def-id does not care about regions - self.0.def_id() + self.skip_binder().def_id() } } @@ -1138,17 +1138,31 @@ pub struct ProjectionPredicate<'tcx> { pub type PolyProjectionPredicate<'tcx> = Binder<ProjectionPredicate<'tcx>>; impl<'tcx> PolyProjectionPredicate<'tcx> { + /// Returns the def-id of the associated item being projected. + pub fn item_def_id(&self) -> DefId { + self.skip_binder().projection_ty.item_def_id + } + pub fn to_poly_trait_ref(&self, tcx: TyCtxt) -> PolyTraitRef<'tcx> { // Note: unlike with TraitRef::to_poly_trait_ref(), // self.0.trait_ref is permitted to have escaping regions. // This is because here `self` has a `Binder` and so does our // return value, so we are preserving the number of binding // levels. - ty::Binder(self.0.projection_ty.trait_ref(tcx)) + self.map_bound(|predicate| predicate.projection_ty.trait_ref(tcx)) } pub fn ty(&self) -> Binder<Ty<'tcx>> { - Binder(self.skip_binder().ty) // preserves binding levels + self.map_bound(|predicate| predicate.ty) + } + + /// The DefId of the TraitItem for the associated type. + /// + /// Note that this is not the DefId of the TraitRef containing this + /// associated type, which is in tcx.associated_item(projection_def_id()).container. + pub fn projection_def_id(&self) -> DefId { + // ok to skip binder since trait def-id does not care about regions + self.skip_binder().projection_ty.item_def_id } } @@ -1158,8 +1172,7 @@ pub trait ToPolyTraitRef<'tcx> { impl<'tcx> ToPolyTraitRef<'tcx> for TraitRef<'tcx> { fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> { - assert!(!self.has_escaping_regions()); - ty::Binder(self.clone()) + ty::Binder::dummy(self.clone()) } } @@ -1175,12 +1188,7 @@ pub trait ToPredicate<'tcx> { impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> { fn to_predicate(&self) -> Predicate<'tcx> { - // we're about to add a binder, so let's check that we don't - // accidentally capture anything, or else that might be some - // weird debruijn accounting. - assert!(!self.has_escaping_regions()); - - ty::Predicate::Trait(ty::Binder(ty::TraitPredicate { + ty::Predicate::Trait(ty::Binder::dummy(ty::TraitPredicate { trait_ref: self.clone() })) } @@ -1219,17 +1227,19 @@ impl<'tcx> Predicate<'tcx> { ty::Predicate::Trait(ref data) => { data.skip_binder().input_types().collect() } - ty::Predicate::Subtype(ty::Binder(SubtypePredicate { a, b, a_is_expected: _ })) => { + ty::Predicate::Subtype(binder) => { + let SubtypePredicate { a, b, a_is_expected: _ } = binder.skip_binder(); vec![a, b] } - ty::Predicate::TypeOutlives(ty::Binder(ref data)) => { - vec![data.0] + ty::Predicate::TypeOutlives(binder) => { + vec![binder.skip_binder().0] } ty::Predicate::RegionOutlives(..) => { vec![] } ty::Predicate::Projection(ref data) => { - data.0.projection_ty.substs.types().chain(Some(data.0.ty)).collect() + let inner = data.skip_binder(); + inner.projection_ty.substs.types().chain(Some(inner.ty)).collect() } ty::Predicate::WellFormed(data) => { vec![data] @@ -2091,7 +2101,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { Some(x) => x, _ => return vec![ty] }; - let sized_predicate = Binder(TraitRef { + let sized_predicate = Binder::dummy(TraitRef { def_id: sized_trait, substs: tcx.mk_substs_trait(ty, &[]) }).to_predicate(); diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 36eb3e3f94c..348cf03dd87 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -431,10 +431,10 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, { // Wrap our types with a temporary GeneratorWitness struct // inside the binder so we can related them - let a_types = ty::Binder(GeneratorWitness(*a_types.skip_binder())); - let b_types = ty::Binder(GeneratorWitness(*b_types.skip_binder())); + let a_types = a_types.map_bound(GeneratorWitness); + let b_types = b_types.map_bound(GeneratorWitness); // Then remove the GeneratorWitness for the result - let types = ty::Binder(relation.relate(&a_types, &b_types)?.skip_binder().0); + let types = relation.relate(&a_types, &b_types)?.map_bound(|witness| witness.0); Ok(tcx.mk_generator_witness(types)) } diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 7b4b7082bb6..199a46678c8 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -270,7 +270,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::Predicate<'a> { impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for ty::Binder<T> { type Lifted = ty::Binder<T::Lifted>; fn lift_to_tcx<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Self::Lifted> { - tcx.lift(&self.0).map(|x| ty::Binder(x)) + tcx.lift(self.skip_binder()).map(ty::Binder::bind) } } @@ -720,7 +720,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Vec<T> { impl<'tcx, T:TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<T> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - ty::Binder(self.0.fold_with(folder)) + self.map_bound_ref(|ty| ty.fold_with(folder)) } fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { @@ -728,7 +728,7 @@ impl<'tcx, T:TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<T> { } fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool { - self.0.visit_with(visitor) + self.skip_binder().visit_with(visitor) } fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool { diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 310fcbcfcb3..92e879a584b 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -345,7 +345,7 @@ impl<'tcx> ClosureSubsts<'tcx> { /// binder, but it never contains bound regions. Probably this /// function should be removed. pub fn generator_poly_sig(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> PolyGenSig<'tcx> { - ty::Binder(self.generator_sig(def_id, tcx)) + ty::Binder::dummy(self.generator_sig(def_id, tcx)) } /// Return the "generator signature", which consists of its yield @@ -504,13 +504,13 @@ impl<'tcx> Slice<ExistentialPredicate<'tcx>> { impl<'tcx> Binder<&'tcx Slice<ExistentialPredicate<'tcx>>> { pub fn principal(&self) -> Option<PolyExistentialTraitRef<'tcx>> { - self.skip_binder().principal().map(Binder) + self.skip_binder().principal().map(Binder::bind) } #[inline] pub fn projection_bounds<'a>(&'a self) -> impl Iterator<Item=PolyExistentialProjection<'tcx>> + 'a { - self.skip_binder().projection_bounds().map(Binder) + self.skip_binder().projection_bounds().map(Binder::bind) } #[inline] @@ -520,7 +520,7 @@ impl<'tcx> Binder<&'tcx Slice<ExistentialPredicate<'tcx>>> { pub fn iter<'a>(&'a self) -> impl DoubleEndedIterator<Item=Binder<ExistentialPredicate<'tcx>>> + 'tcx { - self.skip_binder().iter().cloned().map(Binder) + self.skip_binder().iter().cloned().map(Binder::bind) } } @@ -567,26 +567,16 @@ pub type PolyTraitRef<'tcx> = Binder<TraitRef<'tcx>>; impl<'tcx> PolyTraitRef<'tcx> { pub fn self_ty(&self) -> Ty<'tcx> { - self.0.self_ty() + self.skip_binder().self_ty() } pub fn def_id(&self) -> DefId { - self.0.def_id - } - - pub fn substs(&self) -> &'tcx Substs<'tcx> { - // FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<> - self.0.substs - } - - pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a { - // FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<> - self.0.input_types() + self.skip_binder().def_id } pub fn to_poly_trait_predicate(&self) -> ty::PolyTraitPredicate<'tcx> { // Note that we preserve binding levels - Binder(ty::TraitPredicate { trait_ref: self.0.clone() }) + Binder(ty::TraitPredicate { trait_ref: self.skip_binder().clone() }) } } @@ -633,12 +623,7 @@ pub type PolyExistentialTraitRef<'tcx> = Binder<ExistentialTraitRef<'tcx>>; impl<'tcx> PolyExistentialTraitRef<'tcx> { pub fn def_id(&self) -> DefId { - self.0.def_id - } - - pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a { - // FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<> - self.0.input_types() + self.skip_binder().def_id } } @@ -650,7 +635,7 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> { /// type from `Binder<T>` to just `T` (see /// e.g. `liberate_late_bound_regions`). #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] -pub struct Binder<T>(pub T); +pub struct Binder<T>(T); impl<T> Binder<T> { /// Wraps `value` in a binder, asserting that `value` does not @@ -664,6 +649,12 @@ impl<T> Binder<T> { Binder(value) } + /// Wraps `value` in a binder, binding late-bound regions (if any). + pub fn bind<'tcx>(value: T) -> Binder<T> + { + Binder(value) + } + /// Skips the binder and returns the "bound" value. This is a /// risky thing to do because it's easy to get confused about /// debruijn indices and the like. It is usually better to @@ -685,7 +676,7 @@ impl<T> Binder<T> { } pub fn as_ref(&self) -> Binder<&T> { - ty::Binder(&self.0) + Binder(&self.0) } pub fn map_bound_ref<F, U>(&self, f: F) -> Binder<U> @@ -697,7 +688,7 @@ impl<T> Binder<T> { pub fn map_bound<F, U>(self, f: F) -> Binder<U> where F: FnOnce(T) -> U { - ty::Binder(f(self.0)) + Binder(f(self.0)) } /// Unwraps and returns the value within, but only if it contains @@ -730,7 +721,7 @@ impl<T> Binder<T> { pub fn fuse<U,F,R>(self, u: Binder<U>, f: F) -> Binder<R> where F: FnOnce(T, U) -> R { - ty::Binder(f(self.0, u.0)) + Binder(f(self.0, u.0)) } /// Split the contents into two things that share the same binder @@ -743,7 +734,7 @@ impl<T> Binder<T> { where F: FnOnce(T) -> (U, V) { let (u, v) = f(self.0); - (ty::Binder(u), ty::Binder(v)) + (Binder(u), Binder(v)) } } @@ -839,7 +830,7 @@ pub type PolyFnSig<'tcx> = Binder<FnSig<'tcx>>; impl<'tcx> PolyFnSig<'tcx> { pub fn inputs(&self) -> Binder<&'tcx [Ty<'tcx>]> { - Binder(self.skip_binder().inputs()) + self.map_bound_ref(|fn_sig| fn_sig.inputs()) } pub fn input(&self, index: usize) -> ty::Binder<Ty<'tcx>> { self.map_bound_ref(|fn_sig| fn_sig.inputs()[index]) @@ -1152,6 +1143,10 @@ impl<'a, 'tcx, 'gcx> PolyExistentialProjection<'tcx> { -> ty::PolyProjectionPredicate<'tcx> { self.map_bound(|p| p.with_self_ty(tcx, self_ty)) } + + pub fn item_def_id(&self) -> DefId { + return self.skip_binder().item_def_id; + } } impl DebruijnIndex { diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 77eff49d19f..b23e9124ddc 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -380,7 +380,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { ty::Predicate::ConstEvaluatable(..) => { None } - ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(t, r))) => { + ty::Predicate::TypeOutlives(predicate) => { // Search for a bound of the form `erased_self_ty // : 'a`, but be wary of something like `for<'a> // erased_self_ty : 'a` (we interpret a @@ -390,8 +390,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // it's kind of a moot point since you could never // construct such an object, but this seems // correct even if that code changes). - if t == erased_self_ty && !r.has_escaping_regions() { - Some(r) + let ty::OutlivesPredicate(ref t, ref r) = predicate.skip_binder(); + if t == &erased_self_ty && !r.has_escaping_regions() { + Some(*r) } else { None } @@ -561,7 +562,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { ty::ClosureKind::FnMut => self.mk_mut_ref(self.mk_region(env_region), closure_ty), ty::ClosureKind::FnOnce => closure_ty, }; - Some(ty::Binder(env_ty)) + Some(ty::Binder::bind(env_ty)) } /// Given the def-id of some item that has no type parameters, make diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index f05d56c9d83..aea84791fe8 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -307,7 +307,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { cause, param_env, ty::Predicate::TypeOutlives( - ty::Binder( + ty::Binder::dummy( ty::OutlivesPredicate(mt.ty, r))))); } } @@ -492,7 +492,8 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { for implicit_bound in implicit_bounds { let cause = self.cause(traits::ObjectTypeBound(ty, explicit_bound)); - let outlives = ty::Binder(ty::OutlivesPredicate(explicit_bound, implicit_bound)); + let outlives = ty::Binder::dummy( + ty::OutlivesPredicate(explicit_bound, implicit_bound)); self.out.push(traits::Obligation::new(cause, self.param_env, outlives.to_predicate())); diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index dd478967b18..efe83252d0f 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -268,14 +268,31 @@ impl PrintContext { loop { let key = tcx.def_key(item_def_id); match key.disambiguated_data.data { + DefPathData::AssocTypeInTrait(_) | + DefPathData::AssocTypeInImpl(_) | + DefPathData::Trait(_) | DefPathData::TypeNs(_) => { break; } - DefPathData::ValueNs(_) | DefPathData::EnumVariant(_) => { + DefPathData::ValueNs(_) | + DefPathData::EnumVariant(_) => { is_value_path = true; break; } - _ => { + DefPathData::CrateRoot | + DefPathData::Misc | + DefPathData::Impl | + DefPathData::Module(_) | + DefPathData::MacroDef(_) | + DefPathData::ClosureExpr | + DefPathData::TypeParam(_) | + DefPathData::LifetimeDef(_) | + DefPathData::Field(_) | + DefPathData::StructCtor | + DefPathData::Initializer | + DefPathData::ImplTrait | + DefPathData::Typeof | + DefPathData::GlobalMetaData(_) => { // if we're making a symbol for something, there ought // to be a value or type-def or something in there // *somewhere* @@ -456,7 +473,7 @@ impl PrintContext { let value = if let Some(v) = lifted { v } else { - return original.0.print_display(f, self); + return original.skip_binder().print_display(f, self); }; if self.binder_depth == 0 { @@ -662,9 +679,9 @@ define_print! { ty::tls::with(|tcx| { let dummy_self = tcx.mk_infer(ty::FreshTy(0)); - let trait_ref = tcx.lift(&ty::Binder(*self)) + let trait_ref = *tcx.lift(&ty::Binder::bind(*self)) .expect("could not lift TraitRef for printing") - .with_self_ty(tcx, dummy_self).0; + .with_self_ty(tcx, dummy_self).skip_binder(); cx.parameterized(f, trait_ref.substs, trait_ref.def_id, &[]) }) } diff --git a/src/librustc_allocator/expand.rs b/src/librustc_allocator/expand.rs index ffd02108c27..9338d000c12 100644 --- a/src/librustc_allocator/expand.rs +++ b/src/librustc_allocator/expand.rs @@ -245,7 +245,7 @@ impl<'a> AllocFnFactory<'a> { self.cx.expr_ident(self.span, ident) } - AllocatorTy::ResultPtr | AllocatorTy::Bang | AllocatorTy::Unit => { + AllocatorTy::ResultPtr | AllocatorTy::Unit => { panic!("can't convert AllocatorTy to an argument") } } @@ -262,8 +262,6 @@ impl<'a> AllocFnFactory<'a> { (self.ptr_u8(), expr) } - AllocatorTy::Bang => (self.cx.ty(self.span, TyKind::Never), expr), - AllocatorTy::Unit => (self.cx.ty(self.span, TyKind::Tup(Vec::new())), expr), AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => { diff --git a/src/librustc_allocator/lib.rs b/src/librustc_allocator/lib.rs index 706eab72d44..969086815de 100644 --- a/src/librustc_allocator/lib.rs +++ b/src/librustc_allocator/lib.rs @@ -24,11 +24,6 @@ pub static ALLOCATOR_METHODS: &[AllocatorMethod] = &[ output: AllocatorTy::ResultPtr, }, AllocatorMethod { - name: "oom", - inputs: &[], - output: AllocatorTy::Bang, - }, - AllocatorMethod { name: "dealloc", inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout], output: AllocatorTy::Unit, @@ -52,7 +47,6 @@ pub struct AllocatorMethod { } pub enum AllocatorTy { - Bang, Layout, Ptr, ResultPtr, diff --git a/src/librustc_apfloat/lib.rs b/src/librustc_apfloat/lib.rs index 0f051ea5981..08438805a70 100644 --- a/src/librustc_apfloat/lib.rs +++ b/src/librustc_apfloat/lib.rs @@ -45,6 +45,7 @@ html_root_url = "https://doc.rust-lang.org/nightly/")] #![forbid(unsafe_code)] +#![feature(try_from)] // See librustc_cratesio_shim/Cargo.toml for a comment explaining this. #[allow(unused_extern_crates)] extern crate rustc_cratesio_shim; diff --git a/src/librustc_back/target/android_base.rs b/src/librustc_back/target/android_base.rs index 49baa1b96ce..3660bf7bea9 100644 --- a/src/librustc_back/target/android_base.rs +++ b/src/librustc_back/target/android_base.rs @@ -20,5 +20,6 @@ pub fn opts() -> TargetOptions { base.is_like_android = true; base.position_independent_executables = true; base.has_elf_tls = false; + base.requires_uwtable = true; base } diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index 592b27ac641..e46266b576e 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -481,6 +481,11 @@ pub struct TargetOptions { /// Whether a .debug_gdb_scripts section will be added to the output object file pub emit_debug_gdb_scripts: bool, + + /// Whether or not to unconditionally `uwtable` attributes on functions, + /// typically because the platform needs to unwind for things like stack + /// unwinders. + pub requires_uwtable: bool, } impl Default for TargetOptions { @@ -554,6 +559,7 @@ impl Default for TargetOptions { default_hidden_visibility: false, embed_bitcode: false, emit_debug_gdb_scripts: true, + requires_uwtable: false, } } } @@ -804,6 +810,7 @@ impl Target { key!(default_hidden_visibility, bool); key!(embed_bitcode, bool); key!(emit_debug_gdb_scripts, bool); + key!(requires_uwtable, bool); if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) { for name in array.iter().filter_map(|abi| abi.as_string()) { @@ -1008,6 +1015,7 @@ impl ToJson for Target { target_option_val!(default_hidden_visibility); target_option_val!(embed_bitcode); target_option_val!(emit_debug_gdb_scripts); + target_option_val!(requires_uwtable); if default.abi_blacklist != self.options.abi_blacklist { d.insert("abi-blacklist".to_string(), self.options.abi_blacklist.iter() diff --git a/src/librustc_back/target/windows_base.rs b/src/librustc_back/target/windows_base.rs index 971b21e062f..4b4fb27caa8 100644 --- a/src/librustc_back/target/windows_base.rs +++ b/src/librustc_back/target/windows_base.rs @@ -103,6 +103,7 @@ pub fn opts() -> TargetOptions { custom_unwind_resume: true, abi_return_struct_as_int: true, emit_debug_gdb_scripts: false, + requires_uwtable: true, .. Default::default() } diff --git a/src/librustc_back/target/windows_msvc_base.rs b/src/librustc_back/target/windows_msvc_base.rs index 06e879bec34..fee5a0284c8 100644 --- a/src/librustc_back/target/windows_msvc_base.rs +++ b/src/librustc_back/target/windows_msvc_base.rs @@ -35,6 +35,7 @@ pub fn opts() -> TargetOptions { crt_static_respected: true, abi_return_struct_as_int: true, emit_debug_gdb_scripts: false, + requires_uwtable: true, .. Default::default() } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index f8c0289cc98..2fb811eba1e 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -691,7 +691,7 @@ where krate, &sess.parse_sess, sess.opts.test, - sess.opts.debugging_opts.edition, + sess.edition(), ); // these need to be set "early" so that expansion sees `quote` if enabled. sess.init_features(features); @@ -1155,6 +1155,10 @@ where } }); + time(sess, "dumping chalk-like clauses", || { + rustc_traits::lowering::dump_program_clauses(tcx); + }); + time(sess, "MIR effect checking", || { for def_id in tcx.body_owners() { mir::transform::check_unsafety::check_unsafety(tcx, def_id) @@ -1178,10 +1182,6 @@ where time(sess, "lint checking", || lint::check_crate(tcx)); - time(sess, "dumping chalk-like clauses", || { - rustc_traits::lowering::dump_program_clauses(tcx) - }); - return Ok(f(tcx, analysis, rx, tcx.sess.compile_status())); }, ) diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 04f6503d92d..83501f45ec0 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -284,7 +284,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { } pub fn t_fn(&self, input_tys: &[Ty<'tcx>], output_ty: Ty<'tcx>) -> Ty<'tcx> { - self.infcx.tcx.mk_fn_ptr(ty::Binder(self.infcx.tcx.mk_fn_sig( + self.infcx.tcx.mk_fn_ptr(ty::Binder::bind(self.infcx.tcx.mk_fn_sig( input_tys.iter().cloned(), output_ty, false, diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 6f2c51b0f18..76991e3e52d 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -960,7 +960,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { // Attempt to select a concrete impl before checking. ty::TraitContainer(trait_def_id) => { let trait_ref = ty::TraitRef::from_method(tcx, trait_def_id, callee_substs); - let trait_ref = ty::Binder(trait_ref); + let trait_ref = ty::Binder::bind(trait_ref); let span = tcx.hir.span(expr_id); let obligation = traits::Obligation::new(traits::ObligationCause::misc(span, expr_id), @@ -1441,3 +1441,71 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeAliasBounds { } } } + +/// Lint constants that are erroneous. +/// Without this lint, we might not get any diagnostic if the constant is +/// unused within this crate, even though downstream crates can't use it +/// without producing an error. +pub struct UnusedBrokenConst; + +impl LintPass for UnusedBrokenConst { + fn get_lints(&self) -> LintArray { + lint_array!() + } +} + +fn check_const(cx: &LateContext, body_id: hir::BodyId, what: &str) { + let def_id = cx.tcx.hir.body_owner_def_id(body_id); + let param_env = cx.tcx.param_env(def_id); + let cid = ::rustc::mir::interpret::GlobalId { + instance: ty::Instance::mono(cx.tcx, def_id), + promoted: None + }; + if let Err(err) = cx.tcx.const_eval(param_env.and(cid)) { + let span = cx.tcx.def_span(def_id); + let mut diag = cx.struct_span_lint( + CONST_ERR, + span, + &format!("this {} cannot be used", what), + ); + use rustc::middle::const_val::ConstEvalErrDescription; + match err.description() { + ConstEvalErrDescription::Simple(message) => { + diag.span_label(span, message); + } + ConstEvalErrDescription::Backtrace(miri, frames) => { + diag.span_label(span, format!("{}", miri)); + for frame in frames { + diag.span_label(frame.span, format!("inside call to `{}`", frame.location)); + } + } + } + diag.emit() + } +} + +struct UnusedBrokenConstVisitor<'a, 'tcx: 'a>(&'a LateContext<'a, 'tcx>); + +impl<'a, 'tcx, 'v> hir::intravisit::Visitor<'v> for UnusedBrokenConstVisitor<'a, 'tcx> { + fn visit_nested_body(&mut self, id: hir::BodyId) { + check_const(self.0, id, "array length"); + } + fn nested_visit_map<'this>(&'this mut self) -> hir::intravisit::NestedVisitorMap<'this, 'v> { + hir::intravisit::NestedVisitorMap::None + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedBrokenConst { + fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { + match it.node { + hir::ItemConst(_, body_id) => { + check_const(cx, body_id, "constant"); + }, + hir::ItemTy(ref ty, _) => hir::intravisit::walk_ty( + &mut UnusedBrokenConstVisitor(cx), + ty + ), + _ => {}, + } + } +} diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 16e8600f2d8..889c7d3e34e 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -40,7 +40,7 @@ extern crate rustc_mir; extern crate syntax_pos; use rustc::lint; -use rustc::lint::builtin::BARE_TRAIT_OBJECT; +use rustc::lint::builtin::{BARE_TRAIT_OBJECT, ABSOLUTE_PATH_STARTING_WITH_MODULE}; use rustc::session; use rustc::util; @@ -136,6 +136,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { UnionsWithDropFields, UnreachablePub, TypeAliasBounds, + UnusedBrokenConst, ); add_builtin_with_new!(sess, @@ -278,6 +279,11 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { // Note: this item represents future incompatibility of all unstable functions in the // standard library, and thus should never be removed or changed to an error. }, + FutureIncompatibleInfo { + id: LintId::of(ABSOLUTE_PATH_STARTING_WITH_MODULE), + reference: "issue TBD", + edition: Some(Edition::Edition2018), + }, ]); // Register renamed and removed lints diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index 54e3f544acb..1619637b827 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -28,6 +28,12 @@ fn detect_llvm_link() -> (&'static str, &'static str) { } fn main() { + if env::var_os("RUST_CHECK").is_some() { + // If we're just running `check`, there's no need for LLVM to be built. + println!("cargo:rerun-if-env-changed=RUST_CHECK"); + return; + } + let target = env::var("TARGET").expect("TARGET was not set"); let llvm_config = env::var_os("LLVM_CONFIG") .map(PathBuf::from) diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs deleted file mode 100644 index 71b15643cbc..00000000000 --- a/src/librustc_metadata/astencode.rs +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use rustc::hir::intravisit::{Visitor, NestedVisitorMap}; - -use isolated_encoder::IsolatedEncoder; -use schema::*; - -use rustc::hir; -use rustc::ty::{self, TyCtxt}; - -use rustc::ich::Fingerprint; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; - -#[derive(RustcEncodable, RustcDecodable)] -pub struct Ast<'tcx> { - pub body: Lazy<hir::Body>, - pub tables: Lazy<ty::TypeckTables<'tcx>>, - pub nested_bodies: LazySeq<hir::Body>, - pub rvalue_promotable_to_static: bool, - pub stable_bodies_hash: Fingerprint, -} - -impl_stable_hash_for!(struct Ast<'tcx> { - body, - tables, - nested_bodies, - rvalue_promotable_to_static, - stable_bodies_hash -}); - -impl<'a, 'b, 'tcx> IsolatedEncoder<'a, 'b, 'tcx> { - pub fn encode_body(&mut self, body_id: hir::BodyId) -> Lazy<Ast<'tcx>> { - let body = self.tcx.hir.body(body_id); - - // In order to avoid having to hash hir::Bodies from extern crates, we - // hash them here, during export, and store the hash with metadata. - let stable_bodies_hash = { - let mut hcx = self.tcx.create_stable_hashing_context(); - let mut hasher = StableHasher::new(); - - hcx.while_hashing_hir_bodies(true, |hcx| { - body.hash_stable(hcx, &mut hasher); - }); - - hasher.finish() - }; - - let lazy_body = self.lazy(body); - let body_owner_def_id = self.tcx.hir.body_owner_def_id(body_id); - let tables = self.tcx.typeck_tables_of(body_owner_def_id); - let lazy_tables = self.lazy(tables); - - let mut visitor = NestedBodyCollector { - tcx: self.tcx, - bodies_found: Vec::new(), - }; - visitor.visit_body(body); - let lazy_nested_bodies = self.lazy_seq_ref_from_slice(&visitor.bodies_found); - - let rvalue_promotable_to_static = - self.tcx.const_is_rvalue_promotable_to_static(body_owner_def_id); - - self.lazy(&Ast { - body: lazy_body, - tables: lazy_tables, - nested_bodies: lazy_nested_bodies, - rvalue_promotable_to_static, - stable_bodies_hash, - }) - } -} - -struct NestedBodyCollector<'a, 'tcx: 'a> { - tcx: TyCtxt<'a, 'tcx, 'tcx>, - bodies_found: Vec<&'tcx hir::Body>, -} - -impl<'a, 'tcx: 'a> Visitor<'tcx> for NestedBodyCollector<'a, 'tcx> { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::None - } - - fn visit_nested_body(&mut self, body: hir::BodyId) { - let body = self.tcx.hir.body(body); - self.bodies_found.push(body); - self.visit_body(body); - } -} diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 2c995d2f5cd..a11b95cb5b6 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -142,7 +142,6 @@ provide! { <'tcx> tcx, def_id, other, cdata, mir_const_qualif => { (cdata.mir_const_qualif(def_id.index), Lrc::new(IdxSetBuf::new_empty(0))) } - typeck_tables_of => { cdata.item_body_tables(def_id.index, tcx) } fn_sig => { cdata.fn_sig(def_id.index, tcx) } inherent_impls => { Lrc::new(cdata.get_inherent_implementations_for_type(def_id.index)) } is_const_fn => { cdata.is_const_fn(def_id.index) } @@ -161,9 +160,9 @@ provide! { <'tcx> tcx, def_id, other, cdata, // This is only used by rustdoc anyway, which shouldn't have // incremental recompilation ever enabled. fn_arg_names => { cdata.get_fn_arg_names(def_id.index) } + rendered_const => { cdata.get_rendered_const(def_id.index) } impl_parent => { cdata.get_parent_impl(def_id.index) } trait_of_item => { cdata.get_trait_of_item(def_id.index) } - item_body_nested_bodies => { cdata.item_body_nested_bodies(tcx, def_id.index) } const_is_rvalue_promotable_to_static => { cdata.const_is_rvalue_promotable_to_static(def_id.index) } @@ -243,11 +242,6 @@ provide! { <'tcx> tcx, def_id, other, cdata, defined_lang_items => { Lrc::new(cdata.get_lang_items()) } missing_lang_items => { Lrc::new(cdata.get_missing_lang_items()) } - extern_const_body => { - debug!("item_body({:?}): inlining item", def_id); - cdata.extern_const_body(tcx, def_id.index) - } - missing_extern_crate_item => { let r = match *cdata.extern_crate.borrow() { Some(extern_crate) if !extern_crate.direct => true, diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 936d680380c..0147e8dc607 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -17,8 +17,7 @@ use rustc_data_structures::sync::{Lrc, ReadGuard}; use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash, DisambiguatedDefPathData}; use rustc::hir; -use rustc::middle::cstore::{LinkagePreference, ExternConstBody, - ExternBodyNestedBodies}; +use rustc::middle::cstore::LinkagePreference; use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use rustc::hir::def::{self, Def, CtorKind}; use rustc::hir::def_id::{CrateNum, DefId, DefIndex, @@ -33,7 +32,6 @@ use rustc::mir::Mir; use rustc::util::captures::Captures; use rustc::util::nodemap::FxHashMap; -use std::collections::BTreeMap; use std::io; use std::mem; use std::u32; @@ -433,7 +431,7 @@ impl<'a, 'tcx> MetadataBlob { impl<'tcx> EntryKind<'tcx> { fn to_def(&self, did: DefId) -> Option<Def> { Some(match *self { - EntryKind::Const(_) => Def::Const(did), + EntryKind::Const(..) => Def::Const(did), EntryKind::AssociatedConst(..) => Def::AssociatedConst(did), EntryKind::ImmStatic | EntryKind::ForeignImmStatic => Def::Static(did, false), @@ -794,54 +792,12 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn extern_const_body(&self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - id: DefIndex) - -> ExternConstBody<'tcx> { - assert!(!self.is_proc_macro(id)); - let ast = self.entry(id).ast.unwrap(); - let def_id = self.local_def_id(id); - let ast = ast.decode((self, tcx)); - let body = ast.body.decode((self, tcx)); - ExternConstBody { - body: tcx.hir.intern_inlined_body(def_id, body), - fingerprint: ast.stable_bodies_hash, - } - } - - pub fn item_body_tables(&self, - id: DefIndex, - tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> &'tcx ty::TypeckTables<'tcx> { - let ast = self.entry(id).ast.unwrap().decode(self); - tcx.alloc_tables(ast.tables.decode((self, tcx))) - } - - pub fn item_body_nested_bodies(&self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - id: DefIndex) - -> ExternBodyNestedBodies { - if let Some(ref ast) = self.entry(id).ast { - let mut ast = ast.decode(self); - let nested_bodies: BTreeMap<_, _> = ast.nested_bodies - .decode((self, tcx.sess)) - .map(|body| (body.id(), body)) - .collect(); - ExternBodyNestedBodies { - nested_bodies: Lrc::new(nested_bodies), - fingerprint: ast.stable_bodies_hash, - } - } else { - ExternBodyNestedBodies { - nested_bodies: Lrc::new(BTreeMap::new()), - fingerprint: Fingerprint::ZERO, - } - } - } - pub fn const_is_rvalue_promotable_to_static(&self, id: DefIndex) -> bool { - self.entry(id).ast.expect("const item missing `ast`") - .decode(self).rvalue_promotable_to_static + match self.entry(id).kind { + EntryKind::AssociatedConst(_, data, _) | + EntryKind::Const(data, _) => data.ast_promotable, + _ => bug!(), + } } pub fn is_item_mir_available(&self, id: DefIndex) -> bool { @@ -861,10 +817,10 @@ impl<'a, 'tcx> CrateMetadata { pub fn mir_const_qualif(&self, id: DefIndex) -> u8 { match self.entry(id).kind { - EntryKind::Const(qualif) | - EntryKind::AssociatedConst(AssociatedContainer::ImplDefault, qualif) | - EntryKind::AssociatedConst(AssociatedContainer::ImplFinal, qualif) => { - qualif + EntryKind::Const(qualif, _) | + EntryKind::AssociatedConst(AssociatedContainer::ImplDefault, qualif, _) | + EntryKind::AssociatedConst(AssociatedContainer::ImplFinal, qualif, _) => { + qualif.mir } _ => bug!(), } @@ -877,7 +833,7 @@ impl<'a, 'tcx> CrateMetadata { let name = def_key.disambiguated_data.data.get_opt_name().unwrap(); let (kind, container, has_self) = match item.kind { - EntryKind::AssociatedConst(container, _) => { + EntryKind::AssociatedConst(container, _, _) => { (ty::AssociatedKind::Const, container, false) } EntryKind::Method(data) => { @@ -1076,6 +1032,14 @@ impl<'a, 'tcx> CrateMetadata { lazy_seq.decode((self, tcx)).collect() } + pub fn get_rendered_const(&self, id: DefIndex) -> String { + match self.entry(id).kind { + EntryKind::Const(_, data) | + EntryKind::AssociatedConst(_, _, data) => data.decode(self).0, + _ => bug!(), + } + } + pub fn wasm_custom_sections(&self) -> Vec<DefId> { let sections = self.root .wasm_custom_sections diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 67c180e94ca..d7a06f7932f 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -622,7 +622,6 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), - ast: None, mir: self.encode_optimized_mir(def_id), } } @@ -660,7 +659,6 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { generics: None, predicates: None, - ast: None, mir: None } } @@ -701,7 +699,6 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), - ast: None, mir: None, } } @@ -759,7 +756,6 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), - ast: None, mir: self.encode_optimized_mir(def_id), } } @@ -795,7 +791,18 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { let kind = match trait_item.kind { ty::AssociatedKind::Const => { - EntryKind::AssociatedConst(container, 0) + let const_qualif = + if let hir::TraitItemKind::Const(_, Some(body)) = ast_item.node { + self.const_qualif(0, body) + } else { + ConstQualif { mir: 0, ast_promotable: false } + }; + + let rendered = + hir::print::to_string(&self.tcx.hir, |s| s.print_trait_item(ast_item)); + let rendered_const = self.lazy(&RenderedConst(rendered)); + + EntryKind::AssociatedConst(container, const_qualif, rendered_const) } ty::AssociatedKind::Method => { let fn_data = if let hir::TraitItemKind::Method(_, ref m) = ast_item.node { @@ -855,11 +862,6 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), - ast: if let hir::TraitItemKind::Const(_, Some(body)) = ast_item.node { - Some(self.encode_body(body)) - } else { - None - }, mir: self.encode_optimized_mir(def_id), } } @@ -869,6 +871,13 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { !self.tcx.sess.opts.output_types.should_trans() } + fn const_qualif(&self, mir: u8, body_id: hir::BodyId) -> ConstQualif { + let body_owner_def_id = self.tcx.hir.body_owner_def_id(body_id); + let ast_promotable = self.tcx.const_is_rvalue_promotable_to_static(body_owner_def_id); + + ConstQualif { mir, ast_promotable } + } + 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; @@ -886,8 +895,15 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { let kind = match impl_item.kind { ty::AssociatedKind::Const => { - EntryKind::AssociatedConst(container, - self.tcx.at(ast_item.span).mir_const_qualif(def_id).0) + if let hir::ImplItemKind::Const(_, body_id) = ast_item.node { + let mir = self.tcx.at(ast_item.span).mir_const_qualif(def_id).0; + + EntryKind::AssociatedConst(container, + self.const_qualif(mir, body_id), + self.encode_rendered_const_for_body(body_id)) + } else { + bug!() + } } ty::AssociatedKind::Method => { let fn_data = if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node { @@ -908,20 +924,21 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { ty::AssociatedKind::Type => EntryKind::AssociatedType(container) }; - let (ast, mir) = if let hir::ImplItemKind::Const(_, body) = ast_item.node { - (Some(body), true) - } else if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node { - let generics = self.tcx.generics_of(def_id); - let types = generics.parent_types as usize + generics.types.len(); - let needs_inline = (types > 0 || tcx.trans_fn_attrs(def_id).requests_inline()) && - !self.metadata_output_only(); - let is_const_fn = sig.constness == hir::Constness::Const; - let ast = if is_const_fn { Some(body) } else { None }; - let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir; - (ast, needs_inline || is_const_fn || always_encode_mir) - } else { - (None, false) - }; + let mir = + match ast_item.node { + hir::ImplItemKind::Const(..) => true, + hir::ImplItemKind::Method(ref sig, _) => { + let generics = self.tcx.generics_of(def_id); + let types = generics.parent_types as usize + generics.types.len(); + let needs_inline = + (types > 0 || tcx.trans_fn_attrs(def_id).requests_inline()) + && !self.metadata_output_only(); + let is_const_fn = sig.constness == hir::Constness::Const; + let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir; + needs_inline || is_const_fn || always_encode_mir + }, + hir::ImplItemKind::Type(..) => false, + }; Entry { kind, @@ -942,7 +959,6 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), - ast: ast.map(|body| self.encode_body(body)), mir: if mir { self.encode_optimized_mir(def_id) } else { None }, } } @@ -999,6 +1015,13 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { self.tcx.lookup_deprecation(def_id).map(|depr| self.lazy(&depr)) } + fn encode_rendered_const_for_body(&mut self, body_id: hir::BodyId) -> Lazy<RenderedConst> { + let body = self.tcx.hir.body(body_id); + let rendered = hir::print::to_string(&self.tcx.hir, |s| s.print_expr(&body.value)); + let rendered_const = &RenderedConst(rendered); + self.lazy(rendered_const) + } + fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) -> Entry<'tcx> { let tcx = self.tcx; @@ -1007,8 +1030,12 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { let kind = match item.node { hir::ItemStatic(_, hir::MutMutable, _) => EntryKind::MutStatic, hir::ItemStatic(_, hir::MutImmutable, _) => EntryKind::ImmStatic, - hir::ItemConst(..) => { - EntryKind::Const(tcx.at(item.span).mir_const_qualif(def_id).0) + hir::ItemConst(_, body_id) => { + let mir = tcx.at(item.span).mir_const_qualif(def_id).0; + EntryKind::Const( + self.const_qualif(mir, body_id), + self.encode_rendered_const_for_body(body_id) + ) } hir::ItemFn(_, _, constness, .., body) => { let data = FnData { @@ -1191,13 +1218,6 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { _ => None, }, - ast: match item.node { - hir::ItemConst(_, body) | - hir::ItemFn(_, _, hir::Constness::Const, _, _, body) => { - Some(self.encode_body(body)) - } - _ => None, - }, mir: match item.node { hir::ItemStatic(..) => { self.encode_optimized_mir(def_id) @@ -1240,7 +1260,6 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { variances: LazySeq::empty(), generics: None, predicates: None, - ast: None, mir: None, } } @@ -1269,7 +1288,6 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { generics: None, predicates: None, - ast: None, mir: None, } } @@ -1292,7 +1310,6 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), - ast: None, mir: None, } } @@ -1337,7 +1354,6 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { generics: Some(self.encode_generics(def_id)), predicates: None, - ast: None, mir: self.encode_optimized_mir(def_id), } } @@ -1346,10 +1362,12 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { debug!("IsolatedEncoder::encode_info_for_embedded_const({:?})", def_id); let tcx = self.tcx; let id = tcx.hir.as_local_node_id(def_id).unwrap(); - let body = tcx.hir.body_owned_by(id); + let body_id = tcx.hir.body_owned_by(id); + let const_data = self.encode_rendered_const_for_body(body_id); + let mir = tcx.mir_const_qualif(def_id).0; Entry { - kind: EntryKind::Const(tcx.mir_const_qualif(def_id).0), + kind: EntryKind::Const(self.const_qualif(mir, body_id), const_data), visibility: self.lazy(&ty::Visibility::Public), span: self.lazy(&tcx.def_span(def_id)), attributes: LazySeq::empty(), @@ -1363,7 +1381,6 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), - ast: Some(self.encode_body(body)), mir: self.encode_optimized_mir(def_id), } } @@ -1565,7 +1582,6 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), - ast: None, mir: None, } } diff --git a/src/librustc_metadata/isolated_encoder.rs b/src/librustc_metadata/isolated_encoder.rs index 689c190966e..88594afa320 100644 --- a/src/librustc_metadata/isolated_encoder.rs +++ b/src/librustc_metadata/isolated_encoder.rs @@ -55,10 +55,4 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { { self.ecx.lazy_seq_ref(slice.iter()) } - - pub fn lazy_seq_ref_from_slice<T>(&mut self, slice: &[&T]) -> LazySeq<T> - where T: Encodable - { - self.ecx.lazy_seq_ref(slice.iter().map(|x| *x)) - } } diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index cbbc9d74228..9ecb3fd6cdd 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -44,7 +44,6 @@ extern crate rustc_data_structures; mod diagnostics; -mod astencode; mod index_builder; mod index; mod encoder; diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 23ea5e4cc55..5d6db1abe7b 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use astencode; use index; use rustc::hir; @@ -266,7 +265,6 @@ pub struct Entry<'tcx> { pub generics: Option<Lazy<ty::Generics>>, pub predicates: Option<Lazy<ty::GenericPredicates<'tcx>>>, - pub ast: Option<Lazy<astencode::Ast<'tcx>>>, pub mir: Option<Lazy<mir::Mir<'tcx>>>, } @@ -283,13 +281,12 @@ impl_stable_hash_for!(struct Entry<'tcx> { variances, generics, predicates, - ast, mir }); #[derive(Copy, Clone, RustcEncodable, RustcDecodable)] pub enum EntryKind<'tcx> { - Const(u8), + Const(ConstQualif, Lazy<RenderedConst>), ImmStatic, MutStatic, ForeignImmStatic, @@ -313,7 +310,7 @@ pub enum EntryKind<'tcx> { Impl(Lazy<ImplData<'tcx>>), Method(Lazy<MethodData<'tcx>>), AssociatedType(AssociatedContainer), - AssociatedConst(AssociatedContainer, u8), + AssociatedConst(AssociatedContainer, ConstQualif, Lazy<RenderedConst>), } impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for EntryKind<'gcx> { @@ -333,8 +330,9 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for EntryKind<'gcx> { EntryKind::Type => { // Nothing else to hash here. } - EntryKind::Const(qualif) => { + EntryKind::Const(qualif, ref const_data) => { qualif.hash_stable(hcx, hasher); + const_data.hash_stable(hcx, hasher); } EntryKind::Enum(ref repr_options) => { repr_options.hash_stable(hcx, hasher); @@ -375,7 +373,7 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for EntryKind<'gcx> { EntryKind::AssociatedType(associated_container) => { associated_container.hash_stable(hcx, hasher); } - EntryKind::AssociatedConst(associated_container, qualif) => { + EntryKind::AssociatedConst(associated_container, qualif, _) => { associated_container.hash_stable(hcx, hasher); qualif.hash_stable(hcx, hasher); } @@ -383,6 +381,29 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for EntryKind<'gcx> { } } +/// Additional data for EntryKind::Const and EntryKind::AssociatedConst +#[derive(Clone, Copy, RustcEncodable, RustcDecodable)] +pub struct ConstQualif { + pub mir: u8, + pub ast_promotable: bool, +} + +impl_stable_hash_for!(struct ConstQualif { mir, ast_promotable }); + +/// Contains a constant which has been rendered to a String. +/// Used by rustdoc. +#[derive(RustcEncodable, RustcDecodable)] +pub struct RenderedConst(pub String); + +impl<'a> HashStable<StableHashingContext<'a>> for RenderedConst { + #[inline] + fn hash_stable<W: StableHasherResult>(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher<W>) { + self.0.hash_stable(hcx, hasher); + } +} + #[derive(RustcEncodable, RustcDecodable)] pub struct ModData { pub reexports: LazySeq<def::Export>, diff --git a/src/librustc_mir/borrow_check/nll/region_infer/values.rs b/src/librustc_mir/borrow_check/nll/region_infer/values.rs index 2f0b4c24bd6..d15d85792d9 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/values.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/values.rs @@ -14,7 +14,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::indexed_vec::IndexVec; use rustc::mir::{BasicBlock, Location, Mir}; -use rustc::ty::RegionVid; +use rustc::ty::{self, RegionVid}; use syntax::codemap::Span; use super::{Cause, CauseExt, TrackCauses}; @@ -263,7 +263,17 @@ impl RegionValues { if let Some(causes) = &mut self.causes { let cause = make_cause(causes); let old_cause = causes.get_mut(&(r, i)).unwrap(); - if cause < **old_cause { + // #49998: compare using root cause alone to avoid + // useless traffic from similar outlives chains. + + let overwrite = if ty::tls::with(|tcx| { + tcx.sess.opts.debugging_opts.nll_subminimal_causes + }) { + cause.root_cause() < old_cause.root_cause() + } else { + cause < **old_cause + }; + if overwrite { *old_cause = Rc::new(cause); return true; } diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index acd246b7031..ec7ee466008 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -275,7 +275,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { tcx.predicates_of(def_id).instantiate(tcx, substs); let predicates = type_checker.normalize(&instantiated_predicates.predicates, location); - type_checker.prove_predicates(predicates.iter().cloned(), location); + type_checker.prove_predicates(predicates, location); } value.ty @@ -1516,34 +1516,34 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { let predicates = self.normalize(&instantiated_predicates.predicates, location); debug!("prove_aggregate_predicates: predicates={:?}", predicates); - self.prove_predicates(predicates.iter().cloned(), location); + self.prove_predicates(predicates, location); } fn prove_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>, location: Location) { self.prove_predicates( - [ty::Predicate::Trait( + Some(ty::Predicate::Trait( trait_ref.to_poly_trait_ref().to_poly_trait_predicate(), - )].iter() - .cloned(), + )), location, ); } - fn prove_predicates( - &mut self, - predicates: impl IntoIterator<Item = ty::Predicate<'tcx>>, - location: Location, - ) { - let mut predicates_iter = predicates.into_iter(); + fn prove_predicates<T>(&mut self, predicates: T, location: Location) + where + T: IntoIterator<Item = ty::Predicate<'tcx>>, + T::IntoIter: Clone, + { + let predicates = predicates.into_iter(); debug!( "prove_predicates(predicates={:?}, location={:?})", - predicates_iter.by_ref().collect::<Vec<_>>(), - location + predicates.clone().collect::<Vec<_>>(), + location, ); self.fully_perform_op(location.at_self(), |this| { let cause = this.misc(this.last_span); - let obligations = predicates_iter + let obligations = predicates + .into_iter() .map(|p| traits::Obligation::new(cause.clone(), this.param_env, p)) .collect(); Ok(InferOk { diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs index 4e95ee6444d..147b8cc2175 100644 --- a/src/librustc_mir/build/matches/simplify.rs +++ b/src/librustc_mir/build/matches/simplify.rs @@ -113,6 +113,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { PatternKind::Variant { adt_def, substs, variant_index, ref subpatterns } => { let irrefutable = adt_def.variants.iter().enumerate().all(|(i, v)| { i == variant_index || { + self.hir.tcx().features().never_type && self.hir.tcx().features().exhaustive_patterns && self.hir.tcx().is_variant_uninhabited_from_all_modules(v, substs) } diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 6f8b1f8e799..ff7b4f9e0fd 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -985,15 +985,17 @@ fn slice_pat_covered_by_constructor(tcx: TyCtxt, _span: Span, Ok(true) } -fn constructor_covered_by_range(ctor: &Constructor, - from: &ConstVal, to: &ConstVal, - end: RangeEnd, - ty: Ty) - -> Result<bool, ErrorReported> { +fn constructor_covered_by_range<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + ctor: &Constructor, + from: &ConstVal, to: &ConstVal, + end: RangeEnd, + ty: Ty<'tcx>, +) -> Result<bool, ErrorReported> { trace!("constructor_covered_by_range {:#?}, {:#?}, {:#?}, {}", ctor, from, to, ty); - let cmp_from = |c_from| compare_const_vals(c_from, from, ty) + let cmp_from = |c_from| compare_const_vals(tcx, c_from, from, ty) .map(|res| res != Ordering::Less); - let cmp_to = |c_to| compare_const_vals(c_to, to, ty); + let cmp_to = |c_to| compare_const_vals(tcx, c_to, to, ty); macro_rules! some_or_ok { ($e:expr) => { match $e { @@ -1105,6 +1107,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>( }, _ => { match constructor_covered_by_range( + cx.tcx, constructor, &value.val, &value.val, RangeEnd::Included, value.ty, ) { @@ -1118,6 +1121,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>( PatternKind::Range { lo, hi, ref end } => { match constructor_covered_by_range( + cx.tcx, constructor, &lo.val, &hi.val, end.clone(), lo.ty, ) { Ok(true) => Some(vec![]), diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 8d2b73d6ba0..c2da8c11d87 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -16,7 +16,7 @@ mod check_match; pub use self::check_match::check_crate; pub(crate) use self::check_match::check_match; -use interpret::{const_val_field, const_discr}; +use interpret::{const_val_field, const_variant_index, self}; use rustc::middle::const_val::ConstVal; use rustc::mir::{Field, BorrowKind, Mutability}; @@ -372,7 +372,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { (PatternKind::Constant { value: lo }, PatternKind::Constant { value: hi }) => { use std::cmp::Ordering; - match (end, compare_const_vals(&lo.val, &hi.val, ty).unwrap()) { + match (end, compare_const_vals(self.tcx, &lo.val, &hi.val, ty).unwrap()) { (RangeEnd::Excluded, Ordering::Less) => PatternKind::Range { lo, hi, end }, (RangeEnd::Excluded, _) => { @@ -835,38 +835,9 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { ty::TyAdt(adt_def, substs) if adt_def.is_enum() => { match cv.val { ConstVal::Value(val) => { - let discr_val = const_discr( + let variant_index = const_variant_index( self.tcx, self.param_env, instance, val, cv.ty - ).expect("const_discr failed"); - let layout = self - .tcx - .layout_of(self.param_env.and(cv.ty)) - .expect("layout of enum not available"); - let variant_index = match layout.variants { - ty::layout::Variants::Single { index } => index, - ty::layout::Variants::Tagged { ref discr, .. } => { - // raw discriminants for enums are isize or bigger during - // their computation, but later shrunk to the smallest possible - // representation - let size = discr.value.size(self.tcx).bits(); - let amt = 128 - size; - adt_def - .discriminants(self.tcx) - .position(|var| ((var.val << amt) >> amt) == discr_val) - .unwrap_or_else(|| { - bug!("discriminant {} not found in {:#?}", - discr_val, - adt_def - .discriminants(self.tcx) - .collect::<Vec<_>>(), - ); - }) - } - ty::layout::Variants::NicheFilling { .. } => { - assert_eq!(discr_val as usize as u128, discr_val); - discr_val as usize - }, - }; + ).expect("const_variant_index failed"); let subpatterns = adt_subpatterns( adt_def.variants[variant_index].fields.len(), Some(variant_index), @@ -1076,7 +1047,12 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> { } } -pub fn compare_const_vals(a: &ConstVal, b: &ConstVal, ty: Ty) -> Option<Ordering> { +pub fn compare_const_vals<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + a: &ConstVal, + b: &ConstVal, + ty: Ty<'tcx>, +) -> Option<Ordering> { use rustc_const_math::ConstFloat; trace!("compare_const_vals: {:?}, {:?}", a, b); use rustc::mir::interpret::{Value, PrimVal}; @@ -1096,7 +1072,11 @@ pub fn compare_const_vals(a: &ConstVal, b: &ConstVal, ty: Ty) -> Option<Ordering // FIXME(oli-obk): report cmp errors? l.try_cmp(r).ok() }, - ty::TyInt(_) => Some((a as i128).cmp(&(b as i128))), + ty::TyInt(_) => { + let a = interpret::sign_extend(tcx, a, ty).expect("layout error for TyInt"); + let b = interpret::sign_extend(tcx, b, ty).expect("layout error for TyInt"); + Some((a as i128).cmp(&(b as i128))) + }, _ => Some(a.cmp(&b)), } }, diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs index 954a3dbe5b9..a25331f7279 100644 --- a/src/librustc_mir/interpret/const_eval.rs +++ b/src/librustc_mir/interpret/const_eval.rs @@ -56,7 +56,7 @@ pub fn mk_eval_cx<'a, 'tcx>( Ok(ecx) } -pub fn eval_body_with_mir<'a, 'mir, 'tcx>( +pub fn eval_promoted<'a, 'mir, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, cid: GlobalId<'tcx>, mir: &'mir mir::Mir<'tcx>, @@ -66,7 +66,7 @@ pub fn eval_body_with_mir<'a, 'mir, 'tcx>( match res { Ok(val) => Some(val), Err(mut err) => { - ecx.report(&mut err, true, None); + ecx.report(&mut err, false, None); None } } @@ -400,14 +400,14 @@ pub fn const_val_field<'a, 'tcx>( } } -pub fn const_discr<'a, 'tcx>( +pub fn const_variant_index<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, instance: ty::Instance<'tcx>, value: Value, ty: Ty<'tcx>, -) -> EvalResult<'tcx, u128> { - trace!("const_discr: {:?}, {:?}, {:?}", instance, value, ty); +) -> EvalResult<'tcx, usize> { + trace!("const_variant_index: {:?}, {:?}, {:?}", instance, value, ty); let mut ecx = mk_eval_cx(tcx, instance, param_env).unwrap(); let (ptr, align) = match value { Value::ByValPair(..) | Value::ByVal(_) => { @@ -421,7 +421,7 @@ pub fn const_discr<'a, 'tcx>( Value::ByRef(ptr, align) => (ptr, align), }; let place = Place::from_primval_ptr(ptr, align); - ecx.read_discriminant_value(place, ty) + ecx.read_discriminant_as_variant_index(place, ty) } pub fn const_eval_provider<'a, 'tcx>( diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 03785f9623b..b98ab218de5 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -260,7 +260,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M self.param_env, def_id, substs, - ).ok_or(EvalErrorKind::TypeckError.into()) // turn error prop into a panic to expose associated type in const issue + ).ok_or_else(|| EvalErrorKind::TypeckError.into()) // turn error prop into a panic to expose associated type in const issue } pub(super) fn type_is_sized(&self, ty: Ty<'tcx>) -> bool { @@ -279,9 +279,9 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M trace!("load mir {:?}", instance); match instance { ty::InstanceDef::Item(def_id) => { - self.tcx.maybe_optimized_mir(def_id).ok_or_else(|| { + self.tcx.maybe_optimized_mir(def_id).ok_or_else(|| EvalErrorKind::NoMirFor(self.tcx.item_path_str(def_id)).into() - }) + ) } _ => Ok(self.tcx.instance_mir(instance)), } @@ -691,7 +691,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M self.param_env, def_id, substs, - ).ok_or(EvalErrorKind::TypeckError.into()); + ).ok_or_else(|| EvalErrorKind::TypeckError.into()); let fn_ptr = self.memory.create_fn_alloc(instance?); let valty = ValTy { value: Value::ByVal(PrimVal::Ptr(fn_ptr)), @@ -743,28 +743,8 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M Discriminant(ref place) => { let ty = self.place_ty(place); - let layout = self.layout_of(ty)?; let place = self.eval_place(place)?; let discr_val = self.read_discriminant_value(place, ty)?; - match layout.variants { - layout::Variants::Single { index } => { - assert_eq!(discr_val, index as u128); - } - layout::Variants::Tagged { .. } | - layout::Variants::NicheFilling { .. } => { - if let ty::TyAdt(adt_def, _) = ty.sty { - trace!("Read discriminant {}, valid discriminants {:?}", discr_val, adt_def.discriminants(*self.tcx).collect::<Vec<_>>()); - if adt_def.discriminants(*self.tcx).all(|v| { - discr_val != v.val - }) - { - return err!(InvalidDiscriminant); - } - } else { - bug!("rustc only generates Rvalue::Discriminant for enums"); - } - } - } self.write_primval(dest, PrimVal::Bytes(discr_val), dest_ty)?; } } @@ -837,13 +817,39 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M } } + /// reads a tag and produces the corresponding variant index + pub fn read_discriminant_as_variant_index( + &mut self, + place: Place, + ty: Ty<'tcx>, + ) -> EvalResult<'tcx, usize> { + let layout = self.layout_of(ty)?; + match layout.variants { + ty::layout::Variants::Single { index } => Ok(index), + ty::layout::Variants::Tagged { .. } => { + let discr_val = self.read_discriminant_value(place, ty)?; + ty + .ty_adt_def() + .expect("tagged layout for non adt") + .discriminants(self.tcx.tcx) + .position(|var| var.val == discr_val) + .ok_or_else(|| EvalErrorKind::InvalidDiscriminant.into()) + } + ty::layout::Variants::NicheFilling { .. } => { + let discr_val = self.read_discriminant_value(place, ty)?; + assert_eq!(discr_val as usize as u128, discr_val); + Ok(discr_val as usize) + }, + } + } + pub fn read_discriminant_value( &mut self, place: Place, ty: Ty<'tcx>, ) -> EvalResult<'tcx, u128> { let layout = self.layout_of(ty)?; - //trace!("read_discriminant_value {:#?}", layout); + trace!("read_discriminant_value {:#?}", layout); match layout.variants { layout::Variants::Single { index } => { @@ -854,13 +860,34 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M } let (discr_place, discr) = self.place_field(place, mir::Field::new(0), layout)?; + trace!("discr place: {:?}, {:?}", discr_place, discr); let raw_discr = self.value_to_primval(ValTy { value: self.read_place(discr_place)?, ty: discr.ty })?; let discr_val = match layout.variants { layout::Variants::Single { .. } => bug!(), - layout::Variants::Tagged { .. } => raw_discr.to_bytes()?, + // FIXME: should we catch invalid discriminants here? + layout::Variants::Tagged { .. } => { + if discr.ty.is_signed() { + let i = raw_discr.to_bytes()? as i128; + // going from layout tag type to typeck discriminant type + // requires first sign extending with the layout discriminant + let amt = 128 - discr.size.bits(); + let sexted = (i << amt) >> amt; + // and then zeroing with the typeck discriminant type + let discr_ty = ty + .ty_adt_def().expect("tagged layout corresponds to adt") + .repr + .discr_type(); + let discr_ty = layout::Integer::from_attr(self.tcx.tcx, discr_ty); + let amt = 128 - discr_ty.size().bits(); + let truncatee = sexted as u128; + (truncatee << amt) >> amt + } else { + raw_discr.to_bytes()? + } + }, layout::Variants::NicheFilling { dataful_variant, ref niche_variants, @@ -910,11 +937,18 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M layout::Abi::Uninhabited); } } - layout::Variants::Tagged { .. } => { + layout::Variants::Tagged { ref discr, .. } => { let discr_val = dest_ty.ty_adt_def().unwrap() .discriminant_for_variant(*self.tcx, variant_index) .val; + // raw discriminants for enums are isize or bigger during + // their computation, but the in-memory tag is the smallest possible + // representation + let size = discr.value.size(self.tcx.tcx).bits(); + let amt = 128 - size; + let discr_val = (discr_val << amt) >> amt; + let (discr_dest, discr) = self.place_field(dest, mir::Field::new(0), layout)?; self.write_primval(discr_dest, PrimVal::Bytes(discr_val), discr.ty)?; } @@ -1145,19 +1179,18 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M _ if primval.is_undef() => false, _ => bug!("write_value_to_ptr: invalid ByVal layout: {:#?}", layout) }; - self.memory.write_primval(dest.to_ptr()?, dest_align, primval, layout.size.bytes(), signed) + self.memory.write_primval(dest, dest_align, primval, layout.size.bytes(), signed) } Value::ByValPair(a_val, b_val) => { - let ptr = dest.to_ptr()?; trace!("write_value_to_ptr valpair: {:#?}", layout); let (a, b) = match layout.abi { layout::Abi::ScalarPair(ref a, ref b) => (&a.value, &b.value), _ => bug!("write_value_to_ptr: invalid ByValPair layout: {:#?}", layout) }; let (a_size, b_size) = (a.size(&self), b.size(&self)); - let a_ptr = ptr; + let a_ptr = dest; let b_offset = a_size.abi_align(b.align(&self)); - let b_ptr = ptr.offset(b_offset.bytes(), &self)?.into(); + let b_ptr = dest.offset(b_offset.bytes(), &self)?.into(); // TODO: What about signedess? self.memory.write_primval(a_ptr, dest_align, a_val, a_size.bytes(), false)?; self.memory.write_primval(b_ptr, dest_align, b_val, b_size.bytes(), false) @@ -1679,27 +1712,17 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M } pub fn sign_extend(&self, value: u128, ty: Ty<'tcx>) -> EvalResult<'tcx, u128> { - let layout = self.layout_of(ty)?; - let size = layout.size.bits(); - assert!(layout.abi.is_signed()); - // sign extend - let amt = 128 - size; - // shift the unsigned value to the left - // and back to the right as signed (essentially fills with FF on the left) - Ok((((value << amt) as i128) >> amt) as u128) + super::sign_extend(self.tcx.tcx, value, ty) } pub fn truncate(&self, value: u128, ty: Ty<'tcx>) -> EvalResult<'tcx, u128> { - let size = self.layout_of(ty)?.size.bits(); - let amt = 128 - size; - // truncate (shift left to drop out leftover values, shift right to fill with zeroes) - Ok((value << amt) >> amt) + super::truncate(self.tcx.tcx, value, ty) } } impl<'mir, 'tcx> Frame<'mir, 'tcx> { pub fn get_local(&self, local: mir::Local) -> EvalResult<'tcx, Value> { - self.locals[local].ok_or(EvalErrorKind::DeadLocal.into()) + self.locals[local].ok_or_else(|| EvalErrorKind::DeadLocal.into()) } fn set_local(&mut self, local: mir::Local, value: Value) -> EvalResult<'tcx> { diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index dcf97f61545..5e156e9271f 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -691,7 +691,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { self.read_primval(ptr, ptr_align, self.pointer_size()) } - pub fn write_primval(&mut self, ptr: MemoryPointer, ptr_align: Align, val: PrimVal, size: u64, signed: bool) -> EvalResult<'tcx> { + pub fn write_primval(&mut self, ptr: Pointer, ptr_align: Align, val: PrimVal, size: u64, signed: bool) -> EvalResult<'tcx> { let endianness = self.endianness(); let bytes = match val { @@ -703,11 +703,14 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { PrimVal::Bytes(bytes) => bytes, PrimVal::Undef => { - self.mark_definedness(PrimVal::Ptr(ptr).into(), size, false)?; + self.check_align(ptr.into(), ptr_align)?; + self.mark_definedness(ptr, size, false)?; return Ok(()); } }; + let ptr = ptr.to_ptr()?; + { let align = self.int_align(size); let dst = self.get_bytes_mut(ptr, size, ptr_align.min(align))?; @@ -734,7 +737,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn write_ptr_sized_unsigned(&mut self, ptr: MemoryPointer, ptr_align: Align, val: PrimVal) -> EvalResult<'tcx> { let ptr_size = self.pointer_size(); - self.write_primval(ptr, ptr_align, val, ptr_size, false) + self.write_primval(ptr.into(), ptr_align, val, ptr_size, false) } fn int_align(&self, size: u64) -> Align { diff --git a/src/librustc_mir/interpret/mod.rs b/src/librustc_mir/interpret/mod.rs index ae6337d82c3..1eb131810bd 100644 --- a/src/librustc_mir/interpret/mod.rs +++ b/src/librustc_mir/interpret/mod.rs @@ -19,15 +19,39 @@ pub use self::place::{Place, PlaceExtra}; pub use self::memory::{Memory, MemoryKind, HasMemory}; pub use self::const_eval::{ - eval_body_with_mir, + eval_promoted, mk_borrowck_eval_cx, eval_body, CompileTimeEvaluator, const_eval_provider, const_val_field, - const_discr, + const_variant_index, }; pub use self::machine::Machine; pub use self::memory::{write_target_uint, write_target_int, read_target_uint}; + +use rustc::mir::interpret::{EvalResult, EvalErrorKind}; +use rustc::ty::{Ty, TyCtxt, ParamEnv}; + +pub fn sign_extend<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, value: u128, ty: Ty<'tcx>) -> EvalResult<'tcx, u128> { + let param_env = ParamEnv::empty(); + let layout = tcx.layout_of(param_env.and(ty)).map_err(|layout| EvalErrorKind::Layout(layout))?; + let size = layout.size.bits(); + assert!(layout.abi.is_signed()); + // sign extend + let amt = 128 - size; + // shift the unsigned value to the left + // and back to the right as signed (essentially fills with FF on the left) + Ok((((value << amt) as i128) >> amt) as u128) +} + +pub fn truncate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, value: u128, ty: Ty<'tcx>) -> EvalResult<'tcx, u128> { + let param_env = ParamEnv::empty(); + let layout = tcx.layout_of(param_env.and(ty)).map_err(|layout| EvalErrorKind::Layout(layout))?; + let size = layout.size.bits(); + let amt = 128 - size; + // truncate (shift left to drop out leftover values, shift right to fill with zeroes) + Ok((value << amt) >> amt) +} diff --git a/src/librustc_mir/interpret/terminator/mod.rs b/src/librustc_mir/interpret/terminator/mod.rs index 851fac532e3..3360e5b72a7 100644 --- a/src/librustc_mir/interpret/terminator/mod.rs +++ b/src/librustc_mir/interpret/terminator/mod.rs @@ -37,7 +37,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { ref targets, .. } => { - // FIXME(CTFE): forbid branching let discr_val = self.eval_operand(discr)?; let discr_prim = self.value_to_primval(discr_val)?; @@ -45,8 +44,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { let mut target_block = targets[targets.len() - 1]; for (index, &const_int) in values.iter().enumerate() { - let prim = PrimVal::Bytes(const_int); - if discr_prim.to_bytes()? == prim.to_bytes()? { + if discr_prim.to_bytes()? == const_int { target_block = targets[index]; break; } diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index de3063a5756..a47b3cacc51 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -33,6 +33,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![feature(nonzero)] #![feature(inclusive_range_fields)] #![feature(crate_visibility_modifier)] +#![feature(never_type)] #![cfg_attr(stage0, feature(try_trait))] extern crate arena; diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 008165f33b2..610e70b39cc 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -1177,7 +1177,7 @@ fn collect_neighbours<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, param_substs: instance.substs, }.visit_mir(&mir); let param_env = ty::ParamEnv::reveal_all(); - for (i, promoted) in mir.promoted.iter().enumerate() { + for i in 0..mir.promoted.len() { use rustc_data_structures::indexed_vec::Idx; let cid = GlobalId { instance, @@ -1185,9 +1185,7 @@ fn collect_neighbours<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }; match tcx.const_eval(param_env.and(cid)) { Ok(val) => collect_const(tcx, val, instance.substs, output), - Err(err) => { - err.report(tcx, promoted.span, "promoted"); - } + Err(_) => {}, } } } diff --git a/src/librustc_mir/monomorphize/mod.rs b/src/librustc_mir/monomorphize/mod.rs index 5c38735d920..020dce62c38 100644 --- a/src/librustc_mir/monomorphize/mod.rs +++ b/src/librustc_mir/monomorphize/mod.rs @@ -163,7 +163,7 @@ pub fn custom_coerce_unsize_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, -> CustomCoerceUnsized { let def_id = tcx.lang_items().coerce_unsized_trait().unwrap(); - let trait_ref = ty::Binder(ty::TraitRef { + let trait_ref = ty::Binder::bind(ty::TraitRef { def_id: def_id, substs: tcx.mk_substs_trait(source_ty, &[target_ty]) }); diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index f133d6e9c6d..a3d96f0c073 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -20,7 +20,7 @@ use rustc::mir::visit::{Visitor, PlaceContext}; use rustc::middle::const_val::ConstVal; use rustc::ty::{TyCtxt, self, Instance}; use rustc::mir::interpret::{Value, PrimVal, GlobalId}; -use interpret::{eval_body_with_mir, mk_borrowck_eval_cx, ValTy}; +use interpret::{eval_promoted, mk_borrowck_eval_cx, ValTy}; use transform::{MirPass, MirSource}; use syntax::codemap::Span; use rustc::ty::subst::Substs; @@ -161,7 +161,7 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> { }; // cannot use `const_eval` here, because that would require having the MIR // for the current function available, but we're producing said MIR right now - let (value, _, ty) = eval_body_with_mir(self.tcx, cid, self.mir, self.param_env)?; + let (value, _, ty) = eval_promoted(self.tcx, cid, self.mir, self.param_env)?; let val = (value, ty, c.span); trace!("evaluated {:?} to {:?}", c, val); Some(val) diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index aeefd5ab1d5..591732fbba9 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -964,7 +964,7 @@ This does not pose a problem by itself because they can't be accessed directly." let (msg, note) = if let UnstableFeatures::Disallow = self.tcx.sess.opts.unstable_features { (format!("calls in {}s are limited to \ - struct and enum constructors", + tuple structs and tuple variants", self.mode), Some("a limited form of compile-time function \ evaluation is available on a nightly \ @@ -972,7 +972,7 @@ This does not pose a problem by itself because they can't be accessed directly." } else { (format!("calls in {}s are limited \ to constant functions, \ - struct and enum constructors", + tuple structs and tuple variants", self.mode), None) }; diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 1866122454c..6708640379a 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -273,7 +273,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.err_handler().span_err(item.span, "inherent impls cannot be negative"); } if defaultness == Defaultness::Default { - self.err_handler().span_err(item.span, "inherent impls cannot be default"); + self.err_handler() + .struct_span_err(item.span, "inherent impls cannot be default") + .note("only trait implementations may be annotated with default").emit(); } } ItemKind::ForeignMod(..) => { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 671856c4e54..127331152c1 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1654,11 +1654,12 @@ impl<'a> Resolver<'a> { let path: Vec<Ident> = segments.iter() .map(|seg| Ident::new(seg.name, span)) .collect(); - match self.resolve_path(&path, Some(namespace), true, span) { + // FIXME (Manishearth): Intra doc links won't get warned of epoch changes + match self.resolve_path(&path, Some(namespace), true, span, None) { PathResult::Module(module) => *def = module.def().unwrap(), PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => *def = path_res.base_def(), - PathResult::NonModule(..) => match self.resolve_path(&path, None, true, span) { + PathResult::NonModule(..) => match self.resolve_path(&path, None, true, span, None) { PathResult::Failed(span, msg, _) => { error_callback(self, span, ResolutionError::FailedToResolve(&msg)); } @@ -2360,7 +2361,8 @@ impl<'a> Resolver<'a> { if def != Def::Err { new_id = Some(def.def_id()); let span = trait_ref.path.span; - if let PathResult::Module(module) = self.resolve_path(&path, None, false, span) { + if let PathResult::Module(module) = self.resolve_path(&path, None, false, span, + Some(trait_ref.ref_id)) { new_val = Some((module, trait_ref.clone())); } } @@ -2819,7 +2821,8 @@ impl<'a> Resolver<'a> { (format!(""), format!("the crate root")) } else { let mod_path = &path[..path.len() - 1]; - let mod_prefix = match this.resolve_path(mod_path, Some(TypeNS), false, span) { + let mod_prefix = match this.resolve_path(mod_path, Some(TypeNS), + false, span, None) { PathResult::Module(module) => module.def(), _ => None, }.map_or(format!(""), |def| format!("{} ", def.kind_name())); @@ -3149,7 +3152,7 @@ impl<'a> Resolver<'a> { )); } - let result = match self.resolve_path(&path, Some(ns), true, span) { + let result = match self.resolve_path(&path, Some(ns), true, span, Some(id)) { PathResult::NonModule(path_res) => path_res, PathResult::Module(module) if !module.is_normal() => { PathResolution::new(module.def().unwrap()) @@ -3186,7 +3189,7 @@ impl<'a> Resolver<'a> { 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) { + match self.resolve_path(&[*path.last().unwrap()], Some(ns), false, span, None) { PathResult::NonModule(path_res) => path_res.base_def(), PathResult::Module(module) => module.def().unwrap(), _ => return Some(result), @@ -3205,7 +3208,9 @@ impl<'a> Resolver<'a> { path: &[Ident], opt_ns: Option<Namespace>, // `None` indicates a module path record_used: bool, - path_span: Span) + path_span: Span, + node_id: Option<NodeId>) // None indicates that we don't care about linting + // `::module` paths -> PathResult<'a> { let mut module = None; let mut allow_super = true; @@ -3240,6 +3245,7 @@ impl<'a> Resolver<'a> { if ns == TypeNS { if (i == 0 && name == keywords::CrateRoot.name()) || + (i == 0 && name == keywords::Crate.name()) || (i == 1 && name == keywords::Crate.name() && path[0].name == keywords::CrateRoot.name()) { // `::a::b` or `::crate::a::b` @@ -3253,6 +3259,8 @@ impl<'a> Resolver<'a> { let prev_name = path[0].name; if prev_name == keywords::Extern.name() || prev_name == keywords::CrateRoot.name() && + // Note: When this feature stabilizes, this should + // be gated on sess.rust_2018() self.session.features_untracked().extern_absolute_paths { // `::extern_crate::a::b` let crate_id = self.crate_loader.process_path_extern(name, ident.span); @@ -3272,8 +3280,10 @@ impl<'a> Resolver<'a> { name == keywords::SelfType.name() && i != 0 || name == keywords::Super.name() && i != 0 || name == keywords::Extern.name() && i != 0 || - name == keywords::Crate.name() && i != 1 && - path[0].name != keywords::CrateRoot.name() { + // we allow crate::foo and ::crate::foo but nothing else + name == keywords::Crate.name() && i > 1 && + path[0].name != keywords::CrateRoot.name() || + name == keywords::Crate.name() && path.len() == 1 { let name_str = if name == keywords::CrateRoot.name() { format!("crate root") } else { @@ -3281,8 +3291,6 @@ impl<'a> Resolver<'a> { }; let msg = if i == 1 && path[0].name == keywords::CrateRoot.name() { format!("global paths cannot start with {}", name_str) - } else if i == 0 && name == keywords::Crate.name() { - format!("{} can only be used in absolute paths", name_str) } else { format!("{} in paths can only be used in start position", name_str) }; @@ -3324,6 +3332,33 @@ impl<'a> Resolver<'a> { format!("Not a module `{}`", ident), is_last); } + + if let Some(id) = node_id { + if i == 1 && self.session.features_untracked().crate_in_paths + && !self.session.rust_2018() { + let prev_name = path[0].name; + if prev_name == keywords::Extern.name() || + prev_name == keywords::CrateRoot.name() { + let mut is_crate = false; + if let NameBindingKind::Import { directive: d, .. } = binding.kind { + if let ImportDirectiveSubclass::ExternCrate(..) = d.subclass { + is_crate = true; + } + } + + if !is_crate { + let diag = lint::builtin::BuiltinLintDiagnostics + ::AbsPathWithModule(path_span); + self.session.buffer_lint_with_diagnostic( + lint::builtin::ABSOLUTE_PATH_STARTING_WITH_MODULE, + id, path_span, + "Absolute paths must start with `self`, `super`, \ + `crate`, or an external crate name in the 2018 edition", + diag); + } + } + } + } } Err(Undetermined) => return PathResult::Indeterminate, Err(Determined) => { @@ -3571,7 +3606,7 @@ impl<'a> Resolver<'a> { // Search in module. let mod_path = &path[..path.len() - 1]; if let PathResult::Module(module) = self.resolve_path(mod_path, Some(TypeNS), - false, span) { + false, span, None) { add_module_candidates(module, &mut names); } } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 0388465b485..af1e17cd89c 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -397,6 +397,18 @@ impl<'a> Resolver<'a> { fn resolve_macro_to_def(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool) -> Result<Def, Determinacy> { + if path.segments.len() > 1 { + if !self.session.features_untracked().proc_macro_path_invoc { + emit_feature_err( + &self.session.parse_sess, + "proc_macro_path_invoc", + path.span, + GateIssue::Language, + "paths of length greater than one in macro invocations are \ + currently unstable", + ); + } + } let def = self.resolve_macro_to_def_inner(scope, path, kind, force); if def != Err(Determinacy::Undetermined) { // Do not report duplicated errors on every undetermined resolution. @@ -426,7 +438,7 @@ impl<'a> Resolver<'a> { return Err(Determinacy::Determined); } - let def = match self.resolve_path(&path, Some(MacroNS), false, span) { + let def = match self.resolve_path(&path, Some(MacroNS), false, span, None) { PathResult::NonModule(path_res) => match path_res.base_def() { Def::Err => Err(Determinacy::Determined), def @ _ => { @@ -604,7 +616,7 @@ impl<'a> Resolver<'a> { pub fn finalize_current_module_macro_resolutions(&mut self) { let module = self.current_module; for &(ref path, span) in module.macro_resolutions.borrow().iter() { - match self.resolve_path(&path, Some(MacroNS), true, span) { + match self.resolve_path(&path, Some(MacroNS), true, span, None) { PathResult::NonModule(_) => {}, PathResult::Failed(span, msg, _) => { resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 37c62a7b0b4..e2a7f5668d2 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -535,7 +535,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { // For better failure detection, pretend that the import will not define any names // while resolving its module path. directive.vis.set(ty::Visibility::Invisible); - let result = self.resolve_path(&directive.module_path[..], None, false, directive.span); + let result = self.resolve_path(&directive.module_path[..], None, false, + directive.span, Some(directive.id)); directive.vis.set(vis); match result { @@ -663,7 +664,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { } } - let module_result = self.resolve_path(&module_path, None, true, span); + let module_result = self.resolve_path(&module_path, None, true, span, Some(directive.id)); let module = match module_result { PathResult::Module(module) => module, PathResult::Failed(span, msg, false) => { @@ -677,7 +678,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { if !self_path.is_empty() && !is_special(self_path[0]) && !(self_path.len() > 1 && is_special(self_path[1])) { self_path[0].name = keywords::SelfValue.name(); - self_result = Some(self.resolve_path(&self_path, None, false, span)); + self_result = Some(self.resolve_path(&self_path, None, false, + span, None)); } return if let Some(PathResult::Module(..)) = self_result { Some((span, format!("Did you mean `{}`?", names_to_string(&self_path[..])))) diff --git a/src/librustc_traits/lib.rs b/src/librustc_traits/lib.rs index 8136f6857a5..90c870096e1 100644 --- a/src/librustc_traits/lib.rs +++ b/src/librustc_traits/lib.rs @@ -37,6 +37,7 @@ pub fn provide(p: &mut Providers) { normalize_ty_after_erasing_regions: normalize_erasing_regions::normalize_ty_after_erasing_regions, program_clauses_for: lowering::program_clauses_for, + program_clauses_for_env: lowering::program_clauses_for_env, ..*p }; } diff --git a/src/librustc_traits/lowering.rs b/src/librustc_traits/lowering.rs index 36e60cee788..b6a086f609d 100644 --- a/src/librustc_traits/lowering.rs +++ b/src/librustc_traits/lowering.rs @@ -8,14 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc::hir::{self, ImplPolarity}; use rustc::hir::def_id::DefId; use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; -use rustc::ty::{self, Slice, TyCtxt}; +use rustc::hir::map::definitions::DefPathData; +use rustc::hir::{self, ImplPolarity}; +use rustc::traits::{Clause, Clauses, DomainGoal, Goal, PolyDomainGoal, ProgramClause, + WhereClauseAtom}; use rustc::ty::subst::Substs; -use rustc::traits::{WhereClauseAtom, PolyDomainGoal, DomainGoal, ProgramClause, Clause, Goal}; +use rustc::ty::{self, Slice, TyCtxt}; +use rustc_data_structures::fx::FxHashSet; +use std::mem; use syntax::ast; -use rustc_data_structures::sync::Lrc; use std::iter; @@ -24,7 +27,10 @@ trait Lower<T> { fn lower(&self) -> T; } -impl<T, U> Lower<Vec<U>> for Vec<T> where T: Lower<U> { +impl<T, U> Lower<Vec<U>> for Vec<T> +where + T: Lower<U>, +{ fn lower(&self) -> Vec<U> { self.iter().map(|item| item.lower()).collect() } @@ -42,7 +48,10 @@ impl<'tcx> Lower<WhereClauseAtom<'tcx>> for ty::ProjectionPredicate<'tcx> { } } -impl<'tcx, T> Lower<DomainGoal<'tcx>> for T where T: Lower<WhereClauseAtom<'tcx>> { +impl<'tcx, T> Lower<DomainGoal<'tcx>> for T +where + T: Lower<WhereClauseAtom<'tcx>>, +{ fn lower(&self) -> DomainGoal<'tcx> { DomainGoal::Holds(self.lower()) } @@ -67,7 +76,8 @@ impl<'tcx> Lower<DomainGoal<'tcx>> for ty::TypeOutlivesPredicate<'tcx> { /// `forall<'a> { T: Fn(&'a i32) }` which corresponds to something like /// `Binder<Holds(Implemented(TraitPredicate))>`. impl<'tcx, T> Lower<PolyDomainGoal<'tcx>> for ty::Binder<T> - where T: Lower<DomainGoal<'tcx>> + ty::fold::TypeFoldable<'tcx> +where + T: Lower<DomainGoal<'tcx>> + ty::fold::TypeFoldable<'tcx>, { fn lower(&self) -> PolyDomainGoal<'tcx> { self.map_bound_ref(|p| p.lower()) @@ -84,10 +94,9 @@ impl<'tcx> Lower<PolyDomainGoal<'tcx>> for ty::Predicate<'tcx> { TypeOutlives(predicate) => predicate.lower(), Projection(predicate) => predicate.lower(), WellFormed(ty) => ty::Binder::dummy(DomainGoal::WellFormedTy(*ty)), - ObjectSafe(..) | - ClosureKind(..) | - Subtype(..) | - ConstEvaluatable(..) => unimplemented!(), + ObjectSafe(..) | ClosureKind(..) | Subtype(..) | ConstEvaluatable(..) => { + unimplemented!() + } } } } @@ -104,44 +113,88 @@ impl<'tcx> IntoFromEnvGoal for DomainGoal<'tcx> { use self::DomainGoal::*; match self { Holds(wc_atom) => FromEnv(wc_atom), - WellFormed(..) | - FromEnv(..) | - WellFormedTy(..) | - FromEnvTy(..) | - Normalize(..) | - RegionOutlives(..) | - TypeOutlives(..) => self, + WellFormed(..) | FromEnv(..) | WellFormedTy(..) | FromEnvTy(..) | Normalize(..) + | RegionOutlives(..) | TypeOutlives(..) => self, } } } -crate fn program_clauses_for<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) - -> Lrc<&'tcx Slice<Clause<'tcx>>> -{ - let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); - let node = tcx.hir.find(node_id).unwrap(); - match node { - hir::map::Node::NodeItem(item) => match item.node { - hir::ItemTrait(..) => program_clauses_for_trait(tcx, def_id), - hir::ItemImpl(..) => program_clauses_for_impl(tcx, def_id), - _ => Lrc::new(tcx.mk_clauses(iter::empty::<Clause>())), - } - hir::map::Node::NodeImplItem(item) => { - if let hir::ImplItemKind::Type(..) = item.node { - program_clauses_for_associated_type_value(tcx, def_id) - } else { - Lrc::new(tcx.mk_clauses(iter::empty::<Clause>())) - } - }, +crate fn program_clauses_for<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId, +) -> Clauses<'tcx> { + match tcx.def_key(def_id).disambiguated_data.data { + DefPathData::Trait(_) => program_clauses_for_trait(tcx, def_id), + DefPathData::Impl => program_clauses_for_impl(tcx, def_id), + DefPathData::AssocTypeInImpl(..) => program_clauses_for_associated_type_value(tcx, def_id), + _ => Slice::empty(), + } +} - // FIXME: other constructions e.g. traits, associated types... - _ => Lrc::new(tcx.mk_clauses(iter::empty::<Clause>())), +crate fn program_clauses_for_env<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + param_env: ty::ParamEnv<'tcx>, +) -> Clauses<'tcx> { + debug!("program_clauses_for_env(param_env={:?})", param_env); + + let mut last_round = FxHashSet(); + last_round.extend( + param_env + .caller_bounds + .iter() + .flat_map(|&p| predicate_def_id(p)), + ); + + let mut closure = last_round.clone(); + let mut next_round = FxHashSet(); + while !last_round.is_empty() { + next_round.extend( + last_round + .drain() + .flat_map(|def_id| { + tcx.predicates_of(def_id) + .instantiate_identity(tcx) + .predicates + }) + .flat_map(|p| predicate_def_id(p)) + .filter(|&def_id| closure.insert(def_id)), + ); + mem::swap(&mut next_round, &mut last_round); + } + + debug!("program_clauses_for_env: closure = {:#?}", closure); + + return tcx.mk_clauses( + closure + .into_iter() + .flat_map(|def_id| tcx.program_clauses_for(def_id).iter().cloned()), + ); + + /// Given that `predicate` is in the environment, returns the + /// def-id of something (e.g., a trait, associated item, etc) + /// whose predicates can also be assumed to be true. We will + /// compute the transitive closure of such things. + fn predicate_def_id<'tcx>(predicate: ty::Predicate<'tcx>) -> Option<DefId> { + match predicate { + ty::Predicate::Trait(predicate) => Some(predicate.def_id()), + + ty::Predicate::Projection(projection) => Some(projection.item_def_id()), + + ty::Predicate::WellFormed(..) + | ty::Predicate::RegionOutlives(..) + | ty::Predicate::TypeOutlives(..) + | ty::Predicate::ObjectSafe(..) + | ty::Predicate::ClosureKind(..) + | ty::Predicate::Subtype(..) + | ty::Predicate::ConstEvaluatable(..) => None, + } } } -fn program_clauses_for_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) - -> Lrc<&'tcx Slice<Clause<'tcx>>> -{ +fn program_clauses_for_trait<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId, +) -> Clauses<'tcx> { // `trait Trait<P1..Pn> where WC { .. } // P0 == Self` // Rule Implemented-From-Env (see rustc guide) @@ -156,8 +209,8 @@ fn program_clauses_for_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefI let trait_pred = ty::TraitPredicate { trait_ref: ty::TraitRef { def_id, - substs: Substs::identity_for_item(tcx, def_id) - } + substs: Substs::identity_for_item(tcx, def_id), + }, }; // `FromEnv(Self: Trait<P1..Pn>)` let from_env = Goal::from(DomainGoal::FromEnv(trait_pred.lower())); @@ -169,9 +222,7 @@ fn program_clauses_for_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefI goal: impl_trait, hypotheses: tcx.mk_goals(iter::once(from_env)), }; - let clauses = iter::once( - Clause::ForAll(ty::Binder::dummy(implemented_from_env)) - ); + let clauses = iter::once(Clause::ForAll(ty::Binder::dummy(implemented_from_env))); // Rule Implied-Bound-From-Trait // @@ -186,11 +237,11 @@ fn program_clauses_for_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefI // FIXME: Remove the [1..] slice; this is a hack because the query // predicates_of currently includes the trait itself (`Self: Trait<P1..Pn>`). let where_clauses = &tcx.predicates_of(def_id).predicates; - let implied_bound_clauses = - where_clauses[1..].into_iter() + let implied_bound_clauses = where_clauses[1..] + .into_iter() .map(|wc| implied_bound_from_trait(tcx, trait_pred, wc)); - Lrc::new(tcx.mk_clauses(clauses.chain(implied_bound_clauses))) + tcx.mk_clauses(clauses.chain(implied_bound_clauses)) } /// For a given `where_clause`, returns a clause `FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn>)`. @@ -203,19 +254,15 @@ fn implied_bound_from_trait<'a, 'tcx>( let impl_trait = DomainGoal::FromEnv(WhereClauseAtom::Implemented(trait_pred)); // `FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn>)` - Clause::ForAll( - where_clause.lower().map_bound(|goal| ProgramClause { - goal: goal.into_from_env_goal(), - hypotheses: tcx.mk_goals(iter::once(Goal::from(impl_trait))), - }) - ) + Clause::ForAll(where_clause.lower().map_bound(|goal| ProgramClause { + goal: goal.into_from_env_goal(), + hypotheses: tcx.mk_goals(iter::once(Goal::from(impl_trait))), + })) } -fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) - -> Lrc<&'tcx Slice<Clause<'tcx>>> -{ +fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Clauses<'tcx> { if let ImplPolarity::Negative = tcx.impl_polarity(def_id) { - return Lrc::new(tcx.mk_clauses(iter::empty::<Clause>())); + return Slice::empty(); } // Rule Implemented-From-Impl (see rustc guide) @@ -231,23 +278,25 @@ fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId let trait_ref = tcx.impl_trait_ref(def_id).unwrap(); // `Implemented(A0: Trait<A1..An>)` let trait_pred = ty::TraitPredicate { trait_ref }.lower(); - // `WC` + // `WC` let where_clauses = tcx.predicates_of(def_id).predicates.lower(); - // `Implemented(A0: Trait<A1..An>) :- WC` + // `Implemented(A0: Trait<A1..An>) :- WC` let clause = ProgramClause { goal: trait_pred, hypotheses: tcx.mk_goals( - where_clauses.into_iter().map(|wc| Goal::from_poly_domain_goal(wc, tcx)) - ) + where_clauses + .into_iter() + .map(|wc| Goal::from_poly_domain_goal(wc, tcx)), + ), }; - Lrc::new(tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause))))) + tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause)))) } pub fn program_clauses_for_associated_type_value<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: DefId, -) -> Lrc<&'tcx Slice<Clause<'tcx>>> { +) -> Clauses<'tcx> { // Rule Normalize-From-Impl (see rustc guide) // // ```impl<P0..Pn> Trait<A1..An> for A0 @@ -290,10 +339,12 @@ pub fn program_clauses_for_associated_type_value<'a, 'tcx>( let clause = ProgramClause { goal: normalize_goal, hypotheses: tcx.mk_goals( - where_clauses.into_iter().map(|wc| Goal::from_poly_domain_goal(wc, tcx)) + where_clauses + .into_iter() + .map(|wc| Goal::from_poly_domain_goal(wc, tcx)), ), }; - Lrc::new(tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause))))) + tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause)))) } pub fn dump_program_clauses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { @@ -302,27 +353,54 @@ pub fn dump_program_clauses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { } let mut visitor = ClauseDumper { tcx }; - tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor()); + tcx.hir + .krate() + .visit_all_item_likes(&mut visitor.as_deep_visitor()); } struct ClauseDumper<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, } -impl<'a, 'tcx> ClauseDumper<'a, 'tcx > { +impl<'a, 'tcx> ClauseDumper<'a, 'tcx> { fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) { let def_id = self.tcx.hir.local_def_id(node_id); for attr in attrs { + let mut clauses = None; + if attr.check_name("rustc_dump_program_clauses") { - let clauses = self.tcx.program_clauses_for(def_id); - for clause in *clauses { - // Skip the top-level binder for a less verbose output - let program_clause = match clause { - Clause::Implies(program_clause) => program_clause, - Clause::ForAll(program_clause) => program_clause.skip_binder(), - }; - self.tcx.sess.struct_span_err(attr.span, &format!("{}", program_clause)).emit(); + clauses = Some(self.tcx.program_clauses_for(def_id)); + } + + if attr.check_name("rustc_dump_env_program_clauses") { + let param_env = self.tcx.param_env(def_id); + clauses = Some(self.tcx.program_clauses_for_env(param_env)); + } + + if let Some(clauses) = clauses { + let mut err = self.tcx + .sess + .struct_span_err(attr.span, "program clause dump"); + + let mut strings: Vec<_> = clauses + .iter() + .map(|clause| { + // Skip the top-level binder for a less verbose output + let program_clause = match clause { + Clause::Implies(program_clause) => program_clause, + Clause::ForAll(program_clause) => program_clause.skip_binder(), + }; + format!("{}", program_clause) + }) + .collect(); + + strings.sort(); + + for string in strings { + err.note(&string); } + + err.emit(); } } } diff --git a/src/librustc_traits/util.rs b/src/librustc_traits/util.rs index bff070ab73d..e4cb118a4f7 100644 --- a/src/librustc_traits/util.rs +++ b/src/librustc_traits/util.rs @@ -9,8 +9,7 @@ // except according to those terms. use rustc::infer::InferCtxt; -use rustc::infer::canonical::{CanonicalVarValues, Canonicalize, Certainty, QueryRegionConstraints, - QueryResult}; +use rustc::infer::canonical::{CanonicalVarValues, Canonicalize, Certainty, QueryResult}; use rustc::infer::region_constraints::{Constraint, RegionConstraintData}; use rustc::traits::{FulfillmentContext, TraitEngine}; use rustc::traits::query::NoSolution; @@ -62,7 +61,7 @@ where let region_obligations = infcx.take_registered_region_obligations(); - let (region_outlives, ty_outlives) = infcx.with_region_constraints(|region_constraints| { + let region_constraints = infcx.with_region_constraints(|region_constraints| { let RegionConstraintData { constraints, verifys, @@ -72,24 +71,32 @@ where assert!(verifys.is_empty()); assert!(givens.is_empty()); - let region_outlives: Vec<_> = constraints + let mut outlives: Vec<_> = constraints .into_iter() .map(|(k, _)| match *k { - Constraint::VarSubVar(v1, v2) => { - (tcx.mk_region(ty::ReVar(v1)), tcx.mk_region(ty::ReVar(v2))) + Constraint::VarSubVar(v1, v2) => ty::OutlivesPredicate( + tcx.mk_region(ty::ReVar(v1)).into(), + tcx.mk_region(ty::ReVar(v2)), + ), + Constraint::VarSubReg(v1, r2) => { + ty::OutlivesPredicate(tcx.mk_region(ty::ReVar(v1)).into(), r2) } - Constraint::VarSubReg(v1, r2) => (tcx.mk_region(ty::ReVar(v1)), r2), - Constraint::RegSubVar(r1, v2) => (r1, tcx.mk_region(ty::ReVar(v2))), - Constraint::RegSubReg(r1, r2) => (r1, r2), + Constraint::RegSubVar(r1, v2) => { + ty::OutlivesPredicate(r1.into(), tcx.mk_region(ty::ReVar(v2))) + } + Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r1.into(), r2), }) + .map(ty::Binder::dummy) // no bound regions in the code above .collect(); - let ty_outlives: Vec<_> = region_obligations - .into_iter() - .map(|(_, r_o)| (r_o.sup_type, r_o.sub_region)) - .collect(); + outlives.extend( + region_obligations + .into_iter() + .map(|(_, r_o)| ty::OutlivesPredicate(r_o.sup_type.into(), r_o.sub_region)) + .map(ty::Binder::dummy) // no bound regions in the code above + ); - (region_outlives, ty_outlives) + outlives }); let certainty = if ambig_errors.is_empty() { @@ -100,10 +107,7 @@ where let (canonical_result, _) = infcx.canonicalize_response(&QueryResult { var_values: inference_vars, - region_constraints: QueryRegionConstraints { - region_outlives, - ty_outlives, - }, + region_constraints, certainty, value: answer, }); diff --git a/src/librustc_trans/allocator.rs b/src/librustc_trans/allocator.rs index f2dd2ed8460..ffebb959ebf 100644 --- a/src/librustc_trans/allocator.rs +++ b/src/librustc_trans/allocator.rs @@ -43,13 +43,11 @@ pub(crate) unsafe fn trans(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind) AllocatorTy::Ptr => args.push(i8p), AllocatorTy::Usize => args.push(usize), - AllocatorTy::Bang | AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"), } } let output = match method.output { - AllocatorTy::Bang => None, AllocatorTy::ResultPtr => Some(i8p), AllocatorTy::Unit => None, diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index ebcf06d63be..e001e809ee5 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -960,6 +960,7 @@ impl Linker for WasmLd { fn finalize(&mut self) -> Command { self.cmd.arg("--threads"); + self.cmd.arg("-z").arg("stack-size=1048576"); // FIXME we probably shouldn't pass this but instead pass an explicit // whitelist of symbols we'll allow to be undefined. Unfortunately diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index f501b1739eb..613a07cd269 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -1007,13 +1007,6 @@ pub fn start_async_translation(tcx: TyCtxt, metadata_config.time_passes = false; allocator_config.time_passes = false; - let client = sess.jobserver_from_env.clone().unwrap_or_else(|| { - // Pick a "reasonable maximum" if we don't otherwise have a jobserver in - // our environment, capping out at 32 so we don't take everything down - // by hogging the process run queue. - Client::new(32).expect("failed to create jobserver") - }); - let (shared_emitter, shared_emitter_main) = SharedEmitter::new(); let (trans_worker_send, trans_worker_receive) = channel(); @@ -1023,7 +1016,7 @@ pub fn start_async_translation(tcx: TyCtxt, trans_worker_send, coordinator_receive, total_cgus, - client, + sess.jobserver.clone(), time_graph.clone(), Arc::new(modules_config), Arc::new(metadata_config), diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 1da6f25fd63..a4e1b7f2925 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -492,7 +492,7 @@ pub fn trans_instance<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, instance: Instance<'tc // You can also find more info on why Windows is whitelisted here in: // https://bugzilla.mozilla.org/show_bug.cgi?id=1302078 if !cx.sess().no_landing_pads() || - cx.sess().target.target.options.is_like_windows { + cx.sess().target.target.options.requires_uwtable { attributes::emit_uwtable(lldecl, true); } diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index fe8a7052bdf..4d781d7280d 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -406,7 +406,7 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> { return llfn; } - let ty = tcx.mk_fn_ptr(ty::Binder(tcx.mk_fn_sig( + let ty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig( iter::once(tcx.mk_mut_ptr(tcx.types.u8)), tcx.types.never, false, diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index 5c67f809114..ecdc2d20d21 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -958,7 +958,7 @@ fn gen_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, output: Ty<'tcx>, trans: &mut for<'b> FnMut(Builder<'b, 'tcx>)) -> ValueRef { - let rust_fn_ty = cx.tcx.mk_fn_ptr(ty::Binder(cx.tcx.mk_fn_sig( + let rust_fn_ty = cx.tcx.mk_fn_ptr(ty::Binder::bind(cx.tcx.mk_fn_sig( inputs.into_iter(), output, false, @@ -985,7 +985,7 @@ fn get_rust_try_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, // Define the type up front for the signature of the rust_try function. let tcx = cx.tcx; let i8p = tcx.mk_mut_ptr(tcx.types.i8); - let fn_ty = tcx.mk_fn_ptr(ty::Binder(tcx.mk_fn_sig( + let fn_ty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig( iter::once(i8p), tcx.mk_nil(), false, diff --git a/src/librustc_trans/mir/operand.rs b/src/librustc_trans/mir/operand.rs index 75df349de41..656ab95a28c 100644 --- a/src/librustc_trans/mir/operand.rs +++ b/src/librustc_trans/mir/operand.rs @@ -399,7 +399,14 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { self.mir_constant_to_miri_value(bx, constant) .and_then(|c| OperandRef::from_const(bx, c, ty)) .unwrap_or_else(|err| { - err.report(bx.tcx(), constant.span, "const operand"); + match constant.literal { + mir::Literal::Promoted { .. } => { + // don't report errors inside promoteds, just warnings. + }, + mir::Literal::Value { .. } => { + err.report(bx.tcx(), constant.span, "const operand") + }, + } // We've errored, so we don't have to produce working code. let layout = bx.cx.layout_of(ty); PlaceRef::new_sized( diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 36debf677da..d657db0b125 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -363,7 +363,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { trait_def_id, self_ty, trait_ref.path.segments.last().unwrap()); - let poly_trait_ref = ty::Binder(ty::TraitRef::new(trait_def_id, substs)); + let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs)); poly_projections.extend(assoc_bindings.iter().filter_map(|binding| { // specify type to assert that error was already reported in Err case: @@ -485,7 +485,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok let late_bound_in_trait_ref = tcx.collect_constrained_late_bound_regions(&trait_ref); let late_bound_in_ty = - tcx.collect_referenced_late_bound_regions(&ty::Binder(binding.ty)); + tcx.collect_referenced_late_bound_regions(&ty::Binder::bind(binding.ty)); debug!("late_bound_in_trait_ref = {:?}", late_bound_in_trait_ref); debug!("late_bound_in_ty = {:?}", late_bound_in_ty); for br in late_bound_in_ty.difference(&late_bound_in_trait_ref) { @@ -639,7 +639,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } for projection_bound in &projection_bounds { - associated_types.remove(&projection_bound.0.projection_ty.item_def_id); + associated_types.remove(&projection_bound.projection_def_id()); } for item_def_id in associated_types { @@ -654,6 +654,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { .emit(); } + // skip_binder is okay, because the predicates are re-bound. let mut v = iter::once(ty::ExistentialPredicate::Trait(*existential_principal.skip_binder())) .chain(auto_traits.into_iter().map(ty::ExistentialPredicate::AutoTrait)) @@ -661,7 +662,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { .map(|x| ty::ExistentialPredicate::Projection(*x.skip_binder()))) .collect::<AccumulateVec<[_; 8]>>(); v.sort_by(|a, b| a.cmp(tcx, b)); - let existential_predicates = ty::Binder(tcx.mk_existential_predicates(v.into_iter())); + let existential_predicates = ty::Binder::bind(tcx.mk_existential_predicates(v.into_iter())); // Explicitly specified region bound. Use that. @@ -825,7 +826,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { }; let candidates = - traits::supertraits(tcx, ty::Binder(trait_ref)) + traits::supertraits(tcx, ty::Binder::bind(trait_ref)) .filter(|r| self.trait_defines_associated_type_named(r.def_id(), assoc_name)); @@ -853,7 +854,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } }; - let trait_did = bound.0.def_id; + let trait_did = bound.def_id(); let (assoc_ident, def_scope) = tcx.adjust(assoc_name, trait_did, ref_id); let item = tcx.associated_items(trait_did).find(|i| { Namespace::from(i.kind) == Namespace::Type && @@ -1184,7 +1185,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { debug!("ty_of_fn: output_ty={:?}", output_ty); - let bare_fn_ty = ty::Binder(tcx.mk_fn_sig( + let bare_fn_ty = ty::Binder::bind(tcx.mk_fn_sig( input_tys.into_iter(), output_ty, decl.variadic, @@ -1396,7 +1397,8 @@ impl<'a, 'gcx, 'tcx> Bounds<'tcx> { // account for the binder being introduced below; no need to shift `param_ty` // because, at present at least, it can only refer to early-bound regions let region_bound = tcx.mk_region(ty::fold::shift_region(*region_bound, 1)); - vec.push(ty::Binder(ty::OutlivesPredicate(param_ty, region_bound)).to_predicate()); + vec.push( + ty::Binder::dummy(ty::OutlivesPredicate(param_ty, region_bound)).to_predicate()); } for bound_trait_ref in &self.trait_bounds { diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index b1fb0938698..0c95f5eeb43 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -267,7 +267,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // This is the "default" function signature, used in case of error. // In that case, we check each argument against "error" in order to // set up all the node type bindings. - (ty::Binder(self.tcx.mk_fn_sig( + (ty::Binder::bind(self.tcx.mk_fn_sig( self.err_args(arg_exprs.len()).into_iter(), self.tcx.types.err, false, diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 68b0560355f..ed0613860d0 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -303,7 +303,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { return None; } - let arg_param_ty = trait_ref.substs().type_at(1); + let arg_param_ty = trait_ref.skip_binder().substs.type_at(1); let arg_param_ty = self.resolve_type_vars_if_possible(&arg_param_ty); debug!( "deduce_sig_from_projection: arg_param_ty {:?}", @@ -317,7 +317,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } }; - let ret_param_ty = projection.0.ty; + let ret_param_ty = projection.skip_binder().ty; let ret_param_ty = self.resolve_type_vars_if_possible(&ret_param_ty); debug!( "deduce_sig_from_projection: ret_param_ty {:?}", @@ -458,7 +458,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // regions appearing free in `expected_sig` are now bound up // in this binder we are creating. assert!(!expected_sig.sig.has_regions_escaping_depth(1)); - let bound_sig = ty::Binder(self.tcx.mk_fn_sig( + let bound_sig = ty::Binder::bind(self.tcx.mk_fn_sig( expected_sig.sig.inputs().iter().cloned(), expected_sig.sig.output(), decl.variadic, @@ -562,7 +562,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let (supplied_ty, _) = self.infcx.replace_late_bound_regions_with_fresh_var( hir_ty.span, LateBoundRegionConversionTime::FnCall, - &ty::Binder(supplied_ty), + &ty::Binder::bind(supplied_ty), ); // recreated from (*) above // Check that E' = S'. @@ -607,7 +607,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { hir::DefaultReturn(_) => astconv.ty_infer(decl.output.span()), }; - let result = ty::Binder(self.tcx.mk_fn_sig( + let result = ty::Binder::bind(self.tcx.mk_fn_sig( supplied_arguments, supplied_return, decl.variadic, @@ -639,7 +639,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { hir::DefaultReturn(_) => {} } - let result = ty::Binder(self.tcx.mk_fn_sig( + let result = ty::Binder::bind(self.tcx.mk_fn_sig( supplied_arguments, self.tcx.types.err, decl.variadic, diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index a8d1f69dfe8..8c69608a261 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -558,7 +558,8 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { let trait_ref = match obligation.predicate { 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 { + let sty = &tr.skip_binder().input_types().nth(1).unwrap().sty; + if let ty::TyTuple(..) = sty { debug!("coerce_unsized: found unsized tuple coercion"); has_unsized_tuple_coercion = true; } diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index e1e3dea9a2a..c9e53fa7674 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -234,9 +234,11 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut selcx = traits::SelectionContext::new(&infcx); let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_skol_substs); - let (impl_m_own_bounds, _) = infcx.replace_late_bound_regions_with_fresh_var(impl_m_span, - infer::HigherRankedType, - &ty::Binder(impl_m_own_bounds.predicates)); + let (impl_m_own_bounds, _) = infcx.replace_late_bound_regions_with_fresh_var( + impl_m_span, + infer::HigherRankedType, + &ty::Binder::bind(impl_m_own_bounds.predicates) + ); for predicate in impl_m_own_bounds { let traits::Normalized { value: predicate, obligations } = traits::normalize(&mut selcx, param_env, normalize_cause.clone(), &predicate); @@ -270,7 +272,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_m_node_id, param_env, &impl_sig); - let impl_fty = tcx.mk_fn_ptr(ty::Binder(impl_sig)); + let impl_fty = tcx.mk_fn_ptr(ty::Binder::bind(impl_sig)); debug!("compare_impl_method: impl_fty={:?}", impl_fty); let trait_sig = tcx.liberate_late_bound_regions( @@ -283,7 +285,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_m_node_id, param_env, &trait_sig); - let trait_fty = tcx.mk_fn_ptr(ty::Binder(trait_sig)); + let trait_fty = tcx.mk_fn_ptr(ty::Binder::bind(trait_sig)); debug!("compare_impl_method: trait_fty={:?}", trait_fty); @@ -505,7 +507,7 @@ fn compare_self_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx.infer_ctxt().enter(|infcx| { let self_arg_ty = tcx.liberate_late_bound_regions( method.def_id, - &ty::Binder(self_arg_ty) + &ty::Binder::bind(self_arg_ty) ); let can_eq_self = |ty| infcx.can_eq(param_env, untransformed_self_ty, ty).is_ok(); match ExplicitSelf::determine(self_arg_ty, can_eq_self) { diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs index c50ee13723f..7bae5fe4fd1 100644 --- a/src/librustc_typeck/check/generator_interior.rs +++ b/src/librustc_typeck/check/generator_interior.rs @@ -129,7 +129,7 @@ pub fn resolve_interior<'a, 'gcx, 'tcx>(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, ty::BrAnon(counter))) }); - let witness = fcx.tcx.mk_generator_witness(ty::Binder(type_list)); + let witness = fcx.tcx.mk_generator_witness(ty::Binder::bind(type_list)); debug!("Types in generator after region replacement {:?}, span = {:?}", witness, body.value.span); diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index da0d4509353..64b0e7d0a7d 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -61,7 +61,7 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, return; } - let fty = tcx.mk_fn_ptr(ty::Binder(tcx.mk_fn_sig( + let fty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig( inputs.into_iter(), output, false, @@ -304,7 +304,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, "try" => { let mut_u8 = tcx.mk_mut_ptr(tcx.types.u8); - let fn_ty = ty::Binder(tcx.mk_fn_sig( + let fn_ty = ty::Binder::bind(tcx.mk_fn_sig( iter::once(mut_u8), tcx.mk_nil(), false, diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 7569bdccd5a..09feaaffc5b 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -125,7 +125,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // We won't add these if we encountered an illegal sized bound, so that we can use // a custom error in that case. if !illegal_sized_bound { - let method_ty = self.tcx.mk_fn_ptr(ty::Binder(method_sig)); + let method_ty = self.tcx.mk_fn_ptr(ty::Binder::bind(method_sig)); self.add_obligations(method_ty, all_substs, &method_predicates); } @@ -587,7 +587,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { } }) .any(|trait_pred| { - match trait_pred.0.self_ty().sty { + match trait_pred.skip_binder().self_ty().sty { ty::TyDynamic(..) => true, _ => false, } diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 49d0df555fa..5f55ee6163b 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -336,7 +336,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { &bounds)); // Also add an obligation for the method type being well-formed. - let method_ty = tcx.mk_fn_ptr(ty::Binder(fn_sig)); + let method_ty = tcx.mk_fn_ptr(ty::Binder::bind(fn_sig)); debug!("lookup_in_trait_adjusted: matched method method_ty={:?} obligation={:?}", method_ty, obligation); diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index de570956622..b41a6dcf384 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -471,6 +471,9 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { ty::TyStr => { let lang_def_id = lang_items.str_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); + + let lang_def_id = lang_items.str_alloc_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); } ty::TySlice(_) => { let lang_def_id = lang_items.slice_impl(); @@ -478,6 +481,12 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { let lang_def_id = lang_items.slice_u8_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); + + let lang_def_id = lang_items.slice_alloc_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + + let lang_def_id = lang_items.slice_u8_alloc_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); } ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => { let lang_def_id = lang_items.const_ptr_impl(); @@ -538,10 +547,16 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { ty::TyFloat(ast::FloatTy::F32) => { let lang_def_id = lang_items.f32_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); + + let lang_def_id = lang_items.f32_runtime_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); } ty::TyFloat(ast::FloatTy::F64) => { let lang_def_id = lang_items.f64_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); + + let lang_def_id = lang_items.f64_runtime_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); } _ => {} } @@ -635,7 +650,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { .filter_map(|predicate| { match *predicate { ty::Predicate::Trait(ref trait_predicate) => { - match trait_predicate.0.trait_ref.self_ty().sty { + match trait_predicate.skip_binder().trait_ref.self_ty().sty { ty::TyParam(ref p) if *p == param_ty => { Some(trait_predicate.to_poly_trait_ref()) } @@ -1189,7 +1204,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { if !selcx.evaluate_obligation(&o) { result = ProbeResult::NoMatch; if let &ty::Predicate::Trait(ref pred) = &o.predicate { - possibly_unsatisfied_predicates.push(pred.0.trait_ref); + possibly_unsatisfied_predicates.push(pred.skip_binder().trait_ref); } } } @@ -1470,7 +1485,7 @@ impl<'tcx> Candidate<'tcx> { // inference variables or other artifacts. This // means they are safe to put into the // `WhereClausePick`. - assert!(!trait_ref.substs().needs_infer()); + assert!(!trait_ref.skip_binder().substs.needs_infer()); WhereClausePick(trait_ref.clone()) } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index ca35153d571..4083d4a21ef 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1727,7 +1727,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { predicates: self.param_env.caller_bounds.iter().filter(|predicate| { match **predicate { ty::Predicate::Trait(ref data) => { - data.0.self_ty().is_param(index) + data.skip_binder().self_ty().is_param(index) } _ => false } @@ -2217,7 +2217,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } // Tries to apply a fallback to `ty` if it is an unsolved variable. - // Non-numerics get replaced with !, unconstrained ints with i32, + // Non-numerics get replaced with ! or () (depending on whether + // feature(never_type) is enabled, unconstrained ints with i32, // unconstrained floats with f64. // Fallback becomes very dubious if we have encountered type-checking errors. // In that case, fallback to TyError. @@ -2231,7 +2232,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { _ if self.is_tainted_by_errors() => self.tcx().types.err, UnconstrainedInt => self.tcx.types.i32, UnconstrainedFloat => self.tcx.types.f64, - Neither if self.type_var_diverges(ty) => self.tcx.types.never, + Neither if self.type_var_diverges(ty) => self.tcx.mk_diverging_default(), Neither => return false, }; debug!("default_type_parameters: defaulting `{:?}` to `{:?}`", ty, fallback); diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 6348f386177..9c4807bec2f 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -508,7 +508,7 @@ fn check_method_receiver<'fcx, 'gcx, 'tcx>(fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, let self_ty = fcx.normalize_associated_types_in(span, &self_ty); let self_ty = fcx.tcx.liberate_late_bound_regions( method.def_id, - &ty::Binder(self_ty) + &ty::Binder::bind(self_ty) ); let self_arg_ty = sig.inputs()[0]; @@ -517,7 +517,7 @@ fn check_method_receiver<'fcx, 'gcx, 'tcx>(fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, let self_arg_ty = fcx.normalize_associated_types_in(span, &self_arg_ty); let self_arg_ty = fcx.tcx.liberate_late_bound_regions( method.def_id, - &ty::Binder(self_arg_ty) + &ty::Binder::bind(self_arg_ty) ); let mut autoderef = fcx.autoderef(span, self_arg_ty).include_raw_pointers(); diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs index d43ab0d3713..532f1da4f30 100644 --- a/src/librustc_typeck/coherence/inherent_impls.rs +++ b/src/librustc_typeck/coherence/inherent_impls.rs @@ -114,6 +114,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { ty::TyChar => { self.check_primitive_impl(def_id, lang_items.char_impl(), + None, "char", "char", item.span); @@ -121,6 +122,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { ty::TyStr => { self.check_primitive_impl(def_id, lang_items.str_impl(), + lang_items.str_alloc_impl(), "str", "str", item.span); @@ -128,6 +130,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { ty::TySlice(slice_item) if slice_item == self.tcx.types.u8 => { self.check_primitive_impl(def_id, lang_items.slice_u8_impl(), + lang_items.slice_u8_alloc_impl(), "slice_u8", "[u8]", item.span); @@ -135,6 +138,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { ty::TySlice(_) => { self.check_primitive_impl(def_id, lang_items.slice_impl(), + lang_items.slice_alloc_impl(), "slice", "[T]", item.span); @@ -142,6 +146,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => { self.check_primitive_impl(def_id, lang_items.const_ptr_impl(), + None, "const_ptr", "*const T", item.span); @@ -149,6 +154,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => { self.check_primitive_impl(def_id, lang_items.mut_ptr_impl(), + None, "mut_ptr", "*mut T", item.span); @@ -156,6 +162,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { ty::TyInt(ast::IntTy::I8) => { self.check_primitive_impl(def_id, lang_items.i8_impl(), + None, "i8", "i8", item.span); @@ -163,6 +170,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { ty::TyInt(ast::IntTy::I16) => { self.check_primitive_impl(def_id, lang_items.i16_impl(), + None, "i16", "i16", item.span); @@ -170,6 +178,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { ty::TyInt(ast::IntTy::I32) => { self.check_primitive_impl(def_id, lang_items.i32_impl(), + None, "i32", "i32", item.span); @@ -177,6 +186,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { ty::TyInt(ast::IntTy::I64) => { self.check_primitive_impl(def_id, lang_items.i64_impl(), + None, "i64", "i64", item.span); @@ -184,6 +194,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { ty::TyInt(ast::IntTy::I128) => { self.check_primitive_impl(def_id, lang_items.i128_impl(), + None, "i128", "i128", item.span); @@ -191,6 +202,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { ty::TyInt(ast::IntTy::Isize) => { self.check_primitive_impl(def_id, lang_items.isize_impl(), + None, "isize", "isize", item.span); @@ -198,6 +210,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { ty::TyUint(ast::UintTy::U8) => { self.check_primitive_impl(def_id, lang_items.u8_impl(), + None, "u8", "u8", item.span); @@ -205,6 +218,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { ty::TyUint(ast::UintTy::U16) => { self.check_primitive_impl(def_id, lang_items.u16_impl(), + None, "u16", "u16", item.span); @@ -212,6 +226,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { ty::TyUint(ast::UintTy::U32) => { self.check_primitive_impl(def_id, lang_items.u32_impl(), + None, "u32", "u32", item.span); @@ -219,6 +234,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { ty::TyUint(ast::UintTy::U64) => { self.check_primitive_impl(def_id, lang_items.u64_impl(), + None, "u64", "u64", item.span); @@ -226,6 +242,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { ty::TyUint(ast::UintTy::U128) => { self.check_primitive_impl(def_id, lang_items.u128_impl(), + None, "u128", "u128", item.span); @@ -233,6 +250,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { ty::TyUint(ast::UintTy::Usize) => { self.check_primitive_impl(def_id, lang_items.usize_impl(), + None, "usize", "usize", item.span); @@ -240,6 +258,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { ty::TyFloat(ast::FloatTy::F32) => { self.check_primitive_impl(def_id, lang_items.f32_impl(), + lang_items.f32_runtime_impl(), "f32", "f32", item.span); @@ -247,6 +266,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { ty::TyFloat(ast::FloatTy::F64) => { self.check_primitive_impl(def_id, lang_items.f64_impl(), + lang_items.f64_runtime_impl(), "f64", "f64", item.span); @@ -305,11 +325,15 @@ impl<'a, 'tcx> InherentCollect<'a, 'tcx> { fn check_primitive_impl(&self, impl_def_id: DefId, lang_def_id: Option<DefId>, + lang_def_id2: Option<DefId>, lang: &str, ty: &str, span: Span) { - match lang_def_id { - Some(lang_def_id) if lang_def_id == impl_def_id => { + match (lang_def_id, lang_def_id2) { + (Some(lang_def_id), _) if lang_def_id == impl_def_id => { + // OK + } + (_, Some(lang_def_id)) if lang_def_id == impl_def_id => { // OK } _ => { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 6bd38244e8c..fb8c6ba6401 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1171,7 +1171,7 @@ fn fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let inputs = fields.iter().map(|f| { tcx.type_of(tcx.hir.local_def_id(f.id)) }); - ty::Binder(tcx.mk_fn_sig( + ty::Binder::bind(tcx.mk_fn_sig( inputs, ty, false, @@ -1434,7 +1434,7 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, for bound in ¶m.bounds { let bound_region = AstConv::ast_region_to_region(&icx, bound, None); - let outlives = ty::Binder(ty::OutlivesPredicate(region, bound_region)); + let outlives = ty::Binder::bind(ty::OutlivesPredicate(region, bound_region)); predicates.push(outlives.to_predicate()); } } @@ -1482,7 +1482,7 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let region = AstConv::ast_region_to_region(&icx, lifetime, None); - let pred = ty::Binder(ty::OutlivesPredicate(ty, region)); + let pred = ty::Binder::bind(ty::OutlivesPredicate(ty, region)); predicates.push(ty::Predicate::TypeOutlives(pred)) } } @@ -1493,7 +1493,7 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let r1 = AstConv::ast_region_to_region(&icx, ®ion_pred.lifetime, None); for bound in ®ion_pred.bounds { let r2 = AstConv::ast_region_to_region(&icx, bound, None); - let pred = ty::Binder(ty::OutlivesPredicate(r1, r2)); + let pred = ty::Binder::bind(ty::OutlivesPredicate(r1, r2)); predicates.push(ty::Predicate::RegionOutlives(pred)) } } @@ -1627,7 +1627,7 @@ fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>, } hir::RegionTyParamBound(ref lifetime) => { let region = astconv.ast_region_to_region(lifetime, None); - let pred = ty::Binder(ty::OutlivesPredicate(param_ty, region)); + let pred = ty::Binder::bind(ty::OutlivesPredicate(param_ty, region)); vec![ty::Predicate::TypeOutlives(pred)] } hir::TraitTyParamBound(_, hir::TraitBoundModifier::Maybe) => { @@ -1682,6 +1682,7 @@ fn is_foreign_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn from_target_feature( tcx: TyCtxt, + id: DefId, attr: &ast::Attribute, whitelist: &FxHashMap<String, Option<String>>, target_features: &mut Vec<Symbol>, @@ -1752,7 +1753,7 @@ fn from_target_feature( Some(name) => bug!("unknown target feature gate {}", name), None => true, }; - if !allowed { + if !allowed && id.is_local() { feature_gate::emit_feature_err( &tcx.sess.parse_sess, feature_gate.as_ref().unwrap(), @@ -1877,7 +1878,7 @@ fn trans_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> TransFnAt `unsafe` function"; tcx.sess.span_err(attr.span, msg); } - from_target_feature(tcx, attr, &whitelist, &mut trans_fn_attrs.target_features); + from_target_feature(tcx, id, attr, &whitelist, &mut trans_fn_attrs.target_features); } else if attr.check_name("linkage") { if let Some(val) = attr.value_str() { trans_fn_attrs.linkage = Some(linkage_by_name(tcx, id, &val.as_str())); diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index ae3b2b22ea1..e3f7ff5cb3f 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4526,23 +4526,23 @@ but the type of the numeric value or binding could not be identified. The error happens on numeric literals: ```compile_fail,E0689 -2.0.powi(2); +2.0.recip(); ``` and on numeric bindings without an identified concrete type: ```compile_fail,E0689 let x = 2.0; -x.powi(2); // same error as above +x.recip(); // same error as above ``` Because of this, you must give the numeric literal or binding a type: ``` -let _ = 2.0_f32.powi(2); +let _ = 2.0_f32.recip(); let x: f32 = 2.0; -let _ = x.powi(2); -let _ = (2.0 as f32).powi(2); +let _ = x.recip(); +let _ = (2.0 as f32).recip(); ``` "##, diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 4b66939963e..d29ee3d9b3a 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -82,6 +82,7 @@ This API is completely unstable and subject to change. #![feature(slice_patterns)] #![feature(slice_sort_by_cached_key)] #![feature(dyn_trait)] +#![feature(never_type)] #[macro_use] extern crate log; #[macro_use] extern crate syntax; @@ -211,7 +212,7 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx.mk_nil() }; - let se_ty = tcx.mk_fn_ptr(ty::Binder( + let se_ty = tcx.mk_fn_ptr(ty::Binder::bind( tcx.mk_fn_sig( iter::empty(), expected_return_type, @@ -260,7 +261,7 @@ fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, _ => () } - let se_ty = tcx.mk_fn_ptr(ty::Binder( + let se_ty = tcx.mk_fn_ptr(ty::Binder::bind( tcx.mk_fn_sig( [ tcx.types.isize, diff --git a/src/librustc_typeck/outlives/implicit_infer.rs b/src/librustc_typeck/outlives/implicit_infer.rs index ac53a6d4a3f..65c78d3593f 100644 --- a/src/librustc_typeck/outlives/implicit_infer.rs +++ b/src/librustc_typeck/outlives/implicit_infer.rs @@ -258,7 +258,7 @@ fn check_explicit_predicates<'tcx>( // where OutlivesPredicate<type1, region1> is the predicate // we want to add. ty::Predicate::TypeOutlives(poly) => { - let predicate = poly.0.subst(tcx, substs); + let predicate = poly.skip_binder().subst(tcx, substs); insert_outlives_predicate( tcx, predicate.0.into(), @@ -271,7 +271,7 @@ fn check_explicit_predicates<'tcx>( // where OutlivesPredicate<region1, region2> is the predicate // we want to add. ty::Predicate::RegionOutlives(poly) => { - let predicate = poly.0.subst(tcx, substs); + let predicate = poly.skip_binder().subst(tcx, substs); insert_outlives_predicate( tcx, predicate.0.into(), diff --git a/src/librustc_typeck/outlives/mod.rs b/src/librustc_typeck/outlives/mod.rs index bad0c68a6fe..e5af4c60691 100644 --- a/src/librustc_typeck/outlives/mod.rs +++ b/src/librustc_typeck/outlives/mod.rs @@ -89,11 +89,11 @@ fn inferred_outlives_crate<'tcx>( let vec: Vec<ty::Predicate<'tcx>> = set.iter() .map( |ty::OutlivesPredicate(kind1, region2)| match kind1.unpack() { - UnpackedKind::Type(ty1) => ty::Predicate::TypeOutlives(ty::Binder( + UnpackedKind::Type(ty1) => ty::Predicate::TypeOutlives(ty::Binder::bind( ty::OutlivesPredicate(ty1, region2), )), UnpackedKind::Lifetime(region1) => ty::Predicate::RegionOutlives( - ty::Binder(ty::OutlivesPredicate(region1, region2)), + ty::Binder::bind(ty::OutlivesPredicate(region1, region2)), ), }, ) diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index a24e501aba9..b5e7effa61e 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -313,11 +313,13 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { if let Some(p) = data.principal() { let poly_trait_ref = p.with_self_ty(self.tcx(), self.tcx().types.err); - self.add_constraints_from_trait_ref(current, poly_trait_ref.0, variance); + self.add_constraints_from_trait_ref( + current, *poly_trait_ref.skip_binder(), variance); } for projection in data.projection_bounds() { - self.add_constraints_from_ty(current, projection.0.ty, self.invariant); + self.add_constraints_from_ty( + current, projection.skip_binder().ty, self.invariant); } } @@ -399,10 +401,10 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { sig: ty::PolyFnSig<'tcx>, variance: VarianceTermPtr<'a>) { let contra = self.contravariant(variance); - for &input in sig.0.inputs() { + for &input in sig.skip_binder().inputs() { self.add_constraints_from_ty(current, input, contra); } - self.add_constraints_from_ty(current, sig.0.output(), variance); + self.add_constraints_from_ty(current, sig.skip_binder().output(), variance); } /// Adds constraints appropriate for a region appearing in a diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 52d5dbe3f05..477b576ad21 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -286,7 +286,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { substs: tcx.mk_substs_trait(ty, &[]), }; - let trait_pred = ty::Binder(trait_ref); + let trait_pred = ty::Binder::bind(trait_ref); let bail_out = tcx.infer_ctxt().enter(|infcx| { let mut selcx = SelectionContext::with_negative(&infcx, true); @@ -622,7 +622,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { let mut already_visited = FxHashSet(); let mut predicates = VecDeque::new(); - predicates.push_back(ty::Binder(ty::TraitPredicate { + predicates.push_back(ty::Binder::bind(ty::TraitPredicate { trait_ref: ty::TraitRef { def_id: trait_did, substs: infcx.tcx.mk_substs_trait(ty, &[]), diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 090adc27ef0..23e0c2625ee 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -10,10 +10,7 @@ //! Support for inlining external documentation into the current AST. -use std::collections::BTreeMap; -use std::io; use std::iter::once; -use rustc_data_structures::sync::Lrc; use syntax::ast; use rustc::hir; @@ -289,10 +286,15 @@ pub fn build_impls(cx: &DocContext, did: DefId, auto_traits: bool) -> Vec<clean: lang_items.u128_impl(), lang_items.f32_impl(), lang_items.f64_impl(), + lang_items.f32_runtime_impl(), + lang_items.f64_runtime_impl(), lang_items.char_impl(), lang_items.str_impl(), lang_items.slice_impl(), lang_items.slice_u8_impl(), + lang_items.str_alloc_impl(), + lang_items.slice_alloc_impl(), + lang_items.slice_u8_alloc_impl(), lang_items.const_ptr_impl(), lang_items.mut_ptr_impl(), ]; @@ -408,27 +410,8 @@ fn build_module(cx: &DocContext, did: DefId) -> clean::Module { } } -struct InlinedConst { - nested_bodies: Lrc<BTreeMap<hir::BodyId, hir::Body>> -} - -impl hir::print::PpAnn for InlinedConst { - fn nested(&self, state: &mut hir::print::State, nested: hir::print::Nested) - -> io::Result<()> { - if let hir::print::Nested::Body(body) = nested { - state.print_expr(&self.nested_bodies[&body].value) - } else { - Ok(()) - } - } -} - pub fn print_inlined_const(cx: &DocContext, did: DefId) -> String { - let body = cx.tcx.extern_const_body(did).body; - let inlined = InlinedConst { - nested_bodies: cx.tcx.item_body_nested_bodies(did).nested_bodies - }; - hir::print::to_string(&inlined, |s| s.print_expr(&body.value)) + cx.tcx.rendered_const(did) } fn build_const(cx: &DocContext, did: DefId) -> clean::Constant { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 443caa7618d..e37b3a7fcc4 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -120,7 +120,7 @@ impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> { impl<T, U> Clean<U> for ty::Binder<T> where T: Clean<U> { fn clean(&self, cx: &DocContext) -> U { - self.0.clean(cx) + self.skip_binder().clean(cx) } } @@ -2846,15 +2846,15 @@ impl<'tcx> Clean<Type> for Ty<'tcx> { } let mut bindings = vec![]; - for ty::Binder(ref pb) in obj.projection_bounds() { + for pb in obj.projection_bounds() { bindings.push(TypeBinding { - name: cx.tcx.associated_item(pb.item_def_id).name.clean(cx), - ty: pb.ty.clean(cx) + name: cx.tcx.associated_item(pb.item_def_id()).name.clean(cx), + ty: pb.skip_binder().ty.clean(cx) }); } let path = external_path(cx, &cx.tcx.item_name(did), Some(did), - false, bindings, principal.0.substs); + false, bindings, principal.skip_binder().substs); ResolvedPath { path, typarams: Some(typarams), diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index 0eb4f9ba7e5..b7767606a6a 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -154,7 +154,7 @@ fn trait_is_same_or_supertrait(cx: &DocContext, child: DefId, let predicates = cx.tcx.super_predicates_of(child).predicates; predicates.iter().filter_map(|pred| { if let ty::Predicate::Trait(ref pred) = *pred { - if pred.0.trait_ref.self_ty().is_self() { + if pred.skip_binder().trait_ref.self_ty().is_self() { Some(pred.def_id()) } else { None diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 9fb024fd906..2bd1e72f0eb 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -155,10 +155,10 @@ pub fn run_core(search_paths: SearchPaths, actually_rustdoc: true, debugging_opts: config::DebuggingOptions { force_unstable_if_unmarked, - edition, ..config::basic_debugging_options() }, error_format, + edition, ..config::basic_options().clone() }; diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs index e9c6488c49c..537828de2c7 100644 --- a/src/librustdoc/html/item_type.rs +++ b/src/librustdoc/html/item_type.rs @@ -19,7 +19,7 @@ use clean; /// discriminants. JavaScript then is used to decode them into the original value. /// Consequently, every change to this type should be synchronized to /// the `itemTypes` mapping table in `static/main.js`. -#[derive(Copy, PartialEq, Clone)] +#[derive(Copy, PartialEq, Clone, Debug)] pub enum ItemType { Module = 0, ExternCrate = 1, diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 583c9f2b671..fd54e9bd1e0 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -85,6 +85,9 @@ pub fn render<T: fmt::Display, S: fmt::Display>( autocomplete=\"off\" \ placeholder=\"Click or press ‘S’ to search, ‘?’ for more options…\" \ type=\"search\">\ + <a id=\"settings-menu\" href=\"{root_path}settings.html\">\ + <img src=\"{root_path}wheel{suffix}.svg\" width=\"18\" alt=\"Change settings\">\ + </a>\ </div>\ </form>\ </nav>\ @@ -145,6 +148,7 @@ pub fn render<T: fmt::Display, S: fmt::Display>( </script>\ <script src=\"{root_path}main{suffix}.js\"></script>\ <script defer src=\"{root_path}search-index.js\"></script>\ + <script defer src=\"{root_path}aliases.js\"></script>\ </body>\ </html>", css_extension = if css_file_extension { @@ -181,9 +185,10 @@ pub fn render<T: fmt::Display, S: fmt::Display>( themes = themes.iter() .filter_map(|t| t.file_stem()) .filter_map(|t| t.to_str()) - .map(|t| format!(r#"<link rel="stylesheet" type="text/css" href="{}{}">"#, + .map(|t| format!(r#"<link rel="stylesheet" type="text/css" href="{}{}{}.css">"#, page.root_path, - t.replace(".css", &format!("{}.css", page.resource_suffix)))) + t, + page.resource_suffix)) .collect::<String>(), suffix=page.resource_suffix, ) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 651319743aa..0ae946c4182 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -329,6 +329,10 @@ pub struct Cache { // yet when its implementation methods are being indexed. Caches such methods // and their parent id here and indexes them at the end of crate parsing. orphan_impl_items: Vec<(DefId, clean::Item)>, + + /// Aliases added through `#[doc(alias = "...")]`. Since a few items can have the same alias, + /// we need the alias element to have an array of items. + aliases: FxHashMap<String, Vec<IndexItem>>, } /// Temporary storage for data obtained during `RustdocVisitor::clean()`. @@ -369,6 +373,7 @@ struct Sidebar<'a> { cx: &'a Context, item: &'a clean::Item, } /// Struct representing one entry in the JS search index. These are all emitted /// by hand to a large JS file at the end of cache-creation. +#[derive(Debug)] struct IndexItem { ty: ItemType, name: String, @@ -396,6 +401,7 @@ impl ToJson for IndexItem { } /// A type used for the search index. +#[derive(Debug)] struct Type { name: Option<String>, generics: Option<Vec<String>>, @@ -418,9 +424,10 @@ impl ToJson for Type { } /// Full type of functions/methods in the search index. +#[derive(Debug)] struct IndexItemFunctionType { inputs: Vec<Type>, - output: Option<Type> + output: Option<Type>, } impl ToJson for IndexItemFunctionType { @@ -609,6 +616,7 @@ pub fn run(mut krate: clean::Crate, owned_box_did, masked_crates: mem::replace(&mut krate.masked_crates, FxHashSet()), typarams: external_typarams, + aliases: FxHashMap(), }; // Cache where all our extern crates are located @@ -742,6 +750,8 @@ fn write_shared(cx: &Context, write(cx.dst.join(&format!("rustdoc{}.css", cx.shared.resource_suffix)), include_bytes!("static/rustdoc.css"))?; + write(cx.dst.join(&format!("settings{}.css", cx.shared.resource_suffix)), + include_bytes!("static/settings.css"))?; // To avoid "light.css" to be overwritten, we'll first run over the received themes and only // then we'll run over the "official" styles. @@ -761,6 +771,8 @@ fn write_shared(cx: &Context, write(cx.dst.join(&format!("brush{}.svg", cx.shared.resource_suffix)), include_bytes!("static/brush.svg"))?; + write(cx.dst.join(&format!("wheel{}.svg", cx.shared.resource_suffix)), + include_bytes!("static/wheel.svg"))?; write(cx.dst.join(&format!("light{}.css", cx.shared.resource_suffix)), include_bytes!("static/themes/light.css"))?; themes.insert("light".to_owned()); @@ -794,8 +806,7 @@ themePicker.onclick = function() {{ switchTheme(currentTheme, mainTheme, item); }}; themes.appendChild(but); -}}); -"#, +}});"#, themes.iter() .map(|s| format!("\"{}\"", s)) .collect::<Vec<String>>() @@ -804,6 +815,8 @@ themePicker.onclick = function() {{ write(cx.dst.join(&format!("main{}.js", cx.shared.resource_suffix)), include_bytes!("static/main.js"))?; + write(cx.dst.join(&format!("settings{}.js", cx.shared.resource_suffix)), + include_bytes!("static/settings.js"))?; { let mut data = format!("var resourcesSuffix = \"{}\";\n", @@ -847,8 +860,7 @@ themePicker.onclick = function() {{ write(cx.dst.join("COPYRIGHT.txt"), include_bytes!("static/COPYRIGHT.txt"))?; - fn collect(path: &Path, krate: &str, - key: &str) -> io::Result<Vec<String>> { + fn collect(path: &Path, krate: &str, key: &str) -> io::Result<Vec<String>> { let mut ret = Vec::new(); if path.exists() { for line in BufReader::new(File::open(path)?).lines() { @@ -865,6 +877,40 @@ themePicker.onclick = function() {{ Ok(ret) } + fn show_item(item: &IndexItem, krate: &str) -> String { + format!("{{'crate':'{}','ty':{},'name':'{}','path':'{}'{}}}", + krate, item.ty as usize, item.name, item.path, + if let Some(p) = item.parent_idx { + format!(",'parent':{}", p) + } else { + String::new() + }) + } + + let dst = cx.dst.join("aliases.js"); + { + let mut all_aliases = try_err!(collect(&dst, &krate.name, "ALIASES"), &dst); + let mut w = try_err!(File::create(&dst), &dst); + let mut output = String::with_capacity(100); + for (alias, items) in &cache.aliases { + if items.is_empty() { + continue + } + output.push_str(&format!("\"{}\":[{}],", + alias, + items.iter() + .map(|v| show_item(v, &krate.name)) + .collect::<Vec<_>>() + .join(","))); + } + all_aliases.push(format!("ALIASES['{}'] = {{{}}};", krate.name, output)); + all_aliases.sort(); + try_err!(writeln!(&mut w, "var ALIASES = {{}};"), &dst); + for aliases in &all_aliases { + try_err!(writeln!(&mut w, "{}", aliases), &dst); + } + } + // Update the search index let dst = cx.dst.join("search-index.js"); let mut all_indexes = try_err!(collect(&dst, &krate.name, "searchIndex"), &dst); @@ -1251,13 +1297,13 @@ impl DocFolder for Cache { // `public_items` map, so we can skip inserting into the // paths map if there was already an entry present and we're // not a public item. - if - !self.paths.contains_key(&item.def_id) || - self.access_levels.is_public(item.def_id) + if !self.paths.contains_key(&item.def_id) || + self.access_levels.is_public(item.def_id) { self.paths.insert(item.def_id, (self.stack.clone(), item.type_())); } + self.add_aliases(&item); } // Link variants to their parent enum because pages aren't emitted // for each variant. @@ -1268,6 +1314,7 @@ impl DocFolder for Cache { } clean::PrimitiveItem(..) if item.visibility.is_some() => { + self.add_aliases(&item); self.paths.insert(item.def_id, (self.stack.clone(), item.type_())); } @@ -1372,6 +1419,36 @@ impl<'a> Cache { } } } + + fn add_aliases(&mut self, item: &clean::Item) { + if item.def_id.index == CRATE_DEF_INDEX { + return + } + if let Some(ref item_name) = item.name { + let path = self.paths.get(&item.def_id) + .map(|p| p.0.join("::").to_string()) + .unwrap_or("std".to_owned()); + for alias in item.attrs.lists("doc") + .filter(|a| a.check_name("alias")) + .filter_map(|a| a.value_str() + .map(|s| s.to_string().replace("\"", ""))) + .filter(|v| !v.is_empty()) + .collect::<FxHashSet<_>>() + .into_iter() { + self.aliases.entry(alias) + .or_insert(Vec::with_capacity(1)) + .push(IndexItem { + ty: item.type_(), + name: item_name.to_string(), + path: path.clone(), + desc: String::new(), + parent: None, + parent_idx: None, + search_type: get_index_search_type(&item), + }); + } + } + } } #[derive(Debug, Eq, PartialEq, Hash)] @@ -1503,6 +1580,51 @@ impl fmt::Display for AllTypes { } } +#[derive(Debug)] +struct Settings<'a> { + // (id, explanation, default value) + settings: Vec<(&'static str, &'static str, bool)>, + root_path: &'a str, + suffix: &'a str, +} + +impl<'a> Settings<'a> { + pub fn new(root_path: &'a str, suffix: &'a str) -> Settings<'a> { + Settings { + settings: vec![ + ("item-declarations", "Auto-hide item declarations.", true), + ("item-attributes", "Auto-hide item attributes.", true), + ], + root_path, + suffix, + } + } +} + +impl<'a> fmt::Display for Settings<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, +"<h1 class='fqn'>\ + <span class='in-band'>Rustdoc settings</span>\ +</h1>\ +<div class='settings'>{}</div>\ +<script src='{}settings{}.js'></script>", + self.settings.iter() + .map(|(id, text, enabled)| { + format!("<div class='setting-line'>\ + <label class='toggle'>\ + <input type='checkbox' id='{}' {}>\ + <span class='slider'></span>\ + </label>\ + <div>{}</div>\ + </div>", id, if *enabled { " checked" } else { "" }, text) + }) + .collect::<String>(), + self.root_path, + self.suffix) + } +} + impl Context { /// String representation of how to get back to the root path of the 'doc/' /// folder in terms of a relative URL. @@ -1546,6 +1668,8 @@ impl Context { }; let final_file = self.dst.join(&krate.name) .join("all.html"); + let settings_file = self.dst.join("settings.html"); + let crate_name = krate.name.clone(); item.name = Some(krate.name); @@ -1567,7 +1691,7 @@ impl Context { if !root_path.ends_with('/') { root_path.push('/'); } - let page = layout::Page { + let mut page = layout::Page { title: "List of all items in this crate", css_class: "mod", root_path: "../", @@ -1590,6 +1714,27 @@ impl Context { self.shared.css_file_extension.is_some(), &self.shared.themes), &final_file); + + // Generating settings page. + let settings = Settings::new("./", &self.shared.resource_suffix); + page.title = "Rustdoc settings"; + page.description = "Settings of Rustdoc"; + page.root_path = "./"; + + let mut w = BufWriter::new(try_err!(File::create(&settings_file), &settings_file)); + let mut themes = self.shared.themes.clone(); + let sidebar = "<p class='location'>Settings</p><div class='sidebar-elems'></div>"; + themes.push(PathBuf::from("settings.css")); + let mut layout = self.shared.layout.clone(); + layout.krate = String::new(); + layout.logo = String::new(); + layout.favicon = String::new(); + try_err!(layout::render(&mut w, &layout, + &page, &sidebar, &settings, + self.shared.css_file_extension.is_some(), + &themes), + &settings_file); + Ok(()) } diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 2546a9410a9..ef8bf2244d9 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -77,19 +77,13 @@ return false; } var end = start + className.length; - if (end < elemClass.length && elemClass[end] !== ' ') { - return false; - } - return true; + return !(end < elemClass.length && elemClass[end] !== ' '); } if (start > 0 && elemClass[start - 1] !== ' ') { return false; } var end = start + className.length; - if (end < elemClass.length && elemClass[end] !== ' ') { - return false; - } - return true; + return !(end < elemClass.length && elemClass[end] !== ' '); } return false; } @@ -320,7 +314,7 @@ } else if (ev.target.tagName === 'SPAN' && hasClass(ev.target.parentNode, 'line-numbers')) { var prev_id = 0; - var set_fragment = function (name) { + var set_fragment = function(name) { if (browserSupportsHistoryApi()) { history.replaceState(null, null, '#' + name); window.hashchange(); @@ -835,7 +829,7 @@ query.search = val; // searching by type } else if (val.search("->") > -1) { - var trimmer = function (s) { return s.trim(); }; + var trimmer = function(s) { return s.trim(); }; var parts = val.split("->").map(trimmer); var input = parts[0]; // sort inputs so that order does not matter @@ -1012,11 +1006,21 @@ } } - return { + var ret = { 'in_args': sortResults(results_in_args, true), 'returned': sortResults(results_returned, true), 'others': sortResults(results), }; + if (ALIASES[window.currentCrate][query.raw]) { + var aliases = ALIASES[window.currentCrate][query.raw]; + for (var i = 0; i < aliases.length; ++i) { + ret['others'].unshift(aliases[i]); + if (ret['others'].length > MAX_RESULTS) { + ret['others'].pop(); + } + } + } + return ret; } /** @@ -1197,11 +1201,13 @@ array.forEach(function(item) { var name, type, href, displayPath; - if (shown.indexOf(item) !== -1) { + var id_ty = item.ty + item.path + item.name; + if (shown.indexOf(id_ty) !== -1) { return; } - shown.push(item); + console.log(item); + shown.push(id_ty); name = item.name; type = itemTypes[item.ty]; @@ -1369,13 +1375,17 @@ function search(e) { var params = getQueryStringParams(); - var query = getQuery(document.getElementsByClassName('search-input')[0].value); + var search_input = document.getElementsByClassName('search-input')[0]; + var query = getQuery(search_input.value.trim()); if (e) { e.preventDefault(); } if (!query.query || query.id === currentResults) { + if (query.query.length > 0) { + putBackSearch(search_input); + } return; } @@ -1547,7 +1557,7 @@ startSearch(); // Draw a convenient sidebar of known crates if we have a listing - if (rootPath === '../') { + if (rootPath === '../' || rootPath === "./") { var sidebar = document.getElementsByClassName('sidebar-elems')[0]; if (sidebar) { var div = document.createElement('div'); @@ -1566,11 +1576,11 @@ crates.sort(); for (var i = 0; i < crates.length; ++i) { var klass = 'crate'; - if (crates[i] === window.currentCrate) { + if (rootPath !== "./" && crates[i] === window.currentCrate) { klass += ' current'; } var link = document.createElement('a'); - link.href = '../' + crates[i] + '/index.html'; + link.href = rootPath + crates[i] + '/index.html'; link.title = rawSearchIndex[crates[i]].doc; link.className = klass; link.textContent = crates[i]; @@ -1947,7 +1957,7 @@ otherMessage = ' Show type declaration'; } e.parentNode.insertBefore(createToggle(otherMessage), e); - if (otherMessage) { + if (otherMessage && getCurrentValue('rustdoc-item-declarations') !== "false") { collapseDocs(e.previousSibling.childNodes[0], "toggle"); } } @@ -2017,7 +2027,9 @@ onEach(document.getElementById('main').getElementsByTagName('pre'), function(e) { onEach(e.getElementsByClassName('attributes'), function(i_e) { i_e.parentNode.insertBefore(createToggleWrapper(), i_e); - collapseDocs(i_e.previousSibling.childNodes[0], "toggle"); + if (getCurrentValue("rustdoc-item-attributes") !== "false") { + collapseDocs(i_e.previousSibling.childNodes[0], "toggle"); + } }); }); @@ -2064,19 +2076,23 @@ }; }); + function putBackSearch(search_input) { + if (search_input.value !== "") { + addClass(document.getElementById("main"), "hidden"); + removeClass(document.getElementById("search"), "hidden"); + if (browserSupportsHistoryApi()) { + history.replaceState(search_input.value, + "", + "?search=" + encodeURIComponent(search_input.value)); + } + } + } + var search_input = document.getElementsByClassName("search-input")[0]; if (search_input) { search_input.onfocus = function() { - if (search_input.value !== "") { - addClass(document.getElementById("main"), "hidden"); - removeClass(document.getElementById("search"), "hidden"); - if (browserSupportsHistoryApi()) { - history.replaceState(search_input.value, - "", - "?search=" + encodeURIComponent(search_input.value)); - } - } + putBackSearch(this); }; } diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 4c6c8dcfdda..d6b3ab26af8 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -548,8 +548,16 @@ a { .block a.current.crate { font-weight: 500; } +.search-container { + position: relative; +} +.search-container > .top-button { + position: absolute; + right: 0; + top: 10px; +} .search-input { - width: 100%; + width: calc(100% - 34px); /* Override Normalize.css: we have margins and do not want to overflow - the `moz` attribute is necessary until Firefox 29, too early to drop at this point */ @@ -1224,7 +1232,14 @@ kbd { outline: none; } -#theme-picker { +#settings-menu { + position: absolute; + right: 0; + top: 10px; + outline: none; +} + +#theme-picker, #settings-menu { padding: 4px; width: 27px; height: 29px; diff --git a/src/librustdoc/html/static/settings.css b/src/librustdoc/html/static/settings.css new file mode 100644 index 00000000000..34835f3f22d --- /dev/null +++ b/src/librustdoc/html/static/settings.css @@ -0,0 +1,73 @@ +/** + * Copyright 2018 The Rust Project Developers. See the COPYRIGHT + * file at the top-level directory of this distribution and at + * http://rust-lang.org/COPYRIGHT. + * + * Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or + * http://www.apache.org/licenses/LICENSE-2.0> or the MIT license + * <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your + * option. This file may not be copied, modified, or distributed + * except according to those terms. + */ + +.setting-line { + padding: 5px; +} + +.setting-line > div { + max-width: calc(100% - 74px); + display: inline-block; + vertical-align: top; + font-size: 17px; + padding-top: 2px; +} + +.toggle { + position: relative; + display: inline-block; + width: 45px; + height: 27px; + margin-right: 20px; +} + +.toggle input { + display: none; +} + +.slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: #ccc; + -webkit-transition: .3s; + transition: .3s; +} + +.slider:before { + position: absolute; + content: ""; + height: 19px; + width: 19px; + left: 4px; + bottom: 4px; + background-color: white; + -webkit-transition: .3s; + transition: .3s; +} + +input:checked + .slider { + background-color: #2196F3; +} + +input:focus + .slider { + box-shadow: 0 0 1px #2196F3; +} + +input:checked + .slider:before { + -webkit-transform: translateX(19px); + -ms-transform: translateX(19px); + transform: translateX(19px); +} \ No newline at end of file diff --git a/src/librustdoc/html/static/settings.js b/src/librustdoc/html/static/settings.js new file mode 100644 index 00000000000..cc7c60082fb --- /dev/null +++ b/src/librustdoc/html/static/settings.js @@ -0,0 +1,41 @@ +/*! + * Copyright 2018 The Rust Project Developers. See the COPYRIGHT + * file at the top-level directory of this distribution and at + * http://rust-lang.org/COPYRIGHT. + * + * Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or + * http://www.apache.org/licenses/LICENSE-2.0> or the MIT license + * <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your + * option. This file may not be copied, modified, or distributed + * except according to those terms. + */ + +(function () { + function changeSetting(settingName, isEnabled) { + updateLocalStorage('rustdoc-' + settingName, isEnabled); + } + + function getSettingValue(settingName) { + return getCurrentValue('rustdoc-' + settingName); + } + + function setEvents() { + var elems = document.getElementsByClassName("slider"); + if (!elems || elems.length === 0) { + return; + } + for (var i = 0; i < elems.length; ++i) { + var toggle = elems[i].previousElementSibling; + var settingId = toggle.id; + var settingValue = getSettingValue(settingId); + if (settingValue !== null) { + toggle.checked = settingValue === "true"; + } + toggle.onchange = function() { + changeSetting(this.id, this.checked); + }; + } + } + + setEvents(); +})(); diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index 93971a205bf..da4be7db5aa 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -362,12 +362,13 @@ kbd { box-shadow-color: #c6cbd1; } -#theme-picker { +#theme-picker, #settings-menu { border-color: #e0e0e0; background: #f0f0f0; } -#theme-picker:hover, #theme-picker:focus { +#theme-picker:hover, #theme-picker:focus, +#settings-menu:hover, #settings-menu:focus { border-color: #ffb900; } diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index e13818b4bd2..12af01d2e24 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -356,12 +356,13 @@ kbd { box-shadow-color: #c6cbd1; } -#theme-picker { +#theme-picker, #settings-menu { border-color: #e0e0e0; background-color: #fff; } -#theme-picker:hover, #theme-picker:focus { +#theme-picker:hover, #theme-picker:focus, +#settings-menu:hover, #settings-menu:focus { border-color: #717171; } diff --git a/src/librustdoc/html/static/wheel.svg b/src/librustdoc/html/static/wheel.svg new file mode 100644 index 00000000000..44381a401a8 --- /dev/null +++ b/src/librustdoc/html/static/wheel.svg @@ -0,0 +1 @@ +<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'><svg enable-background="new 0 0 27.434 29.5" height="29.5px" id="Capa_1" version="1.1" viewBox="0 0 27.434 29.5" width="27.434px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g><path d="M27.315,18.389c-0.165-0.604-0.509-1.113-0.981-1.459c-0.042-0.144-0.083-0.429-0.015-0.761l0.037-0.177v-0.182V14.8 c0-1.247-0.006-1.277-0.048-1.472c-0.076-0.354-0.035-0.653,0.007-0.803c0.477-0.346,0.828-0.861,0.996-1.476 c0.261-0.956,0.076-2.091-0.508-3.114l-0.591-1.032c-0.746-1.307-1.965-2.119-3.182-2.119c-0.378,0-0.75,0.081-1.085,0.235 c-0.198-0.025-0.554-0.15-0.855-0.389l-0.103-0.082l-0.114-0.065l-1.857-1.067L18.92,3.36l-0.105-0.044 c-0.376-0.154-0.658-0.41-0.768-0.556C17.918,1.172,16.349,0,14.296,0H13.14c-2.043,0-3.608,1.154-3.749,2.721 C9.277,2.862,8.999,3.104,8.633,3.25l-0.1,0.039L8.439,3.341L6.495,4.406L6.363,4.479L6.245,4.573 C5.936,4.82,5.596,4.944,5.416,4.977c-0.314-0.139-0.66-0.21-1.011-0.21c-1.198,0-2.411,0.819-3.165,2.139L0.65,7.938 c-0.412,0.72-0.642,1.521-0.644,2.258c-0.003,0.952,0.362,1.756,1.013,2.256c0.034,0.155,0.061,0.448-0.016,0.786 c-0.038,0.168-0.062,0.28-0.062,1.563c0,1.148,0,1.148,0.015,1.262l0.009,0.073l0.017,0.073c0.073,0.346,0.045,0.643,0.011,0.802 C0.348,17.512-0.01,18.314,0,19.268c0.008,0.729,0.238,1.523,0.648,2.242l0.589,1.031c0.761,1.331,1.967,2.159,3.15,2.159 c0.324,0,0.645-0.064,0.938-0.187c0.167,0.038,0.492,0.156,0.813,0.416l0.11,0.088l0.124,0.07l2.045,1.156l0.102,0.057l0.107,0.043 c0.364,0.147,0.646,0.381,0.766,0.521c0.164,1.52,1.719,2.634,3.745,2.634h1.155c2.037,0,3.598-1.134,3.747-2.675 c0.117-0.145,0.401-0.393,0.774-0.549l0.111-0.047l0.105-0.062l1.96-1.159l0.105-0.062l0.097-0.075 c0.309-0.246,0.651-0.371,0.832-0.402c0.313,0.138,0.662,0.212,1.016,0.212c1.199,0,2.412-0.82,3.166-2.139l0.59-1.032 C27.387,20.48,27.575,19.342,27.315,18.389z M25.274,20.635l-0.59,1.032c-0.438,0.765-1.104,1.251-1.639,1.251 c-0.133,0-0.258-0.029-0.369-0.094c-0.15-0.086-0.346-0.127-0.566-0.127c-0.596,0-1.383,0.295-2.01,0.796l-1.96,1.157 c-1.016,0.425-1.846,1.291-1.846,1.929s-0.898,1.159-1.998,1.159H13.14c-1.1,0-1.998-0.514-1.998-1.141s-0.834-1.477-1.854-1.888 l-2.046-1.157c-0.636-0.511-1.425-0.814-2.006-0.814c-0.202,0-0.379,0.037-0.516,0.115c-0.101,0.057-0.214,0.084-0.333,0.084 c-0.518,0-1.179-0.498-1.62-1.271l-0.591-1.032c-0.545-0.954-0.556-1.983-0.024-2.286c0.532-0.305,0.78-1.432,0.551-2.506 c0,0,0-0.003,0-1.042c0-1.088,0.021-1.18,0.021-1.18c0.238-1.072-0.01-2.203-0.552-2.513C1.631,10.8,1.634,9.765,2.18,8.812 L2.769,7.78c0.438-0.766,1.103-1.251,1.636-1.251c0.131,0,0.255,0.029,0.365,0.092C4.92,6.707,5.114,6.747,5.334,6.747 c0.596,0,1.38-0.296,2.007-0.795l1.944-1.065c1.021-0.407,1.856-1.277,1.856-1.933c0-0.656,0.898-1.192,1.998-1.192h1.156V1.761 c1.1,0,1.998,0.545,1.998,1.211c0,0.667,0.832,1.554,1.849,1.973L20,6.013c0.618,0.489,1.401,0.775,2.012,0.775 c0.24,0,0.454-0.045,0.62-0.139c0.122-0.069,0.259-0.102,0.403-0.102c0.551,0,1.221,0.476,1.653,1.231l0.59,1.032 c0.544,0.953,0.518,2.004-0.062,2.334c-0.577,0.331-0.859,1.48-0.627,2.554c0,0,0.01,0.042,0.01,1.103c0,1.012,0,1.012,0,1.012 c-0.218,1.049,0.068,2.174,0.636,2.498C25.802,18.635,25.819,19.68,25.274,20.635z"/><path d="M13.61,7.611c-3.913,0-7.084,3.173-7.084,7.085c0,3.914,3.171,7.085,7.084,7.085s7.085-3.172,7.085-7.085 C20.695,10.784,17.523,7.611,13.61,7.611z M13.61,20.02c-2.936,0-5.323-2.388-5.323-5.323c0-2.935,2.388-5.323,5.323-5.323 s5.324,2.388,5.324,5.323C18.934,17.632,16.546,20.02,13.61,20.02z"/><path d="M13.682,9.908c-2.602,0-4.718,2.116-4.718,4.718c0,2.601,2.116,4.716,4.718,4.716c2.601,0,4.717-2.115,4.717-4.716 C18.399,12.024,16.283,9.908,13.682,9.908z M13.682,17.581c-1.633,0-2.956-1.323-2.956-2.955s1.323-2.956,2.956-2.956 c1.632,0,2.956,1.324,2.956,2.956S15.314,17.581,13.682,17.581z"/></g></svg> \ No newline at end of file diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 600e9eaa05f..c4eaa48e49d 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -80,9 +80,9 @@ pub fn run(input_path: &Path, lint_cap: Some(::rustc::lint::Level::Allow), actually_rustdoc: true, debugging_opts: config::DebuggingOptions { - edition, ..config::basic_debugging_options() }, + edition, ..config::basic_options().clone() }; @@ -223,9 +223,9 @@ fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize, test: as_test_harness, unstable_features: UnstableFeatures::from_environment(), debugging_opts: config::DebuggingOptions { - edition, ..config::basic_debugging_options() }, + edition, ..config::basic_options().clone() }; @@ -437,7 +437,7 @@ fn partition_source(s: &str) -> (String, String) { for line in s.lines() { let trimline = line.trim(); - let header = trimline.is_whitespace() || + let header = trimline.chars().all(|c| c.is_whitespace()) || trimline.starts_with("#![") || trimline.starts_with("#[macro_use] extern crate") || trimline.starts_with("extern crate"); diff --git a/src/libstd/alloc.rs b/src/libstd/alloc.rs index ff578ec42d2..a8578404467 100644 --- a/src/libstd/alloc.rs +++ b/src/libstd/alloc.rs @@ -13,10 +13,18 @@ #![unstable(issue = "32838", feature = "allocator_api")] #[doc(inline)] #[allow(deprecated)] pub use alloc_crate::alloc::Heap; -#[doc(inline)] pub use alloc_crate::alloc::Global; +#[doc(inline)] pub use alloc_crate::alloc::{Global, oom}; #[doc(inline)] pub use alloc_system::System; #[doc(inline)] pub use core::alloc::*; +#[cfg(not(stage0))] +#[cfg(not(test))] +#[doc(hidden)] +#[lang = "oom"] +pub extern fn rust_oom() -> ! { + rtabort!("memory allocation failed"); +} + #[cfg(not(test))] #[doc(hidden)] #[allow(unused_attributes)] @@ -35,10 +43,11 @@ pub mod __default_lib_allocator { System.alloc(layout) as *mut u8 } + #[cfg(stage0)] #[no_mangle] #[rustc_std_internal_symbol] pub unsafe extern fn __rdl_oom() -> ! { - System.oom() + super::oom() } #[no_mangle] diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 14ef8563bb0..a8c70489f44 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -11,7 +11,7 @@ use self::Entry::*; use self::VacantEntryState::*; -use alloc::{Global, Alloc, CollectionAllocErr}; +use alloc::{CollectionAllocErr, oom}; use cell::Cell; use borrow::Borrow; use cmp::max; @@ -784,7 +784,7 @@ impl<K, V, S> HashMap<K, V, S> pub fn reserve(&mut self, additional: usize) { match self.try_reserve(additional) { Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"), - Err(CollectionAllocErr::AllocErr) => Global.oom(), + Err(CollectionAllocErr::AllocErr) => oom(), Ok(()) => { /* yay */ } } } @@ -2126,8 +2126,8 @@ impl<'a, K, V> Entry<'a, K, V> { /// assert_eq!(map["poneyland"], 43); /// ``` #[stable(feature = "entry_and_modify", since = "1.26.0")] - pub fn and_modify<F>(self, mut f: F) -> Self - where F: FnMut(&mut V) + pub fn and_modify<F>(self, f: F) -> Self + where F: FnOnce(&mut V) { match self { Occupied(mut entry) => { diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index 115f9628a23..52c53dc3b12 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use alloc::{Global, Alloc, Layout, CollectionAllocErr}; +use alloc::{Global, Alloc, Layout, CollectionAllocErr, oom}; use cmp; use hash::{BuildHasher, Hash, Hasher}; use marker; @@ -770,7 +770,7 @@ impl<K, V> RawTable<K, V> { unsafe fn new_uninitialized(capacity: usize) -> RawTable<K, V> { match Self::try_new_uninitialized(capacity) { Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"), - Err(CollectionAllocErr::AllocErr) => Global.oom(), + Err(CollectionAllocErr::AllocErr) => oom(), Ok(table) => { table } } } @@ -809,7 +809,7 @@ impl<K, V> RawTable<K, V> { pub fn new(capacity: usize) -> RawTable<K, V> { match Self::try_new(capacity) { Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"), - Err(CollectionAllocErr::AllocErr) => Global.oom(), + Err(CollectionAllocErr::AllocErr) => oom(), Ok(table) => { table } } } diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 3c209928d43..749b8ccc13d 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -233,7 +233,7 @@ impl<'a> From<Cow<'a, str>> for Box<Error> { } } -#[stable(feature = "never_type", since = "1.26.0")] +#[unstable(feature = "never_type", issue = "35121")] impl Error for ! { fn description(&self) -> &str { *self } } @@ -284,14 +284,14 @@ impl Error for num::ParseIntError { } } -#[stable(feature = "try_from", since = "1.26.0")] +#[unstable(feature = "try_from", issue = "33417")] impl Error for num::TryFromIntError { fn description(&self) -> &str { self.__description() } } -#[stable(feature = "try_from", since = "1.26.0")] +#[unstable(feature = "try_from", issue = "33417")] impl Error for array::TryFromSliceError { fn description(&self) -> &str { self.__description() @@ -365,7 +365,7 @@ impl Error for cell::BorrowMutError { } } -#[stable(feature = "try_from", since = "1.26.0")] +#[unstable(feature = "try_from", issue = "33417")] impl Error for char::CharTryFromError { fn description(&self) -> &str { "converted integer out of range for `char`" diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index ca39089a958..26644c76957 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -19,10 +19,12 @@ #![allow(missing_docs)] #[cfg(not(test))] -use core::num; +#[cfg(stage0)] +use core::num::Float; #[cfg(not(test))] use intrinsics; #[cfg(not(test))] +#[cfg(stage0)] use num::FpCategory; #[cfg(not(test))] use sys::cmath; @@ -39,106 +41,11 @@ pub use core::f32::{MIN, MIN_POSITIVE, MAX}; pub use core::f32::consts; #[cfg(not(test))] -#[lang = "f32"] +#[cfg_attr(stage0, lang = "f32")] +#[cfg_attr(not(stage0), lang = "f32_runtime")] impl f32 { - /// Returns `true` if this value is `NaN` and false otherwise. - /// - /// ``` - /// use std::f32; - /// - /// let nan = f32::NAN; - /// let f = 7.0_f32; - /// - /// assert!(nan.is_nan()); - /// assert!(!f.is_nan()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn is_nan(self) -> bool { num::Float::is_nan(self) } - - /// Returns `true` if this value is positive infinity or negative infinity and - /// false otherwise. - /// - /// ``` - /// use std::f32; - /// - /// let f = 7.0f32; - /// let inf = f32::INFINITY; - /// let neg_inf = f32::NEG_INFINITY; - /// let nan = f32::NAN; - /// - /// assert!(!f.is_infinite()); - /// assert!(!nan.is_infinite()); - /// - /// assert!(inf.is_infinite()); - /// assert!(neg_inf.is_infinite()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn is_infinite(self) -> bool { num::Float::is_infinite(self) } - - /// Returns `true` if this number is neither infinite nor `NaN`. - /// - /// ``` - /// use std::f32; - /// - /// let f = 7.0f32; - /// let inf = f32::INFINITY; - /// let neg_inf = f32::NEG_INFINITY; - /// let nan = f32::NAN; - /// - /// assert!(f.is_finite()); - /// - /// assert!(!nan.is_finite()); - /// assert!(!inf.is_finite()); - /// assert!(!neg_inf.is_finite()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn is_finite(self) -> bool { num::Float::is_finite(self) } - - /// Returns `true` if the number is neither zero, infinite, - /// [subnormal][subnormal], or `NaN`. - /// - /// ``` - /// use std::f32; - /// - /// let min = f32::MIN_POSITIVE; // 1.17549435e-38f32 - /// let max = f32::MAX; - /// let lower_than_min = 1.0e-40_f32; - /// let zero = 0.0_f32; - /// - /// assert!(min.is_normal()); - /// assert!(max.is_normal()); - /// - /// assert!(!zero.is_normal()); - /// assert!(!f32::NAN.is_normal()); - /// assert!(!f32::INFINITY.is_normal()); - /// // Values between `0` and `min` are Subnormal. - /// assert!(!lower_than_min.is_normal()); - /// ``` - /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn is_normal(self) -> bool { num::Float::is_normal(self) } - - /// Returns the floating point category of the number. If only one property - /// is going to be tested, it is generally faster to use the specific - /// predicate instead. - /// - /// ``` - /// use std::num::FpCategory; - /// use std::f32; - /// - /// let num = 12.4_f32; - /// let inf = f32::INFINITY; - /// - /// assert_eq!(num.classify(), FpCategory::Normal); - /// assert_eq!(inf.classify(), FpCategory::Infinite); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn classify(self) -> FpCategory { num::Float::classify(self) } + #[cfg(stage0)] + f32_core_methods!(); /// Returns the largest integer less than or equal to a number. /// @@ -257,7 +164,9 @@ impl f32 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn abs(self) -> f32 { num::Float::abs(self) } + pub fn abs(self) -> f32 { + unsafe { intrinsics::fabsf32(self) } + } /// Returns a number that represents the sign of `self`. /// @@ -277,35 +186,13 @@ impl f32 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn signum(self) -> f32 { num::Float::signum(self) } - - /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with - /// positive sign bit and positive infinity. - /// - /// ``` - /// let f = 7.0_f32; - /// let g = -7.0_f32; - /// - /// assert!(f.is_sign_positive()); - /// assert!(!g.is_sign_positive()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn is_sign_positive(self) -> bool { num::Float::is_sign_positive(self) } - - /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with - /// negative sign bit and negative infinity. - /// - /// ``` - /// let f = 7.0f32; - /// let g = -7.0f32; - /// - /// assert!(!f.is_sign_negative()); - /// assert!(g.is_sign_negative()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn is_sign_negative(self) -> bool { num::Float::is_sign_negative(self) } + pub fn signum(self) -> f32 { + if self.is_nan() { + NAN + } else { + unsafe { intrinsics::copysignf32(1.0, self) } + } + } /// Fused multiply-add. Computes `(self * a) + b` with only one rounding /// error. This produces a more accurate result with better performance than @@ -380,20 +267,6 @@ impl f32 { } - /// Takes the reciprocal (inverse) of a number, `1/x`. - /// - /// ``` - /// use std::f32; - /// - /// let x = 2.0_f32; - /// let abs_difference = (x.recip() - (1.0/x)).abs(); - /// - /// assert!(abs_difference <= f32::EPSILON); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn recip(self) -> f32 { num::Float::recip(self) } - /// Raises a number to an integer power. /// /// Using this function is generally faster than using `powf` @@ -408,7 +281,9 @@ impl f32 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn powi(self, n: i32) -> f32 { num::Float::powi(self, n) } + pub fn powi(self, n: i32) -> f32 { + unsafe { intrinsics::powif32(self, n) } + } /// Raises a number to a floating point power. /// @@ -584,68 +459,6 @@ impl f32 { return unsafe { intrinsics::log10f32(self) }; } - /// Converts radians to degrees. - /// - /// ``` - /// use std::f32::{self, consts}; - /// - /// let angle = consts::PI; - /// - /// let abs_difference = (angle.to_degrees() - 180.0).abs(); - /// - /// assert!(abs_difference <= f32::EPSILON); - /// ``` - #[stable(feature = "f32_deg_rad_conversions", since="1.7.0")] - #[inline] - pub fn to_degrees(self) -> f32 { num::Float::to_degrees(self) } - - /// Converts degrees to radians. - /// - /// ``` - /// use std::f32::{self, consts}; - /// - /// let angle = 180.0f32; - /// - /// let abs_difference = (angle.to_radians() - consts::PI).abs(); - /// - /// assert!(abs_difference <= f32::EPSILON); - /// ``` - #[stable(feature = "f32_deg_rad_conversions", since="1.7.0")] - #[inline] - pub fn to_radians(self) -> f32 { num::Float::to_radians(self) } - - /// Returns the maximum of the two numbers. - /// - /// ``` - /// let x = 1.0f32; - /// let y = 2.0f32; - /// - /// assert_eq!(x.max(y), y); - /// ``` - /// - /// If one of the arguments is NaN, then the other argument is returned. - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn max(self, other: f32) -> f32 { - num::Float::max(self, other) - } - - /// Returns the minimum of the two numbers. - /// - /// ``` - /// let x = 1.0f32; - /// let y = 2.0f32; - /// - /// assert_eq!(x.min(y), x); - /// ``` - /// - /// If one of the arguments is NaN, then the other argument is returned. - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn min(self, other: f32) -> f32 { - num::Float::min(self, other) - } - /// The positive difference of two numbers. /// /// * If `self <= other`: `0:0` @@ -1046,73 +859,6 @@ impl f32 { pub fn atanh(self) -> f32 { 0.5 * ((2.0 * self) / (1.0 - self)).ln_1p() } - - /// Raw transmutation to `u32`. - /// - /// This is currently identical to `transmute::<f32, u32>(self)` on all platforms. - /// - /// See `from_bits` for some discussion of the portability of this operation - /// (there are almost no issues). - /// - /// Note that this function is distinct from `as` casting, which attempts to - /// preserve the *numeric* value, and not the bitwise value. - /// - /// # Examples - /// - /// ``` - /// assert_ne!((1f32).to_bits(), 1f32 as u32); // to_bits() is not casting! - /// assert_eq!((12.5f32).to_bits(), 0x41480000); - /// - /// ``` - #[stable(feature = "float_bits_conv", since = "1.20.0")] - #[inline] - pub fn to_bits(self) -> u32 { - num::Float::to_bits(self) - } - - /// Raw transmutation from `u32`. - /// - /// This is currently identical to `transmute::<u32, f32>(v)` on all platforms. - /// It turns out this is incredibly portable, for two reasons: - /// - /// * Floats and Ints have the same endianness on all supported platforms. - /// * IEEE-754 very precisely specifies the bit layout of floats. - /// - /// However there is one caveat: prior to the 2008 version of IEEE-754, how - /// to interpret the NaN signaling bit wasn't actually specified. Most platforms - /// (notably x86 and ARM) picked the interpretation that was ultimately - /// standardized in 2008, but some didn't (notably MIPS). As a result, all - /// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa. - /// - /// Rather than trying to preserve signaling-ness cross-platform, this - /// implementation favours preserving the exact bits. This means that - /// any payloads encoded in NaNs will be preserved even if the result of - /// this method is sent over the network from an x86 machine to a MIPS one. - /// - /// If the results of this method are only manipulated by the same - /// architecture that produced them, then there is no portability concern. - /// - /// If the input isn't NaN, then there is no portability concern. - /// - /// If you don't care about signalingness (very likely), then there is no - /// portability concern. - /// - /// Note that this function is distinct from `as` casting, which attempts to - /// preserve the *numeric* value, and not the bitwise value. - /// - /// # Examples - /// - /// ``` - /// use std::f32; - /// let v = f32::from_bits(0x41480000); - /// let difference = (v - 12.5).abs(); - /// assert!(difference <= 1e-5); - /// ``` - #[stable(feature = "float_bits_conv", since = "1.20.0")] - #[inline] - pub fn from_bits(v: u32) -> Self { - num::Float::from_bits(v) - } } #[cfg(test)] diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index a9585670ad0..a7e63f59b1c 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -19,10 +19,12 @@ #![allow(missing_docs)] #[cfg(not(test))] -use core::num; +#[cfg(stage0)] +use core::num::Float; #[cfg(not(test))] use intrinsics; #[cfg(not(test))] +#[cfg(stage0)] use num::FpCategory; #[cfg(not(test))] use sys::cmath; @@ -39,106 +41,11 @@ pub use core::f64::{MIN, MIN_POSITIVE, MAX}; pub use core::f64::consts; #[cfg(not(test))] -#[lang = "f64"] +#[cfg_attr(stage0, lang = "f64")] +#[cfg_attr(not(stage0), lang = "f64_runtime")] impl f64 { - /// Returns `true` if this value is `NaN` and false otherwise. - /// - /// ``` - /// use std::f64; - /// - /// let nan = f64::NAN; - /// let f = 7.0_f64; - /// - /// assert!(nan.is_nan()); - /// assert!(!f.is_nan()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn is_nan(self) -> bool { num::Float::is_nan(self) } - - /// Returns `true` if this value is positive infinity or negative infinity and - /// false otherwise. - /// - /// ``` - /// use std::f64; - /// - /// let f = 7.0f64; - /// let inf = f64::INFINITY; - /// let neg_inf = f64::NEG_INFINITY; - /// let nan = f64::NAN; - /// - /// assert!(!f.is_infinite()); - /// assert!(!nan.is_infinite()); - /// - /// assert!(inf.is_infinite()); - /// assert!(neg_inf.is_infinite()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn is_infinite(self) -> bool { num::Float::is_infinite(self) } - - /// Returns `true` if this number is neither infinite nor `NaN`. - /// - /// ``` - /// use std::f64; - /// - /// let f = 7.0f64; - /// let inf: f64 = f64::INFINITY; - /// let neg_inf: f64 = f64::NEG_INFINITY; - /// let nan: f64 = f64::NAN; - /// - /// assert!(f.is_finite()); - /// - /// assert!(!nan.is_finite()); - /// assert!(!inf.is_finite()); - /// assert!(!neg_inf.is_finite()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn is_finite(self) -> bool { num::Float::is_finite(self) } - - /// Returns `true` if the number is neither zero, infinite, - /// [subnormal][subnormal], or `NaN`. - /// - /// ``` - /// use std::f64; - /// - /// let min = f64::MIN_POSITIVE; // 2.2250738585072014e-308f64 - /// let max = f64::MAX; - /// let lower_than_min = 1.0e-308_f64; - /// let zero = 0.0f64; - /// - /// assert!(min.is_normal()); - /// assert!(max.is_normal()); - /// - /// assert!(!zero.is_normal()); - /// assert!(!f64::NAN.is_normal()); - /// assert!(!f64::INFINITY.is_normal()); - /// // Values between `0` and `min` are Subnormal. - /// assert!(!lower_than_min.is_normal()); - /// ``` - /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn is_normal(self) -> bool { num::Float::is_normal(self) } - - /// Returns the floating point category of the number. If only one property - /// is going to be tested, it is generally faster to use the specific - /// predicate instead. - /// - /// ``` - /// use std::num::FpCategory; - /// use std::f64; - /// - /// let num = 12.4_f64; - /// let inf = f64::INFINITY; - /// - /// assert_eq!(num.classify(), FpCategory::Normal); - /// assert_eq!(inf.classify(), FpCategory::Infinite); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn classify(self) -> FpCategory { num::Float::classify(self) } + #[cfg(stage0)] + f64_core_methods!(); /// Returns the largest integer less than or equal to a number. /// @@ -235,7 +142,9 @@ impl f64 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn abs(self) -> f64 { num::Float::abs(self) } + pub fn abs(self) -> f64 { + unsafe { intrinsics::fabsf64(self) } + } /// Returns a number that represents the sign of `self`. /// @@ -255,45 +164,13 @@ impl f64 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn signum(self) -> f64 { num::Float::signum(self) } - - /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with - /// positive sign bit and positive infinity. - /// - /// ``` - /// let f = 7.0_f64; - /// let g = -7.0_f64; - /// - /// assert!(f.is_sign_positive()); - /// assert!(!g.is_sign_positive()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn is_sign_positive(self) -> bool { num::Float::is_sign_positive(self) } - - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_deprecated(since = "1.0.0", reason = "renamed to is_sign_positive")] - #[inline] - pub fn is_positive(self) -> bool { num::Float::is_sign_positive(self) } - - /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with - /// negative sign bit and negative infinity. - /// - /// ``` - /// let f = 7.0_f64; - /// let g = -7.0_f64; - /// - /// assert!(!f.is_sign_negative()); - /// assert!(g.is_sign_negative()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn is_sign_negative(self) -> bool { num::Float::is_sign_negative(self) } - - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_deprecated(since = "1.0.0", reason = "renamed to is_sign_negative")] - #[inline] - pub fn is_negative(self) -> bool { num::Float::is_sign_negative(self) } + pub fn signum(self) -> f64 { + if self.is_nan() { + NAN + } else { + unsafe { intrinsics::copysignf64(1.0, self) } + } + } /// Fused multiply-add. Computes `(self * a) + b` with only one rounding /// error. This produces a more accurate result with better performance than @@ -365,18 +242,6 @@ impl f64 { } } - /// Takes the reciprocal (inverse) of a number, `1/x`. - /// - /// ``` - /// let x = 2.0_f64; - /// let abs_difference = (x.recip() - (1.0/x)).abs(); - /// - /// assert!(abs_difference < 1e-10); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn recip(self) -> f64 { num::Float::recip(self) } - /// Raises a number to an integer power. /// /// Using this function is generally faster than using `powf` @@ -389,7 +254,9 @@ impl f64 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn powi(self, n: i32) -> f64 { num::Float::powi(self, n) } + pub fn powi(self, n: i32) -> f64 { + unsafe { intrinsics::powif64(self, n) } + } /// Raises a number to a floating point power. /// @@ -535,68 +402,6 @@ impl f64 { self.log_wrapper(|n| { unsafe { intrinsics::log10f64(n) } }) } - /// Converts radians to degrees. - /// - /// ``` - /// use std::f64::consts; - /// - /// let angle = consts::PI; - /// - /// let abs_difference = (angle.to_degrees() - 180.0).abs(); - /// - /// assert!(abs_difference < 1e-10); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn to_degrees(self) -> f64 { num::Float::to_degrees(self) } - - /// Converts degrees to radians. - /// - /// ``` - /// use std::f64::consts; - /// - /// let angle = 180.0_f64; - /// - /// let abs_difference = (angle.to_radians() - consts::PI).abs(); - /// - /// assert!(abs_difference < 1e-10); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn to_radians(self) -> f64 { num::Float::to_radians(self) } - - /// Returns the maximum of the two numbers. - /// - /// ``` - /// let x = 1.0_f64; - /// let y = 2.0_f64; - /// - /// assert_eq!(x.max(y), y); - /// ``` - /// - /// If one of the arguments is NaN, then the other argument is returned. - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn max(self, other: f64) -> f64 { - num::Float::max(self, other) - } - - /// Returns the minimum of the two numbers. - /// - /// ``` - /// let x = 1.0_f64; - /// let y = 2.0_f64; - /// - /// assert_eq!(x.min(y), x); - /// ``` - /// - /// If one of the arguments is NaN, then the other argument is returned. - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn min(self, other: f64) -> f64 { - num::Float::min(self, other) - } - /// The positive difference of two numbers. /// /// * If `self <= other`: `0:0` @@ -1000,73 +805,6 @@ impl f64 { } } } - - /// Raw transmutation to `u64`. - /// - /// This is currently identical to `transmute::<f64, u64>(self)` on all platforms. - /// - /// See `from_bits` for some discussion of the portability of this operation - /// (there are almost no issues). - /// - /// Note that this function is distinct from `as` casting, which attempts to - /// preserve the *numeric* value, and not the bitwise value. - /// - /// # Examples - /// - /// ``` - /// assert!((1f64).to_bits() != 1f64 as u64); // to_bits() is not casting! - /// assert_eq!((12.5f64).to_bits(), 0x4029000000000000); - /// - /// ``` - #[stable(feature = "float_bits_conv", since = "1.20.0")] - #[inline] - pub fn to_bits(self) -> u64 { - num::Float::to_bits(self) - } - - /// Raw transmutation from `u64`. - /// - /// This is currently identical to `transmute::<u64, f64>(v)` on all platforms. - /// It turns out this is incredibly portable, for two reasons: - /// - /// * Floats and Ints have the same endianness on all supported platforms. - /// * IEEE-754 very precisely specifies the bit layout of floats. - /// - /// However there is one caveat: prior to the 2008 version of IEEE-754, how - /// to interpret the NaN signaling bit wasn't actually specified. Most platforms - /// (notably x86 and ARM) picked the interpretation that was ultimately - /// standardized in 2008, but some didn't (notably MIPS). As a result, all - /// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa. - /// - /// Rather than trying to preserve signaling-ness cross-platform, this - /// implementation favours preserving the exact bits. This means that - /// any payloads encoded in NaNs will be preserved even if the result of - /// this method is sent over the network from an x86 machine to a MIPS one. - /// - /// If the results of this method are only manipulated by the same - /// architecture that produced them, then there is no portability concern. - /// - /// If the input isn't NaN, then there is no portability concern. - /// - /// If you don't care about signalingness (very likely), then there is no - /// portability concern. - /// - /// Note that this function is distinct from `as` casting, which attempts to - /// preserve the *numeric* value, and not the bitwise value. - /// - /// # Examples - /// - /// ``` - /// use std::f64; - /// let v = f64::from_bits(0x4029000000000000); - /// let difference = (v - 12.5).abs(); - /// assert!(difference <= 1e-5); - /// ``` - #[stable(feature = "float_bits_conv", since = "1.20.0")] - #[inline] - pub fn from_bits(v: u64) -> Self { - num::Float::from_bits(v) - } } #[cfg(test)] diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index d6eac748334..ee297d3783e 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -1251,6 +1251,7 @@ mod tests { } #[test] + #[allow(deprecated)] fn read_char_buffered() { let buf = [195, 159]; let reader = BufReader::with_capacity(1, &buf[..]); @@ -1258,6 +1259,7 @@ mod tests { } #[test] + #[allow(deprecated)] fn test_chars() { let buf = [195, 159, b'a']; let reader = BufReader::with_capacity(1, &buf[..]); diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs index 2673f3ccfa3..8ac52572810 100644 --- a/src/libstd/io/cursor.rs +++ b/src/libstd/io/cursor.rs @@ -566,6 +566,7 @@ mod tests { } #[test] + #[allow(deprecated)] fn test_read_char() { let b = &b"Vi\xE1\xBB\x87t"[..]; let mut c = Cursor::new(b).chars(); @@ -577,6 +578,7 @@ mod tests { } #[test] + #[allow(deprecated)] fn test_read_bad_char() { let b = &b"\x80"[..]; let mut c = Cursor::new(b).chars(); diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index b02e133ee4d..eba4e9fe703 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -840,6 +840,9 @@ pub trait Read { of where errors happen is currently \ unclear and may change", issue = "27802")] + #[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead: + https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")] + #[allow(deprecated)] fn chars(self) -> Chars<Self> where Self: Sized { Chars { inner: self } } @@ -2010,16 +2013,22 @@ impl<R: Read> Iterator for Bytes<R> { /// [chars]: trait.Read.html#method.chars #[unstable(feature = "io", reason = "awaiting stability of Read::chars", issue = "27802")] +#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead: + https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")] #[derive(Debug)] +#[allow(deprecated)] pub struct Chars<R> { inner: R, } /// An enumeration of possible errors that can be generated from the `Chars` /// adapter. -#[derive(Debug)] #[unstable(feature = "io", reason = "awaiting stability of Read::chars", issue = "27802")] +#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead: + https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")] +#[derive(Debug)] +#[allow(deprecated)] pub enum CharsError { /// Variant representing that the underlying stream was read successfully /// but it did not contain valid utf8 data. @@ -2031,6 +2040,7 @@ pub enum CharsError { #[unstable(feature = "io", reason = "awaiting stability of Read::chars", issue = "27802")] +#[allow(deprecated)] impl<R: Read> Iterator for Chars<R> { type Item = result::Result<char, CharsError>; @@ -2063,6 +2073,7 @@ impl<R: Read> Iterator for Chars<R> { #[unstable(feature = "io", reason = "awaiting stability of Read::chars", issue = "27802")] +#[allow(deprecated)] impl std_error::Error for CharsError { fn description(&self) -> &str { match *self { @@ -2080,6 +2091,7 @@ impl std_error::Error for CharsError { #[unstable(feature = "io", reason = "awaiting stability of Read::chars", issue = "27802")] +#[allow(deprecated)] impl fmt::Display for CharsError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 7d896695311..41992193135 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -252,7 +252,7 @@ #![feature(collections_range)] #![feature(compiler_builtins_lib)] #![feature(const_fn)] -#![feature(core_float)] +#![cfg_attr(stage0, feature(core_float))] #![feature(core_intrinsics)] #![feature(dropck_eyepatch)] #![feature(exact_size_is_empty)] @@ -260,6 +260,7 @@ #![feature(fs_read_write)] #![feature(fixed_size_array)] #![feature(float_from_str_radix)] +#![cfg_attr(stage0, feature(float_internals))] #![feature(fn_traits)] #![feature(fnbox)] #![cfg_attr(stage0, feature(generic_param_attrs))] @@ -275,6 +276,7 @@ #![feature(macro_reexport)] #![feature(macro_vis_matcher)] #![feature(needs_panic_runtime)] +#![feature(never_type)] #![feature(exhaustive_patterns)] #![feature(nonzero)] #![feature(num_bits_bytes)] @@ -306,6 +308,7 @@ #![feature(test, rustc_private)] #![feature(thread_local)] #![feature(toowned_clone_into)] +#![feature(try_from)] #![feature(try_reserve)] #![feature(unboxed_closures)] #![feature(untagged_unions)] @@ -316,6 +319,7 @@ #![feature(doc_spotlight)] #![cfg_attr(test, feature(update_panic_count))] #![cfg_attr(windows, feature(used))] +#![feature(doc_alias)] #![default_lib_allocator] @@ -457,6 +461,8 @@ pub use alloc_crate::vec; pub use core::char; #[stable(feature = "i128", since = "1.26.0")] pub use core::u128; +#[stable(feature = "core_hint", since = "1.27.0")] +pub use core::hint; pub mod f32; pub mod f64; @@ -478,7 +484,6 @@ pub mod path; pub mod process; pub mod sync; pub mod time; -pub mod alloc; #[unstable(feature = "allocator_api", issue = "32838")] #[rustc_deprecated(since = "1.27.0", reason = "module renamed to `alloc`")] @@ -492,6 +497,8 @@ pub mod heap { mod sys_common; mod sys; +pub mod alloc; + // Private support modules mod panicking; mod memchr; diff --git a/src/libstd/os/android/fs.rs b/src/libstd/os/android/fs.rs index a51b4655985..5899dc688e2 100644 --- a/src/libstd/os/android/fs.rs +++ b/src/libstd/os/android/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::android::raw; -/// OS-specific extension methods for `fs::Metadata` +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { /// Gain a reference to the underlying `stat` structure which contains diff --git a/src/libstd/os/bitrig/fs.rs b/src/libstd/os/bitrig/fs.rs index e4f1c9432f3..24caf326ab0 100644 --- a/src/libstd/os/bitrig/fs.rs +++ b/src/libstd/os/bitrig/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::bitrig::raw; -/// OS-specific extension methods for `fs::Metadata` +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { /// Gain a reference to the underlying `stat` structure which contains diff --git a/src/libstd/os/dragonfly/fs.rs b/src/libstd/os/dragonfly/fs.rs index db672e56435..6aea450774f 100644 --- a/src/libstd/os/dragonfly/fs.rs +++ b/src/libstd/os/dragonfly/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::dragonfly::raw; -/// OS-specific extension methods for `fs::Metadata` +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { /// Gain a reference to the underlying `stat` structure which contains diff --git a/src/libstd/os/emscripten/fs.rs b/src/libstd/os/emscripten/fs.rs index 8056ce4fdc4..e0e197dc122 100644 --- a/src/libstd/os/emscripten/fs.rs +++ b/src/libstd/os/emscripten/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::emscripten::raw; -/// OS-specific extension methods for `fs::Metadata` +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { /// Gain a reference to the underlying `stat` structure which contains diff --git a/src/libstd/os/freebsd/fs.rs b/src/libstd/os/freebsd/fs.rs index 2f17d2f7409..5f24cd636d5 100644 --- a/src/libstd/os/freebsd/fs.rs +++ b/src/libstd/os/freebsd/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::freebsd::raw; -/// OS-specific extension methods for `fs::Metadata` +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { /// Gain a reference to the underlying `stat` structure which contains diff --git a/src/libstd/os/fuchsia/fs.rs b/src/libstd/os/fuchsia/fs.rs index d22f9a628bd..16802576356 100644 --- a/src/libstd/os/fuchsia/fs.rs +++ b/src/libstd/os/fuchsia/fs.rs @@ -13,7 +13,9 @@ use fs::Metadata; use sys_common::AsInner; -/// OS-specific extension methods for `fs::Metadata` +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { #[stable(feature = "metadata_ext2", since = "1.8.0")] diff --git a/src/libstd/os/haiku/fs.rs b/src/libstd/os/haiku/fs.rs index 54f8ea1b71b..453136e0ac8 100644 --- a/src/libstd/os/haiku/fs.rs +++ b/src/libstd/os/haiku/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::haiku::raw; -/// OS-specific extension methods for `fs::Metadata` +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { /// Gain a reference to the underlying `stat` structure which contains diff --git a/src/libstd/os/ios/fs.rs b/src/libstd/os/ios/fs.rs index 275daf3d3a0..296ce69ff43 100644 --- a/src/libstd/os/ios/fs.rs +++ b/src/libstd/os/ios/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::ios::raw; -/// OS-specific extension methods for `fs::Metadata` +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { /// Gain a reference to the underlying `stat` structure which contains diff --git a/src/libstd/os/linux/fs.rs b/src/libstd/os/linux/fs.rs index 2be2fbcb2db..76fb10da850 100644 --- a/src/libstd/os/linux/fs.rs +++ b/src/libstd/os/linux/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::linux::raw; -/// OS-specific extension methods for `fs::Metadata` +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { /// Gain a reference to the underlying `stat` structure which contains diff --git a/src/libstd/os/macos/fs.rs b/src/libstd/os/macos/fs.rs index 12b44901d03..0b14c05cb55 100644 --- a/src/libstd/os/macos/fs.rs +++ b/src/libstd/os/macos/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::macos::raw; -/// OS-specific extension methods for `fs::Metadata` +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { /// Gain a reference to the underlying `stat` structure which contains diff --git a/src/libstd/os/netbsd/fs.rs b/src/libstd/os/netbsd/fs.rs index cd7d5fafd1c..e9cad33fee6 100644 --- a/src/libstd/os/netbsd/fs.rs +++ b/src/libstd/os/netbsd/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::netbsd::raw; -/// OS-specific extension methods for `fs::Metadata` +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { /// Gain a reference to the underlying `stat` structure which contains diff --git a/src/libstd/os/openbsd/fs.rs b/src/libstd/os/openbsd/fs.rs index cc812fcf12c..0f6b83b6e32 100644 --- a/src/libstd/os/openbsd/fs.rs +++ b/src/libstd/os/openbsd/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::openbsd::raw; -/// OS-specific extension methods for `fs::Metadata` +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { /// Gain a reference to the underlying `stat` structure which contains diff --git a/src/libstd/os/solaris/fs.rs b/src/libstd/os/solaris/fs.rs index 5dc43d03a86..19dce1ba34c 100644 --- a/src/libstd/os/solaris/fs.rs +++ b/src/libstd/os/solaris/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::solaris::raw; -/// OS-specific extension methods for `fs::Metadata` +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { /// Gain a reference to the underlying `stat` structure which contains diff --git a/src/libstd/path.rs b/src/libstd/path.rs index ec961575473..955a6af1ae6 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -298,10 +298,9 @@ pub const MAIN_SEPARATOR: char = ::sys::path::MAIN_SEP; // Iterate through `iter` while it matches `prefix`; return `None` if `prefix` // is not a prefix of `iter`, otherwise return `Some(iter_after_prefix)` giving // `iter` after having exhausted `prefix`. -fn iter_after<A, I, J>(mut iter: I, mut prefix: J) -> Option<I> - where I: Iterator<Item = A> + Clone, - J: Iterator<Item = A>, - A: PartialEq +fn iter_after<'a, 'b, I, J>(mut iter: I, mut prefix: J) -> Option<I> + where I: Iterator<Item = Component<'a>> + Clone, + J: Iterator<Item = Component<'b>>, { loop { let mut iter_next = iter.clone(); @@ -1967,7 +1966,7 @@ impl Path { /// # Examples /// /// ``` - /// use std::path::Path; + /// use std::path::{Path, PathBuf}; /// /// let path = Path::new("/test/haha/foo.txt"); /// @@ -1978,17 +1977,20 @@ impl Path { /// assert_eq!(path.strip_prefix("/test/haha/foo.txt/"), Ok(Path::new(""))); /// assert_eq!(path.strip_prefix("test").is_ok(), false); /// assert_eq!(path.strip_prefix("/haha").is_ok(), false); + /// + /// let prefix = PathBuf::from("/test/"); + /// assert_eq!(path.strip_prefix(prefix), Ok(Path::new("haha/foo.txt"))); /// ``` #[stable(since = "1.7.0", feature = "path_strip_prefix")] - pub fn strip_prefix<'a, P: ?Sized>(&'a self, base: &'a P) - -> Result<&'a Path, StripPrefixError> + pub fn strip_prefix<P>(&self, base: P) + -> Result<&Path, StripPrefixError> where P: AsRef<Path> { self._strip_prefix(base.as_ref()) } - fn _strip_prefix<'a>(&'a self, base: &'a Path) - -> Result<&'a Path, StripPrefixError> { + fn _strip_prefix(&self, base: &Path) + -> Result<&Path, StripPrefixError> { iter_after(self.components(), base.components()) .map(|c| c.as_path()) .ok_or(StripPrefixError(())) diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index ce4bbfffc2e..919d9648297 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -9,6 +9,8 @@ // except according to those terms. #[doc(primitive = "bool")] +#[doc(alias = "true")] +#[doc(alias = "false")] // /// The boolean type. /// @@ -68,6 +70,7 @@ mod prim_bool { } #[doc(primitive = "never")] +#[doc(alias = "!")] // /// The `!` type, also called "never". /// @@ -79,6 +82,7 @@ mod prim_bool { } /// write: /// /// ``` +/// #![feature(never_type)] /// # fn foo() -> u32 { /// let x: ! = { /// return 123 @@ -155,6 +159,7 @@ mod prim_bool { } /// for example: /// /// ``` +/// #![feature(never_type)] /// # use std::fmt; /// # trait Debug { /// # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result; @@ -499,6 +504,9 @@ mod prim_pointer { } mod prim_array { } #[doc(primitive = "slice")] +#[doc(alias = "[")] +#[doc(alias = "]")] +#[doc(alias = "[]")] // /// A dynamically-sized view into a contiguous sequence, `[T]`. /// @@ -597,6 +605,9 @@ mod prim_slice { } mod prim_str { } #[doc(primitive = "tuple")] +#[doc(alias = "(")] +#[doc(alias = ")")] +#[doc(alias = "()")] // /// A finite heterogeneous sequence, `(T, U, ..)`. /// @@ -819,6 +830,7 @@ mod prim_isize { } mod prim_usize { } #[doc(primitive = "reference")] +#[doc(alias = "&")] // /// References, both shared and mutable. /// diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 92f0406c09b..00051d4487a 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -1121,8 +1121,13 @@ impl ExitCode { } impl Child { - /// Forces the child to exit. This is equivalent to sending a - /// SIGKILL on unix platforms. + /// Forces the child process to exit. If the child has already exited, an [`InvalidInput`] + /// error is returned. + /// + /// The mapping to [`ErrorKind`]s is not part of the compatibility contract of the function, + /// especially the [`Other`] kind might change to more specific kinds in the future. + /// + /// This is equivalent to sending a SIGKILL on Unix platforms. /// /// # Examples /// @@ -1138,6 +1143,10 @@ impl Child { /// println!("yes command didn't start"); /// } /// ``` + /// + /// [`ErrorKind`]: ../io/enum.ErrorKind.html + /// [`InvalidInput`]: ../io/enum.ErrorKind.html#variant.InvalidInput + /// [`Other`]: ../io/enum.ErrorKind.html#variant.Other #[stable(feature = "process", since = "1.0.0")] pub fn kill(&mut self) -> io::Result<()> { self.handle.kill() diff --git a/src/libstd/sys/redox/ext/ffi.rs b/src/libstd/sys/redox/ext/ffi.rs index d59b4fc0b70..cd88c8f46b3 100644 --- a/src/libstd/sys/redox/ext/ffi.rs +++ b/src/libstd/sys/redox/ext/ffi.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Unix-specific extension to the primitives in the `std::ffi` module +//! Redox-specific extension to the primitives in the `std::ffi` module. #![stable(feature = "rust1", since = "1.0.0")] @@ -17,7 +17,9 @@ use mem; use sys::os_str::Buf; use sys_common::{FromInner, IntoInner, AsInner}; -/// Unix-specific extensions to `OsString`. +/// Redox-specific extensions to [`OsString`]. +/// +/// [`OsString`]: ../../../../std/ffi/struct.OsString.html #[stable(feature = "rust1", since = "1.0.0")] pub trait OsStringExt { /// Creates an `OsString` from a byte vector. @@ -39,7 +41,9 @@ impl OsStringExt for OsString { } } -/// Unix-specific extensions to `OsStr`. +/// Redox-specific extensions to [`OsStr`]. +/// +/// [`OsStr`]: ../../../../std/ffi/struct.OsStr.html #[stable(feature = "rust1", since = "1.0.0")] pub trait OsStrExt { #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/sys/redox/ext/fs.rs b/src/libstd/sys/redox/ext/fs.rs index 0f4762aa881..c1dba6edda4 100644 --- a/src/libstd/sys/redox/ext/fs.rs +++ b/src/libstd/sys/redox/ext/fs.rs @@ -18,7 +18,9 @@ use path::Path; use sys; use sys_common::{FromInner, AsInner, AsInnerMut}; -/// Redox-specific extensions to `Permissions` +/// Redox-specific extensions to [`fs::Permissions`]. +/// +/// [`fs::Permissions`]: ../../../../std/fs/struct.Permissions.html #[stable(feature = "fs_ext", since = "1.1.0")] pub trait PermissionsExt { /// Returns the underlying raw `mode_t` bits that are the standard Redox @@ -95,7 +97,9 @@ impl PermissionsExt for Permissions { } } -/// Redox-specific extensions to `OpenOptions` +/// Redox-specific extensions to [`fs::OpenOptions`]. +/// +/// [`fs::OpenOptions`]: ../../../../std/fs/struct.OpenOptions.html #[stable(feature = "fs_ext", since = "1.1.0")] pub trait OpenOptionsExt { /// Sets the mode bits that a new file will be created with. @@ -163,13 +167,9 @@ impl OpenOptionsExt for OpenOptions { } } -// Hm, why are there casts here to the returned type, shouldn't the types always -// be the same? Right you are! Turns out, however, on android at least the types -// in the raw `stat` structure are not the same as the types being returned. Who -// knew! -// -// As a result to make sure this compiles for all platforms we do the manual -// casts and rely on manual lowering to `stat` if the raw type is desired. +/// Redox-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { #[stable(feature = "metadata_ext", since = "1.1.0")] @@ -204,6 +204,13 @@ pub trait MetadataExt { fn blocks(&self) -> u64; } +// Hm, why are there casts here to the returned type, shouldn't the types always +// be the same? Right you are! Turns out, however, on android at least the types +// in the raw `stat` structure are not the same as the types being returned. Who +// knew! +// +// As a result to make sure this compiles for all platforms we do the manual +// casts and rely on manual lowering to `stat` if the raw type is desired. #[stable(feature = "metadata_ext", since = "1.1.0")] impl MetadataExt for fs::Metadata { fn dev(&self) -> u64 { @@ -253,7 +260,12 @@ impl MetadataExt for fs::Metadata { } } -/// Add special Redox types (block/char device, fifo and socket) +/// Redox-specific extensions for [`FileType`]. +/// +/// Adds support for special Unix file types such as block/character devices, +/// pipes, and sockets. +/// +/// [`FileType`]: ../../../../std/fs/struct.FileType.html #[stable(feature = "file_type_ext", since = "1.5.0")] pub trait FileTypeExt { /// Returns whether this file type is a block device. @@ -307,8 +319,10 @@ pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> sys::fs::symlink(src.as_ref(), dst.as_ref()) } +/// Redox-specific extensions to [`fs::DirBuilder`]. +/// +/// [`fs::DirBuilder`]: ../../../../std/fs/struct.DirBuilder.html #[stable(feature = "dir_builder", since = "1.6.0")] -/// An extension trait for `fs::DirBuilder` for Redox-specific options. pub trait DirBuilderExt { /// Sets the mode to create new directories with. This option defaults to /// 0o777. diff --git a/src/libstd/sys/redox/ext/process.rs b/src/libstd/sys/redox/ext/process.rs index e68e180acf1..cfb6d5fc703 100644 --- a/src/libstd/sys/redox/ext/process.rs +++ b/src/libstd/sys/redox/ext/process.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Unix-specific extensions to primitives in the `std::process` module. +//! Redox-specific extensions to primitives in the `std::process` module. #![stable(feature = "rust1", since = "1.0.0")] @@ -18,7 +18,9 @@ use process; use sys; use sys_common::{AsInnerMut, AsInner, FromInner, IntoInner}; -/// Unix-specific extensions to the `std::process::Command` builder +/// Redox-specific extensions to the [`process::Command`] builder, +/// +/// [`process::Command`]: ../../../../std/process/struct.Command.html #[stable(feature = "rust1", since = "1.0.0")] pub trait CommandExt { /// Sets the child process's user id. This translates to a @@ -107,7 +109,9 @@ impl CommandExt for process::Command { } } -/// Unix-specific extensions to `std::process::ExitStatus` +/// Redox-specific extensions to [`process::ExitStatus`]. +/// +/// [`process::ExitStatus`]: ../../../../std/process/struct.ExitStatus.html #[stable(feature = "rust1", since = "1.0.0")] pub trait ExitStatusExt { /// Creates a new `ExitStatus` from the raw underlying `i32` return value of diff --git a/src/libstd/sys/redox/ext/thread.rs b/src/libstd/sys/redox/ext/thread.rs index 52be2ccd9f9..71ff0d46b91 100644 --- a/src/libstd/sys/redox/ext/thread.rs +++ b/src/libstd/sys/redox/ext/thread.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Unix-specific extensions to primitives in the `std::thread` module. +//! Redox-specific extensions to primitives in the `std::thread` module. #![stable(feature = "thread_extensions", since = "1.9.0")] @@ -19,7 +19,9 @@ use thread::JoinHandle; #[allow(deprecated)] pub type RawPthread = usize; -/// Unix-specific extensions to `std::thread::JoinHandle` +/// Redox-specific extensions to [`thread::JoinHandle`]. +/// +/// [`thread::JoinHandle`]: ../../../../std/thread/struct.JoinHandle.html #[stable(feature = "thread_extensions", since = "1.9.0")] pub trait JoinHandleExt { /// Extracts the raw pthread_t without taking ownership diff --git a/src/libstd/sys/unix/ext/ffi.rs b/src/libstd/sys/unix/ext/ffi.rs index fb9984ccbdd..8347145db5a 100644 --- a/src/libstd/sys/unix/ext/ffi.rs +++ b/src/libstd/sys/unix/ext/ffi.rs @@ -17,7 +17,9 @@ use mem; use sys::os_str::Buf; use sys_common::{FromInner, IntoInner, AsInner}; -/// Unix-specific extensions to `OsString`. +/// Unix-specific extensions to [`OsString`]. +/// +/// [`OsString`]: ../../../../std/ffi/struct.OsString.html #[stable(feature = "rust1", since = "1.0.0")] pub trait OsStringExt { /// Creates an [`OsString`] from a byte vector. @@ -66,7 +68,9 @@ impl OsStringExt for OsString { } } -/// Unix-specific extensions to `OsStr`. +/// Unix-specific extensions to [`OsStr`]. +/// +/// [`OsStr`]: ../../../../std/ffi/struct.OsStr.html #[stable(feature = "rust1", since = "1.0.0")] pub trait OsStrExt { #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs index 3c5b9424fb0..4e981012669 100644 --- a/src/libstd/sys/unix/ext/fs.rs +++ b/src/libstd/sys/unix/ext/fs.rs @@ -105,7 +105,9 @@ impl FileExt for fs::File { } } -/// Unix-specific extensions to `Permissions` +/// Unix-specific extensions to [`fs::Permissions`]. +/// +/// [`fs::Permissions`]: ../../../../std/fs/struct.Permissions.html #[stable(feature = "fs_ext", since = "1.1.0")] pub trait PermissionsExt { /// Returns the underlying raw `st_mode` bits that contain the standard @@ -180,7 +182,9 @@ impl PermissionsExt for Permissions { } } -/// Unix-specific extensions to `OpenOptions` +/// Unix-specific extensions to [`fs::OpenOptions`]. +/// +/// [`fs::OpenOptions`]: ../../../../std/fs/struct.OpenOptions.html #[stable(feature = "fs_ext", since = "1.1.0")] pub trait OpenOptionsExt { /// Sets the mode bits that a new file will be created with. @@ -246,13 +250,9 @@ impl OpenOptionsExt for OpenOptions { } } -// Hm, why are there casts here to the returned type, shouldn't the types always -// be the same? Right you are! Turns out, however, on android at least the types -// in the raw `stat` structure are not the same as the types being returned. Who -// knew! -// -// As a result to make sure this compiles for all platforms we do the manual -// casts and rely on manual lowering to `stat` if the raw type is desired. +/// Unix-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { /// Returns the ID of the device containing the file. @@ -555,7 +555,12 @@ impl MetadataExt for fs::Metadata { fn blocks(&self) -> u64 { self.st_blocks() } } -/// Add support for special unix types (block/char device, fifo and socket). +/// Unix-specific extensions for [`FileType`]. +/// +/// Adds support for special Unix file types such as block/character devices, +/// pipes, and sockets. +/// +/// [`FileType`]: ../../../../std/fs/struct.FileType.html #[stable(feature = "file_type_ext", since = "1.5.0")] pub trait FileTypeExt { /// Returns whether this file type is a block device. @@ -701,10 +706,10 @@ pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> sys::fs::symlink(src.as_ref(), dst.as_ref()) } -#[stable(feature = "dir_builder", since = "1.6.0")] -/// An extension trait for [`fs::DirBuilder`] for unix-specific options. +/// Unix-specific extensions to [`fs::DirBuilder`]. /// /// [`fs::DirBuilder`]: ../../../../std/fs/struct.DirBuilder.html +#[stable(feature = "dir_builder", since = "1.6.0")] pub trait DirBuilderExt { /// Sets the mode to create new directories with. This option defaults to /// 0o777. diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index ba80cbe47c8..e277b1aa7b5 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -214,7 +214,10 @@ impl SocketAddr { let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) }; // macOS seems to return a len of 16 and a zeroed sun_path for unnamed addresses - if len == 0 || (cfg!(not(target_os = "linux")) && self.addr.sun_path[0] == 0) { + if len == 0 + || (cfg!(not(any(target_os = "linux", target_os = "android"))) + && self.addr.sun_path[0] == 0) + { AddressKind::Unnamed } else if self.addr.sun_path[0] == 0 { AddressKind::Abstract(&path[1..len]) diff --git a/src/libstd/sys/unix/ext/process.rs b/src/libstd/sys/unix/ext/process.rs index 7b4ec20d91f..21630ae9746 100644 --- a/src/libstd/sys/unix/ext/process.rs +++ b/src/libstd/sys/unix/ext/process.rs @@ -18,7 +18,9 @@ use process; use sys; use sys_common::{AsInnerMut, AsInner, FromInner, IntoInner}; -/// Unix-specific extensions to the `std::process::Command` builder +/// Unix-specific extensions to the [`process::Command`] builder. +/// +/// [`process::Command`]: ../../../../std/process/struct.Command.html #[stable(feature = "rust1", since = "1.0.0")] pub trait CommandExt { /// Sets the child process's user id. This translates to a @@ -117,7 +119,9 @@ impl CommandExt for process::Command { } } -/// Unix-specific extensions to `std::process::ExitStatus` +/// Unix-specific extensions to [`process::ExitStatus`]. +/// +/// [`process::ExitStatus`]: ../../../../std/process/struct.ExitStatus.html #[stable(feature = "rust1", since = "1.0.0")] pub trait ExitStatusExt { /// Creates a new `ExitStatus` from the raw underlying `i32` return value of diff --git a/src/libstd/sys/unix/ext/thread.rs b/src/libstd/sys/unix/ext/thread.rs index fe2a48764dc..8dadf29945c 100644 --- a/src/libstd/sys/unix/ext/thread.rs +++ b/src/libstd/sys/unix/ext/thread.rs @@ -21,7 +21,9 @@ use thread::JoinHandle; #[allow(deprecated)] pub type RawPthread = pthread_t; -/// Unix-specific extensions to `std::thread::JoinHandle` +/// Unix-specific extensions to [`thread::JoinHandle`]. +/// +/// [`thread::JoinHandle`]: ../../../../std/thread/struct.JoinHandle.html #[stable(feature = "thread_extensions", since = "1.9.0")] pub trait JoinHandleExt { /// Extracts the raw pthread_t without taking ownership diff --git a/src/libstd/sys/windows/ext/ffi.rs b/src/libstd/sys/windows/ext/ffi.rs index d6b8896ac09..98d43552489 100644 --- a/src/libstd/sys/windows/ext/ffi.rs +++ b/src/libstd/sys/windows/ext/ffi.rs @@ -76,7 +76,9 @@ use sys_common::{FromInner, AsInner}; #[stable(feature = "rust1", since = "1.0.0")] pub use sys_common::wtf8::EncodeWide; -/// Windows-specific extensions to `OsString`. +/// Windows-specific extensions to [`OsString`]. +/// +/// [`OsString`]: ../../../../std/ffi/struct.OsString.html #[stable(feature = "rust1", since = "1.0.0")] pub trait OsStringExt { /// Creates an `OsString` from a potentially ill-formed UTF-16 slice of @@ -109,7 +111,9 @@ impl OsStringExt for OsString { } } -/// Windows-specific extensions to `OsStr`. +/// Windows-specific extensions to [`OsStr`]. +/// +/// [`OsStr`]: ../../../../std/ffi/struct.OsStr.html #[stable(feature = "rust1", since = "1.0.0")] pub trait OsStrExt { /// Re-encodes an `OsStr` as a wide character sequence, i.e. potentially diff --git a/src/libstd/sys/windows/ext/fs.rs b/src/libstd/sys/windows/ext/fs.rs index e5cd51b6550..78c9e95a055 100644 --- a/src/libstd/sys/windows/ext/fs.rs +++ b/src/libstd/sys/windows/ext/fs.rs @@ -103,9 +103,9 @@ impl FileExt for fs::File { } } -/// Windows-specific extensions to [`OpenOptions`]. +/// Windows-specific extensions to [`fs::OpenOptions`]. /// -/// [`OpenOptions`]: ../../../fs/struct.OpenOptions.html +/// [`fs::OpenOptions`]: ../../../../std/fs/struct.OpenOptions.html #[stable(feature = "open_options_ext", since = "1.10.0")] pub trait OpenOptionsExt { /// Overrides the `dwDesiredAccess` argument to the call to [`CreateFile`] @@ -281,13 +281,12 @@ impl OpenOptionsExt for OpenOptions { } } -/// Extension methods for [`fs::Metadata`] to access the raw fields contained -/// within. +/// Windows-specific extensions to [`fs::Metadata`]. /// /// The data members that this trait exposes correspond to the members /// of the [`BY_HANDLE_FILE_INFORMATION`] structure. /// -/// [`fs::Metadata`]: ../../../fs/struct.Metadata.html +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html /// [`BY_HANDLE_FILE_INFORMATION`]: /// https://msdn.microsoft.com/en-us/library/windows/desktop/aa363788.aspx #[stable(feature = "metadata_ext", since = "1.1.0")] @@ -445,8 +444,11 @@ impl MetadataExt for Metadata { fn file_size(&self) -> u64 { self.as_inner().size() } } -/// Add support for the Windows specific fact that a symbolic link knows whether it is a file -/// or directory. +/// Windows-specific extensions to [`FileType`]. +/// +/// On Windows, a symbolic link knows whether it is a file or directory. +/// +/// [`FileType`]: ../../../../std/fs/struct.FileType.html #[unstable(feature = "windows_file_type_ext", issue = "0")] pub trait FileTypeExt { /// Returns whether this file type is a symbolic link that is also a directory. diff --git a/src/libstd/sys/windows/ext/process.rs b/src/libstd/sys/windows/ext/process.rs index 759f055c4b1..a02bcbe0c87 100644 --- a/src/libstd/sys/windows/ext/process.rs +++ b/src/libstd/sys/windows/ext/process.rs @@ -82,7 +82,9 @@ impl IntoRawHandle for process::ChildStderr { } } -/// Windows-specific extensions to `std::process::ExitStatus` +/// Windows-specific extensions to [`process::ExitStatus`]. +/// +/// [`process::ExitStatus`]: ../../../../std/process/struct.ExitStatus.html #[stable(feature = "exit_status_from", since = "1.12.0")] pub trait ExitStatusExt { /// Creates a new `ExitStatus` from the raw underlying `u32` return value of @@ -98,7 +100,9 @@ impl ExitStatusExt for process::ExitStatus { } } -/// Windows-specific extensions to the `std::process::Command` builder +/// Windows-specific extensions to the [`process::Command`] builder. +/// +/// [`process::Command`]: ../../../../std/process/struct.Command.html #[stable(feature = "windows_process_extensions", since = "1.16.0")] pub trait CommandExt { /// Sets the [process creation flags][1] to be passed to `CreateProcess`. diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs index dda4e1bab3b..fe7e058091e 100644 --- a/src/libstd/sys_common/wtf8.rs +++ b/src/libstd/sys_common/wtf8.rs @@ -876,21 +876,7 @@ impl Hash for Wtf8 { } impl Wtf8 { - pub fn is_ascii(&self) -> bool { - self.bytes.is_ascii() - } - pub fn to_ascii_uppercase(&self) -> Wtf8Buf { - Wtf8Buf { bytes: self.bytes.to_ascii_uppercase() } - } - pub fn to_ascii_lowercase(&self) -> Wtf8Buf { - Wtf8Buf { bytes: self.bytes.to_ascii_lowercase() } - } - pub fn eq_ignore_ascii_case(&self, other: &Wtf8) -> bool { - self.bytes.eq_ignore_ascii_case(&other.bytes) - } - pub fn make_ascii_uppercase(&mut self) { self.bytes.make_ascii_uppercase() } - pub fn make_ascii_lowercase(&mut self) { self.bytes.make_ascii_lowercase() } } #[cfg(test)] diff --git a/src/libsyntax/edition.rs b/src/libsyntax/edition.rs index e579fc74b42..3fc1c279f5a 100644 --- a/src/libsyntax/edition.rs +++ b/src/libsyntax/edition.rs @@ -24,20 +24,19 @@ pub enum Edition { // when adding new editions, be sure to update: // - // - the list in the `parse_edition` static in librustc::session::config + // - Update the `ALL_EDITIONS` const + // - Update the EDITION_NAME_LIST const // - add a `rust_####()` function to the session // - update the enum in Cargo's sources as well - // - // When -Zedition becomes --edition, there will - // also be a check for the edition being nightly-only - // somewhere. That will need to be updated - // whenever we're stabilizing/introducing a new edition - // as well as changing the default Cargo template. } // must be in order from oldest to newest pub const ALL_EDITIONS: &[Edition] = &[Edition::Edition2015, Edition::Edition2018]; +pub const EDITION_NAME_LIST: &'static str = "2015|2018"; + +pub const DEFAULT_EDITION: Edition = Edition::Edition2015; + impl fmt::Display for Edition { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let s = match *self { @@ -62,6 +61,13 @@ impl Edition { Edition::Edition2018 => "rust_2018_preview", } } + + pub fn is_stable(&self) -> bool { + match *self { + Edition::Edition2015 => true, + Edition::Edition2018 => false, + } + } } impl FromStr for Edition { diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 678c20402d6..1434e5fddea 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -514,6 +514,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { Some(kind.expect_from_annotatables(items)) } AttrProcMacro(ref mac) => { + self.gate_proc_macro_attr_item(attr.span, &item); let item_tok = TokenTree::Token(DUMMY_SP, Token::interpolated(match item { Annotatable::Item(item) => token::NtItem(item), Annotatable::TraitItem(item) => token::NtTraitItem(item.into_inner()), @@ -522,7 +523,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()), Annotatable::Expr(expr) => token::NtExpr(expr), })).into(); - let tok_result = mac.expand(self.cx, attr.span, attr.tokens, item_tok); + let input = self.extract_proc_macro_attr_input(attr.tokens, attr.span); + let tok_result = mac.expand(self.cx, attr.span, input, item_tok); self.parse_expansion(tok_result, kind, &attr.path, attr.span) } ProcMacroDerive(..) | BuiltinDerive(..) => { @@ -539,6 +541,49 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } } + fn extract_proc_macro_attr_input(&self, tokens: TokenStream, span: Span) -> TokenStream { + let mut trees = tokens.trees(); + match trees.next() { + Some(TokenTree::Delimited(_, delim)) => { + if trees.next().is_none() { + return delim.tts.into() + } + } + Some(TokenTree::Token(..)) => {} + None => return TokenStream::empty(), + } + self.cx.span_err(span, "custom attribute invocations must be \ + of the form #[foo] or #[foo(..)], the macro name must only be \ + followed by a delimiter token"); + TokenStream::empty() + } + + fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) { + let (kind, gate) = match *item { + Annotatable::Item(ref item) => { + match item.node { + ItemKind::Mod(_) if self.cx.ecfg.proc_macro_mod() => return, + ItemKind::Mod(_) => ("modules", "proc_macro_mod"), + _ => return, + } + } + Annotatable::TraitItem(_) => return, + Annotatable::ImplItem(_) => return, + Annotatable::ForeignItem(_) => return, + Annotatable::Stmt(_) | + Annotatable::Expr(_) if self.cx.ecfg.proc_macro_expr() => return, + Annotatable::Stmt(_) => ("statements", "proc_macro_expr"), + Annotatable::Expr(_) => ("expressions", "proc_macro_expr"), + }; + emit_feature_err( + self.cx.parse_sess, + gate, + span, + GateIssue::Language, + &format!("custom attributes cannot be applied to {}", kind), + ); + } + /// Expand a macro invocation. Returns the result of expansion. fn expand_bang_invoc(&mut self, invoc: Invocation, @@ -665,6 +710,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { self.cx.trace_macros_diag(); kind.dummy(span) } else { + self.gate_proc_macro_expansion_kind(span, kind); invoc.expansion_data.mark.set_expn_info(ExpnInfo { call_site: span, callee: NameAndSpan { @@ -695,6 +741,30 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } } + fn gate_proc_macro_expansion_kind(&self, span: Span, kind: ExpansionKind) { + let kind = match kind { + ExpansionKind::Expr => "expressions", + ExpansionKind::OptExpr => "expressions", + ExpansionKind::Pat => "patterns", + ExpansionKind::Ty => "types", + ExpansionKind::Stmts => "statements", + ExpansionKind::Items => return, + ExpansionKind::TraitItems => return, + ExpansionKind::ImplItems => return, + ExpansionKind::ForeignItems => return, + }; + if self.cx.ecfg.proc_macro_non_items() { + return + } + emit_feature_err( + self.cx.parse_sess, + "proc_macro_non_items", + span, + GateIssue::Language, + &format!("procedural macros cannot be expanded to {}", kind), + ); + } + /// Expand a derive invocation. Returns the result of expansion. fn expand_derive_invoc(&mut self, invoc: Invocation, @@ -1370,6 +1440,9 @@ impl<'feat> ExpansionConfig<'feat> { fn enable_custom_derive = custom_derive, fn proc_macro_enabled = proc_macro, fn macros_in_extern_enabled = macros_in_extern, + fn proc_macro_mod = proc_macro_mod, + fn proc_macro_expr = proc_macro_expr, + fn proc_macro_non_items = proc_macro_non_items, } } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 7b7cfe5eea0..39ddb13d347 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -272,6 +272,9 @@ declare_features! ( // Allows cfg(target_has_atomic = "..."). (active, cfg_target_has_atomic, "1.9.0", Some(32976), None), + // The `!` type. Does not imply exhaustive_patterns (below) any more. + (active, never_type, "1.13.0", Some(35121), None), + // Allows exhaustive pattern matching on types that contain uninhabited types. (active, exhaustive_patterns, "1.13.0", None, None), @@ -451,6 +454,18 @@ declare_features! ( (active, mmx_target_feature, "1.27.0", None, None), (active, sse4a_target_feature, "1.27.0", None, None), (active, tbm_target_feature, "1.27.0", None, None), + + // Allows macro invocations of the form `#[foo::bar]` + (active, proc_macro_path_invoc, "1.27.0", None, None), + + // Allows macro invocations on modules expressions and statements and + // procedural macros to expand to non-items. + (active, proc_macro_mod, "1.27.0", None, None), + (active, proc_macro_expr, "1.27.0", None, None), + (active, proc_macro_non_items, "1.27.0", None, None), + + // #[doc(alias = "...")] + (active, doc_alias, "1.27.0", Some(50146), None), ); declare_features! ( @@ -921,7 +936,7 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG "the `#[naked]` attribute \ is an experimental feature", cfg_fn!(naked_functions))), - ("target_feature", Normal, Ungated), + ("target_feature", Whitelisted, Ungated), ("export_name", Whitelisted, Ungated), ("inline", Whitelisted, Ungated), ("link", Whitelisted, Ungated), @@ -1227,10 +1242,9 @@ fn leveled_feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue GateIssue::Library(lib) => lib, }; - let explanation = if let Some(n) = issue { - format!("{} (see issue #{})", explain, n) - } else { - explain.to_owned() + let explanation = match issue { + None | Some(0) => explain.to_owned(), + Some(n) => format!("{} (see issue #{})", explain, n) }; let mut err = match level { @@ -1446,6 +1460,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, doc_spotlight, attr.span, "#[doc(spotlight)] is experimental" ); + } else if content.iter().any(|c| c.check_name("alias")) { + gate_feature_post!(&self, doc_alias, attr.span, + "#[doc(alias = \"...\")] is experimental" + ); } } } @@ -1635,6 +1653,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::TyKind::BareFn(ref bare_fn_ty) => { self.check_abi(bare_fn_ty.abi, ty.span); } + ast::TyKind::Never => { + gate_feature_post!(&self, never_type, ty.span, + "The `!` type is experimental"); + } ast::TyKind::TraitObject(_, ast::TraitObjectSyntax::Dyn) => { gate_feature_post!(&self, dyn_trait, ty.span, "`dyn Trait` syntax is unstable"); @@ -1745,8 +1767,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } ast::TraitItemKind::Type(_, ref default) => { - // We use two if statements instead of something like match guards so that both - // of these errors can be emitted if both cases apply. + // We use three if statements instead of something like match guards so that all + // of these errors can be emitted if all cases apply. if default.is_some() { gate_feature_post!(&self, associated_type_defaults, ti.span, "associated type defaults are unstable"); @@ -1755,6 +1777,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, generic_associated_types, ti.span, "generic associated types are unstable"); } + if !ti.generics.where_clause.predicates.is_empty() { + gate_feature_post!(&self, generic_associated_types, ti.span, + "where clauses on associated types are unstable"); + } } _ => {} } diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index ff63c9a5c6d..0397c3297db 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -271,8 +271,16 @@ pub fn char_lit(lit: &str, diag: Option<(Span, &Handler)>) -> (char, isize) { 'u' => { assert_eq!(lit.as_bytes()[2], b'{'); let idx = lit.find('}').unwrap(); - let s = &lit[3..idx].chars().filter(|&c| c != '_').collect::<String>(); - let v = u32::from_str_radix(&s, 16).unwrap(); + + // All digits and '_' are ascii, so treat each byte as a char. + let mut v: u32 = 0; + for c in lit[3..idx].bytes() { + let c = char::from(c); + if c != '_' { + let x = c.to_digit(16).unwrap(); + v = v.checked_mul(16).unwrap().checked_add(x).unwrap(); + } + } let c = char::from_u32(v).unwrap_or_else(|| { if let Some((span, diag)) = diag { let mut diag = diag.struct_span_err(span, "invalid unicode character escape"); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a7a9ce74512..9fa3952ca80 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -589,7 +589,8 @@ impl<'a> Parser<'a> { self.token_cursor.next() }; if next.sp == syntax_pos::DUMMY_SP { - next.sp = self.prev_span; + // Tweak the location for better diagnostics, but keep syntactic context intact. + next.sp = self.prev_span.with_ctxt(next.sp.ctxt()); } next } @@ -5758,18 +5759,33 @@ impl<'a> Parser<'a> { vis: Visibility, attrs: Vec<Attribute> ) -> PResult<'a, StructField> { + let mut seen_comma: bool = false; let a_var = self.parse_name_and_ty(lo, vis, attrs)?; + if self.token == token::Comma { + seen_comma = true; + } match self.token { token::Comma => { self.bump(); } token::CloseDelim(token::Brace) => {} token::DocComment(_) => { + let previous_span = self.prev_span; let mut err = self.span_fatal_err(self.span, Error::UselessDocComment); self.bump(); // consume the doc comment - if self.eat(&token::Comma) || self.token == token::CloseDelim(token::Brace) { + let comma_after_doc_seen = self.eat(&token::Comma); + // `seen_comma` is always false, because we are inside doc block + // condition is here to make code more readable + if seen_comma == false && comma_after_doc_seen == true { + seen_comma = true; + } + if comma_after_doc_seen || self.token == token::CloseDelim(token::Brace) { err.emit(); } else { + if seen_comma == false { + let sp = self.sess.codemap().next_point(previous_span); + err.span_suggestion(sp, "missing comma here", ",".into()); + } return Err(err); } } diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 2688a1adb56..44394384c7a 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -26,6 +26,7 @@ use tokenstream::{TokenStream, TokenTree}; use tokenstream; use std::{cmp, fmt}; +use std::mem; use rustc_data_structures::sync::{Lrc, Lock}; #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)] @@ -88,6 +89,12 @@ impl Lit { ByteStr(_) | ByteStrRaw(..) => "byte string" } } + + // See comments in `interpolated_to_tokenstream` for why we care about + // *probably* equal here rather than actual equality + fn probably_equal_for_proc_macro(&self, other: &Lit) -> bool { + mem::discriminant(self) == mem::discriminant(other) + } } pub(crate) fn ident_can_begin_expr(ident: ast::Ident, is_raw: bool) -> bool { @@ -530,14 +537,6 @@ impl Token { // stream they came from. Here we attempt to extract these // lossless token streams before we fall back to the // stringification. - // - // During early phases of the compiler, though, the AST could - // get modified directly (e.g. attributes added or removed) and - // the internal cache of tokens my not be invalidated or - // updated. Consequently if the "lossless" token stream - // disagrees with our actuall stringification (which has - // historically been much more battle-tested) then we go with - // the lossy stream anyway (losing span information). let mut tokens = None; match nt.0 { @@ -569,13 +568,96 @@ impl Token { let source = pprust::token_to_string(self); parse_stream_from_source_str(FileName::MacroExpansion, source, sess, Some(span)) }); + + // During early phases of the compiler the AST could get modified + // directly (e.g. attributes added or removed) and the internal cache + // of tokens my not be invalidated or updated. Consequently if the + // "lossless" token stream disagrees with our actual stringification + // (which has historically been much more battle-tested) then we go + // with the lossy stream anyway (losing span information). + // + // Note that the comparison isn't `==` here to avoid comparing spans, + // but it *also* is a "probable" equality which is a pretty weird + // definition. We mostly want to catch actual changes to the AST + // like a `#[cfg]` being processed or some weird `macro_rules!` + // expansion. + // + // What we *don't* want to catch is the fact that a user-defined + // literal like `0xf` is stringified as `15`, causing the cached token + // stream to not be literal `==` token-wise (ignoring spans) to the + // token stream we got from stringification. + // + // Instead the "probably equal" check here is "does each token + // recursively have the same discriminant?" We basically don't look at + // the token values here and assume that such fine grained modifications + // of token streams doesn't happen. if let Some(tokens) = tokens { - if tokens.eq_unspanned(&tokens_for_real) { + if tokens.probably_equal_for_proc_macro(&tokens_for_real) { return tokens } } return tokens_for_real } + + // See comments in `interpolated_to_tokenstream` for why we care about + // *probably* equal here rather than actual equality + pub fn probably_equal_for_proc_macro(&self, other: &Token) -> bool { + if mem::discriminant(self) != mem::discriminant(other) { + return false + } + match (self, other) { + (&Eq, &Eq) | + (&Lt, &Lt) | + (&Le, &Le) | + (&EqEq, &EqEq) | + (&Ne, &Ne) | + (&Ge, &Ge) | + (&Gt, &Gt) | + (&AndAnd, &AndAnd) | + (&OrOr, &OrOr) | + (&Not, &Not) | + (&Tilde, &Tilde) | + (&At, &At) | + (&Dot, &Dot) | + (&DotDot, &DotDot) | + (&DotDotDot, &DotDotDot) | + (&DotDotEq, &DotDotEq) | + (&DotEq, &DotEq) | + (&Comma, &Comma) | + (&Semi, &Semi) | + (&Colon, &Colon) | + (&ModSep, &ModSep) | + (&RArrow, &RArrow) | + (&LArrow, &LArrow) | + (&FatArrow, &FatArrow) | + (&Pound, &Pound) | + (&Dollar, &Dollar) | + (&Question, &Question) | + (&Whitespace, &Whitespace) | + (&Comment, &Comment) | + (&Eof, &Eof) => true, + + (&BinOp(a), &BinOp(b)) | + (&BinOpEq(a), &BinOpEq(b)) => a == b, + + (&OpenDelim(a), &OpenDelim(b)) | + (&CloseDelim(a), &CloseDelim(b)) => a == b, + + (&DocComment(a), &DocComment(b)) | + (&Shebang(a), &Shebang(b)) => a == b, + + (&Lifetime(a), &Lifetime(b)) => a.name == b.name, + (&Ident(a, b), &Ident(c, d)) => a.name == c.name && b == d, + + (&Literal(ref a, b), &Literal(ref c, d)) => { + b == d && a.probably_equal_for_proc_macro(c) + } + + (&Interpolated(_), &Interpolated(_)) => false, + + _ => panic!("forgot to add a token?"), + } + } } #[derive(Clone, RustcEncodable, RustcDecodable, Eq, Hash)] diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index fd2e760e9be..325927ed832 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -320,37 +320,48 @@ fn ignored_span(cx: &TestCtxt, sp: Span) -> Span { #[derive(PartialEq)] enum HasTestSignature { Yes, - No, + No(BadTestSignature), +} + +#[derive(PartialEq)] +enum BadTestSignature { NotEvenAFunction, + WrongTypeSignature, + NoArgumentsAllowed, + ShouldPanicOnlyWithNoArgs, } fn is_test_fn(cx: &TestCtxt, i: &ast::Item) -> bool { let has_test_attr = attr::contains_name(&i.attrs, "test"); fn has_test_signature(cx: &TestCtxt, i: &ast::Item) -> HasTestSignature { + let has_should_panic_attr = attr::contains_name(&i.attrs, "should_panic"); match i.node { ast::ItemKind::Fn(ref decl, _, _, _, ref generics, _) => { // If the termination trait is active, the compiler will check that the output // type implements the `Termination` trait as `libtest` enforces that. - let output_matches = if cx.features.termination_trait_test { - true - } else { - let no_output = match decl.output { - ast::FunctionRetTy::Default(..) => true, - ast::FunctionRetTy::Ty(ref t) if t.node == ast::TyKind::Tup(vec![]) => true, - _ => false - }; - - no_output && !generics.is_parameterized() + let has_output = match decl.output { + ast::FunctionRetTy::Default(..) => false, + ast::FunctionRetTy::Ty(ref t) if t.node == ast::TyKind::Tup(vec![]) => false, + _ => true }; - if decl.inputs.is_empty() && output_matches { - Yes - } else { - No + if !decl.inputs.is_empty() { + return No(BadTestSignature::NoArgumentsAllowed); + } + + match (has_output, cx.features.termination_trait_test, has_should_panic_attr) { + (true, true, true) => No(BadTestSignature::ShouldPanicOnlyWithNoArgs), + (true, true, false) => if generics.is_parameterized() { + No(BadTestSignature::WrongTypeSignature) + } else { + Yes + }, + (true, false, _) => No(BadTestSignature::WrongTypeSignature), + (false, _, _) => Yes } } - _ => NotEvenAFunction, + _ => No(BadTestSignature::NotEvenAFunction), } } @@ -358,18 +369,20 @@ fn is_test_fn(cx: &TestCtxt, i: &ast::Item) -> bool { let diag = cx.span_diagnostic; match has_test_signature(cx, i) { Yes => true, - No => { - if cx.features.termination_trait_test { - diag.span_err(i.span, "functions used as tests can not have any arguments"); - } else { - diag.span_err(i.span, "functions used as tests must have signature fn() -> ()"); + No(cause) => { + match cause { + BadTestSignature::NotEvenAFunction => + diag.span_err(i.span, "only functions may be used as tests"), + BadTestSignature::WrongTypeSignature => + diag.span_err(i.span, + "functions used as tests must have signature fn() -> ()"), + BadTestSignature::NoArgumentsAllowed => + diag.span_err(i.span, "functions used as tests can not have any arguments"), + BadTestSignature::ShouldPanicOnlyWithNoArgs => + diag.span_err(i.span, "functions using `#[should_panic]` must return `()`"), } false - }, - NotEvenAFunction => { - diag.span_err(i.span, "only functions may be used as tests"); - false - }, + } } } else { false @@ -407,7 +420,7 @@ fn is_bench_fn(cx: &TestCtxt, i: &ast::Item) -> bool { // well before resolve, can't get too deep. input_cnt == 1 && output_matches } - _ => false + _ => false } } diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index 6ac04b3cdf6..e2b5c4e1adf 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -124,6 +124,24 @@ impl TokenTree { } } + // See comments in `interpolated_to_tokenstream` for why we care about + // *probably* equal here rather than actual equality + // + // This is otherwise the same as `eq_unspanned`, only recursing with a + // different method. + pub fn probably_equal_for_proc_macro(&self, other: &TokenTree) -> bool { + match (self, other) { + (&TokenTree::Token(_, ref tk), &TokenTree::Token(_, ref tk2)) => { + tk.probably_equal_for_proc_macro(tk2) + } + (&TokenTree::Delimited(_, ref dl), &TokenTree::Delimited(_, ref dl2)) => { + dl.delim == dl2.delim && + dl.stream().probably_equal_for_proc_macro(&dl2.stream()) + } + (_, _) => false, + } + } + /// Retrieve the TokenTree's span. pub fn span(&self) -> Span { match *self { @@ -250,6 +268,22 @@ impl TokenStream { t1.next().is_none() && t2.next().is_none() } + // See comments in `interpolated_to_tokenstream` for why we care about + // *probably* equal here rather than actual equality + // + // This is otherwise the same as `eq_unspanned`, only recursing with a + // different method. + pub fn probably_equal_for_proc_macro(&self, other: &TokenStream) -> bool { + let mut t1 = self.trees(); + let mut t2 = other.trees(); + for (t1, t2) in t1.by_ref().zip(t2.by_ref()) { + if !t1.probably_equal_for_proc_macro(&t2) { + return false; + } + } + t1.next().is_none() && t2.next().is_none() + } + /// Precondition: `self` consists of a single token tree. /// Returns true if the token tree is a joint operation w.r.t. `proc_macro::TokenNode`. pub fn as_tree(self) -> (TokenTree, bool /* joint? */) { diff --git a/src/libsyntax_ext/deriving/cmp/ord.rs b/src/libsyntax_ext/deriving/cmp/ord.rs index 1a392ac3765..99b6f752e94 100644 --- a/src/libsyntax_ext/deriving/cmp/ord.rs +++ b/src/libsyntax_ext/deriving/cmp/ord.rs @@ -38,7 +38,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt, name: "cmp", generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), - args: vec![borrowed_self()], + args: vec![(borrowed_self(), "other")], ret_ty: Literal(path_std!(cx, cmp::Ordering)), attributes: attrs, is_unsafe: false, @@ -64,7 +64,7 @@ pub fn ordering_collapsed(cx: &mut ExtCtxt, } pub fn cs_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> { - let test_id = cx.ident_of("__cmp"); + let test_id = cx.ident_of("cmp").gensym(); let equals_path = cx.path_global(span, cx.std_path(&["cmp", "Ordering", "Equal"])); let cmp_path = cx.std_path(&["cmp", "Ord", "cmp"]); @@ -77,9 +77,9 @@ pub fn cs_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> { // ::std::cmp::Ordering::Equal => { // ... // } - // __cmp => __cmp + // cmp => cmp // }, - // __cmp => __cmp + // cmp => cmp // } // cs_fold(// foldr nests the if-elses correctly, leaving the first field @@ -88,7 +88,7 @@ pub fn cs_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> { |cx, span, old, self_f, other_fs| { // match new { // ::std::cmp::Ordering::Equal => old, - // __cmp => __cmp + // cmp => cmp // } let new = { diff --git a/src/libsyntax_ext/deriving/cmp/partial_eq.rs b/src/libsyntax_ext/deriving/cmp/partial_eq.rs index 81ca7e73228..c259733d81a 100644 --- a/src/libsyntax_ext/deriving/cmp/partial_eq.rs +++ b/src/libsyntax_ext/deriving/cmp/partial_eq.rs @@ -78,7 +78,7 @@ pub fn expand_deriving_partial_eq(cx: &mut ExtCtxt, name: $name, generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), - args: vec![borrowed_self()], + args: vec![(borrowed_self(), "other")], ret_ty: Literal(path_local!(bool)), attributes: attrs, is_unsafe: false, diff --git a/src/libsyntax_ext/deriving/cmp/partial_ord.rs b/src/libsyntax_ext/deriving/cmp/partial_ord.rs index 9560fd0570a..d71527fd0ed 100644 --- a/src/libsyntax_ext/deriving/cmp/partial_ord.rs +++ b/src/libsyntax_ext/deriving/cmp/partial_ord.rs @@ -34,7 +34,7 @@ pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt, name: $name, generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), - args: vec![borrowed_self()], + args: vec![(borrowed_self(), "other")], ret_ty: Literal(path_local!(bool)), attributes: attrs, is_unsafe: false, @@ -59,7 +59,7 @@ pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt, name: "partial_cmp", generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), - args: vec![borrowed_self()], + args: vec![(borrowed_self(), "other")], ret_ty, attributes: attrs, is_unsafe: false, @@ -123,7 +123,7 @@ pub fn some_ordering_collapsed(cx: &mut ExtCtxt, } pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> { - let test_id = cx.ident_of("__cmp"); + let test_id = cx.ident_of("cmp").gensym(); let ordering = cx.path_global(span, cx.std_path(&["cmp", "Ordering", "Equal"])); let ordering_expr = cx.expr_path(ordering.clone()); let equals_expr = cx.expr_some(span, ordering_expr); @@ -138,9 +138,9 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P< // ::std::option::Option::Some(::std::cmp::Ordering::Equal) => { // ... // } - // __cmp => __cmp + // cmp => cmp // }, - // __cmp => __cmp + // cmp => cmp // } // cs_fold(// foldr nests the if-elses correctly, leaving the first field @@ -149,7 +149,7 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P< |cx, span, old, self_f, other_fs| { // match new { // Some(::std::cmp::Ordering::Equal) => old, - // __cmp => __cmp + // cmp => cmp // } let new = { diff --git a/src/libsyntax_ext/deriving/debug.rs b/src/libsyntax_ext/deriving/debug.rs index c007285cd85..b546f5df157 100644 --- a/src/libsyntax_ext/deriving/debug.rs +++ b/src/libsyntax_ext/deriving/debug.rs @@ -40,7 +40,7 @@ pub fn expand_deriving_debug(cx: &mut ExtCtxt, name: "fmt", generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), - args: vec![fmtr], + args: vec![(fmtr, "f")], ret_ty: Literal(path_std!(cx, fmt::Result)), attributes: Vec::new(), is_unsafe: false, @@ -70,7 +70,7 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<E // We want to make sure we have the ctxt set so that we can use unstable methods let span = span.with_ctxt(cx.backtrace()); let name = cx.expr_lit(span, ast::LitKind::Str(ident.name, ast::StrStyle::Cooked)); - let builder = Ident::from_str("__debug_trait_builder"); + let builder = Ident::from_str("debug_trait_builder").gensym(); let builder_expr = cx.expr_ident(span, builder.clone()); let fmt = substr.nonself_args[0].clone(); diff --git a/src/libsyntax_ext/deriving/decodable.rs b/src/libsyntax_ext/deriving/decodable.rs index 46dada256b8..7618fe63ab3 100644 --- a/src/libsyntax_ext/deriving/decodable.rs +++ b/src/libsyntax_ext/deriving/decodable.rs @@ -67,8 +67,8 @@ fn expand_deriving_decodable_imp(cx: &mut ExtCtxt, PathKind::Global)])], }, explicit_self: None, - args: vec![Ptr(Box::new(Literal(Path::new_local(typaram))), - Borrowed(None, Mutability::Mutable))], + args: vec![(Ptr(Box::new(Literal(Path::new_local(typaram))), + Borrowed(None, Mutability::Mutable)), "d")], ret_ty: Literal(Path::new_(pathvec_std!(cx, result::Result), None, diff --git a/src/libsyntax_ext/deriving/encodable.rs b/src/libsyntax_ext/deriving/encodable.rs index d579b3abd45..2c6c18cc51c 100644 --- a/src/libsyntax_ext/deriving/encodable.rs +++ b/src/libsyntax_ext/deriving/encodable.rs @@ -148,8 +148,8 @@ fn expand_deriving_encodable_imp(cx: &mut ExtCtxt, ], }, explicit_self: borrowed_explicit_self(), - args: vec![Ptr(Box::new(Literal(Path::new_local(typaram))), - Borrowed(None, Mutability::Mutable))], + args: vec![(Ptr(Box::new(Literal(Path::new_local(typaram))), + Borrowed(None, Mutability::Mutable)), "s")], ret_ty: Literal(Path::new_( pathvec_std!(cx, result::Result), None, diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 1f80385cfbd..1ef0d2b0b49 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -252,7 +252,7 @@ pub struct MethodDef<'a> { pub explicit_self: Option<Option<PtrTy<'a>>>, /// Arguments other than the self argument - pub args: Vec<Ty<'a>>, + pub args: Vec<(Ty<'a>, &'a str)>, /// Return type pub ret_ty: Ty<'a>, @@ -915,9 +915,9 @@ impl<'a> MethodDef<'a> { explicit_self }); - for (i, ty) in self.args.iter().enumerate() { + for (ty, name) in self.args.iter() { let ast_ty = ty.to_ty(cx, trait_.span, type_ident, generics); - let ident = cx.ident_of(&format!("__arg_{}", i)); + let ident = cx.ident_of(name).gensym(); arg_tys.push((ident, ast_ty)); let arg_expr = cx.expr_ident(trait_.span, ident); @@ -1004,10 +1004,10 @@ impl<'a> MethodDef<'a> { /// /// // equivalent to: /// impl PartialEq for A { - /// fn eq(&self, __arg_1: &A) -> bool { + /// fn eq(&self, other: &A) -> bool { /// match *self { /// A {x: ref __self_0_0, y: ref __self_0_1} => { - /// match *__arg_1 { + /// match *other { /// A {x: ref __self_1_0, y: ref __self_1_1} => { /// __self_0_0.eq(__self_1_0) && __self_0_1.eq(__self_1_1) /// } @@ -1020,10 +1020,10 @@ impl<'a> MethodDef<'a> { /// // or if A is repr(packed) - note fields are matched by-value /// // instead of by-reference. /// impl PartialEq for A { - /// fn eq(&self, __arg_1: &A) -> bool { + /// fn eq(&self, other: &A) -> bool { /// match *self { /// A {x: __self_0_0, y: __self_0_1} => { - /// match __arg_1 { + /// match other { /// A {x: __self_1_0, y: __self_1_1} => { /// __self_0_0.eq(&__self_1_0) && __self_0_1.eq(&__self_1_1) /// } @@ -1134,14 +1134,14 @@ impl<'a> MethodDef<'a> { /// // is equivalent to /// /// impl PartialEq for A { - /// fn eq(&self, __arg_1: &A) -> ::bool { - /// match (&*self, &*__arg_1) { + /// fn eq(&self, other: &A) -> ::bool { + /// match (&*self, &*other) { /// (&A1, &A1) => true, /// (&A2(ref self_0), /// &A2(ref __arg_1_0)) => (*self_0).eq(&(*__arg_1_0)), /// _ => { /// let __self_vi = match *self { A1(..) => 0, A2(..) => 1 }; - /// let __arg_1_vi = match *__arg_1 { A1(..) => 0, A2(..) => 1 }; + /// let __arg_1_vi = match *other { A1(..) => 0, A2(..) => 1 }; /// false /// } /// } @@ -1240,7 +1240,7 @@ impl<'a> MethodDef<'a> { let vi_idents: Vec<ast::Ident> = self_arg_names.iter() .map(|name| { let vi_suffix = format!("{}_vi", &name[..]); - cx.ident_of(&vi_suffix[..]) + cx.ident_of(&vi_suffix[..]).gensym() }) .collect::<Vec<ast::Ident>>(); @@ -1616,7 +1616,7 @@ impl<'a> TraitDef<'a> { let mut ident_exprs = Vec::new(); for (i, struct_field) in struct_def.fields().iter().enumerate() { let sp = struct_field.span.with_ctxt(self.span.ctxt()); - let ident = cx.ident_of(&format!("{}_{}", prefix, i)); + let ident = cx.ident_of(&format!("{}_{}", prefix, i)).gensym(); paths.push(ident.with_span_pos(sp)); let val = cx.expr_path(cx.path_ident(sp, ident)); let val = if use_temporaries { diff --git a/src/libsyntax_ext/deriving/hash.rs b/src/libsyntax_ext/deriving/hash.rs index b192ab2527e..67096cdb49a 100644 --- a/src/libsyntax_ext/deriving/hash.rs +++ b/src/libsyntax_ext/deriving/hash.rs @@ -44,8 +44,8 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt, bounds: vec![(typaram, vec![path_std!(cx, hash::Hasher)])], }, explicit_self: borrowed_explicit_self(), - args: vec![Ptr(Box::new(Literal(arg)), - Borrowed(None, Mutability::Mutable))], + args: vec![(Ptr(Box::new(Literal(arg)), + Borrowed(None, Mutability::Mutable)), "state")], ret_ty: nil_ty(), attributes: vec![], is_unsafe: false, diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index c78decb1eb9..6b155b6596d 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -543,6 +543,10 @@ impl<'a, 'b> Context<'a, 'b> { let mut pats = Vec::new(); let mut heads = Vec::new(); + let names_pos: Vec<_> = (0..self.args.len()).map(|i| { + self.ecx.ident_of(&format!("arg{}", i)).gensym() + }).collect(); + // First, build up the static array which will become our precompiled // format "string" let pieces = self.ecx.expr_vec_slice(self.fmtsp, self.str_pieces); @@ -560,7 +564,7 @@ impl<'a, 'b> Context<'a, 'b> { // of each variable because we don't want to move out of the arguments // passed to this function. for (i, e) in self.args.into_iter().enumerate() { - let name = self.ecx.ident_of(&format!("__arg{}", i)); + let name = names_pos[i]; let span = DUMMY_SP.with_ctxt(e.span.ctxt().apply_mark(self.ecx.current_expansion.mark)); pats.push(self.ecx.pat_ident(span, name)); @@ -570,14 +574,12 @@ impl<'a, 'b> Context<'a, 'b> { heads.push(self.ecx.expr_addr_of(e.span, e)); } for pos in self.count_args { - let name = self.ecx.ident_of(&match pos { - Exact(i) => format!("__arg{}", i), - _ => panic!("should never happen"), - }); - let span = match pos { - Exact(i) => spans_pos[i], + let index = match pos { + Exact(i) => i, _ => panic!("should never happen"), }; + let name = names_pos[index]; + let span = spans_pos[index]; counts.push(Context::format_arg(self.ecx, self.macsp, span, &Count, name)); } diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 50fac600a97..556ee162c6e 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -15,8 +15,8 @@ use hygiene::SyntaxContext; use {Span, DUMMY_SP, GLOBALS}; +use rustc_data_structures::fx::FxHashMap; use serialize::{Decodable, Decoder, Encodable, Encoder}; -use std::collections::HashMap; use std::fmt; use std::hash::{Hash, Hasher}; @@ -53,6 +53,10 @@ impl Ident { pub fn modern(self) -> Ident { Ident::new(self.name, self.span.modern()) } + + pub fn gensym(self) -> Ident { + Ident::new(self.name.gensymed(), self.span) + } } impl PartialEq for Ident { @@ -184,7 +188,7 @@ impl<T: ::std::ops::Deref<Target=str>> PartialEq<T> for Symbol { #[derive(Default)] pub struct Interner { - names: HashMap<Box<str>, Symbol>, + names: FxHashMap<Box<str>, Symbol>, strings: Vec<Box<str>>, gensyms: Vec<Symbol>, } diff --git a/src/stdsimd b/src/stdsimd -Subproject effdcd0132d17b6c4badc67b4b6d3fdf749a2d2 +Subproject 1ea18a5cb431e24aa838b652ac305acc5e394d6 diff --git a/src/test/codegen/nounwind.rs b/src/test/codegen/nounwind.rs index 9fea907d3c8..6863b1f2792 100644 --- a/src/test/codegen/nounwind.rs +++ b/src/test/codegen/nounwind.rs @@ -11,6 +11,7 @@ // aux-build:nounwind.rs // compile-flags: -C no-prepopulate-passes -C panic=abort -C metadata=a // ignore-windows +// ignore-android #![crate_type = "lib"] diff --git a/src/test/compile-fail-fulldeps/proc-macro/attr-invalid-exprs.rs b/src/test/compile-fail-fulldeps/proc-macro/attr-invalid-exprs.rs index 2f65bd16bb5..749d87e37b5 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/attr-invalid-exprs.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/attr-invalid-exprs.rs @@ -13,7 +13,7 @@ //! Attributes producing expressions in invalid locations -#![feature(proc_macro, stmt_expr_attributes)] +#![feature(proc_macro, stmt_expr_attributes, proc_macro_expr)] extern crate attr_stmt_expr; use attr_stmt_expr::{duplicate, no_output}; diff --git a/src/test/compile-fail-fulldeps/proc-macro/attr-stmt-expr.rs b/src/test/compile-fail-fulldeps/proc-macro/attr-stmt-expr.rs index d29bc00c663..ce04fdfb976 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/attr-stmt-expr.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/attr-stmt-expr.rs @@ -11,7 +11,7 @@ // aux-build:attr-stmt-expr.rs // ignore-stage1 -#![feature(proc_macro)] +#![feature(proc_macro, proc_macro_expr)] extern crate attr_stmt_expr; use attr_stmt_expr::{expect_let, expect_print_stmt, expect_expr, expect_print_expr}; diff --git a/src/test/compile-fail-fulldeps/proc-macro/attribute-with-error.rs b/src/test/compile-fail-fulldeps/proc-macro/attribute-with-error.rs index 00a27818327..edfedebf870 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/attribute-with-error.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/attribute-with-error.rs @@ -21,6 +21,8 @@ use attribute_with_error::foo; fn test1() { let a: i32 = "foo"; //~^ ERROR: mismatched types + let b: i32 = "f'oo"; + //~^ ERROR: mismatched types } fn test2() { diff --git a/src/test/compile-fail-fulldeps/proc-macro/attributes-included.rs b/src/test/compile-fail-fulldeps/proc-macro/attributes-included.rs index 2adbee1d3fb..9947e8f66ce 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/attributes-included.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/attributes-included.rs @@ -11,7 +11,7 @@ // aux-build:attributes-included.rs // ignore-stage1 -#![feature(proc_macro, rustc_attrs)] +#![feature(proc_macro, rustc_attrs, proc_macro_path_invoc)] #![warn(unused)] extern crate attributes_included; diff --git a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/proc-macro-gates.rs b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/proc-macro-gates.rs new file mode 100644 index 00000000000..25579f1fc83 --- /dev/null +++ b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/proc-macro-gates.rs @@ -0,0 +1,29 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// no-prefer-dynamic +// force-host + +#![crate_type = "proc-macro"] +#![feature(proc_macro)] + +extern crate proc_macro; + +use proc_macro::*; + +#[proc_macro] +pub fn m(a: TokenStream) -> TokenStream { + a +} + +#[proc_macro_attribute] +pub fn a(_a: TokenStream, b: TokenStream) -> TokenStream { + b +} diff --git a/src/test/compile-fail-fulldeps/proc-macro/lints_in_proc_macros.rs b/src/test/compile-fail-fulldeps/proc-macro/lints_in_proc_macros.rs index 773b16b945f..c7be3167947 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/lints_in_proc_macros.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/lints_in_proc_macros.rs @@ -11,7 +11,7 @@ // aux-build:bang_proc_macro2.rs // ignore-stage1 -#![feature(proc_macro)] +#![feature(proc_macro, proc_macro_non_items)] #![allow(unused_macros)] extern crate bang_proc_macro2; diff --git a/src/test/compile-fail-fulldeps/proc-macro/macro-use-bang.rs b/src/test/compile-fail-fulldeps/proc-macro/macro-use-bang.rs index 7ecc685357e..f16ca79ca93 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/macro-use-bang.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/macro-use-bang.rs @@ -10,7 +10,7 @@ // aux-build:bang_proc_macro.rs -#![feature(proc_macro)] +#![feature(proc_macro, proc_macro_non_items)] #[macro_use] extern crate bang_proc_macro; diff --git a/src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates.rs b/src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates.rs new file mode 100644 index 00000000000..0dc1c2ab2da --- /dev/null +++ b/src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates.rs @@ -0,0 +1,54 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:proc-macro-gates.rs +// gate-test-proc_macro_non_items +// gate-test-proc_macro_path_invoc +// gate-test-proc_macro_mod line +// gate-test-proc_macro_expr +// gate-test-proc_macro_mod + +#![feature(proc_macro, stmt_expr_attributes)] + +extern crate proc_macro_gates as foo; + +use foo::*; + +#[foo::a] //~ ERROR: paths of length greater than one +fn _test() {} + +#[a] //~ ERROR: custom attributes cannot be applied to modules +mod _test2 {} + +#[a = y] //~ ERROR: must only be followed by a delimiter token +fn _test3() {} + +#[a = ] //~ ERROR: must only be followed by a delimiter token +fn _test4() {} + +#[a () = ] //~ ERROR: must only be followed by a delimiter token +fn _test5() {} + +fn main() { + #[a] //~ ERROR: custom attributes cannot be applied to statements + let _x = 2; + let _x = #[a] 2; + //~^ ERROR: custom attributes cannot be applied to expressions + + let _x: m!(u32) = 3; + //~^ ERROR: procedural macros cannot be expanded to types + if let m!(Some(_x)) = Some(3) { + //~^ ERROR: procedural macros cannot be expanded to patterns + } + let _x = m!(3); + //~^ ERROR: procedural macros cannot be expanded to expressions + m!(let _x = 3;); + //~^ ERROR: procedural macros cannot be expanded to statements +} diff --git a/src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates2.rs b/src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates2.rs new file mode 100644 index 00000000000..a1a15afecd5 --- /dev/null +++ b/src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates2.rs @@ -0,0 +1,35 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:proc-macro-gates.rs + +#![feature(proc_macro, stmt_expr_attributes)] + +extern crate proc_macro_gates as foo; + +use foo::*; + +// NB. these errors aren't the best errors right now, but they're definitely +// intended to be errors. Somehow using a custom attribute in these positions +// should either require a feature gate or not be allowed on stable. + +fn _test6<#[a] T>() {} +//~^ ERROR: unknown to the compiler + +fn _test7() { + match 1 { + #[a] //~ ERROR: unknown to the compiler + 0 => {} + _ => {} + } +} + +fn main() { +} diff --git a/src/test/compile-fail/allocator/not-an-allocator.rs b/src/test/compile-fail/allocator/not-an-allocator.rs index 1479d0b6264..140cad22f34 100644 --- a/src/test/compile-fail/allocator/not-an-allocator.rs +++ b/src/test/compile-fail/allocator/not-an-allocator.rs @@ -16,6 +16,5 @@ static A: usize = 0; //~| the trait bound `usize: //~| the trait bound `usize: //~| the trait bound `usize: -//~| the trait bound `usize: fn main() {} diff --git a/src/test/compile-fail/array_const_index-0.rs b/src/test/compile-fail/array_const_index-0.rs index 501c66e75cd..9b9deb4ca8d 100644 --- a/src/test/compile-fail/array_const_index-0.rs +++ b/src/test/compile-fail/array_const_index-0.rs @@ -12,6 +12,7 @@ const A: &'static [i32] = &[]; const B: i32 = (&A)[1]; //~^ ERROR constant evaluation error //~| index out of bounds: the len is 0 but the index is 1 +//~| WARN this constant cannot be used fn main() { let _ = B; diff --git a/src/test/compile-fail/array_const_index-1.rs b/src/test/compile-fail/array_const_index-1.rs index d3b43e83bfe..46feb20cf11 100644 --- a/src/test/compile-fail/array_const_index-1.rs +++ b/src/test/compile-fail/array_const_index-1.rs @@ -12,6 +12,7 @@ const A: [i32; 0] = []; const B: i32 = A[1]; //~^ ERROR constant evaluation error //~| index out of bounds: the len is 0 but the index is 1 +//~| WARN this constant cannot be used fn main() { let _ = B; diff --git a/src/test/compile-fail/call-fn-never-arg-wrong-type.rs b/src/test/compile-fail/call-fn-never-arg-wrong-type.rs index c2f157cd35c..583befed1e8 100644 --- a/src/test/compile-fail/call-fn-never-arg-wrong-type.rs +++ b/src/test/compile-fail/call-fn-never-arg-wrong-type.rs @@ -10,6 +10,8 @@ // Test that we can't pass other types for ! +#![feature(never_type)] + fn foo(x: !) -> ! { x } diff --git a/src/test/compile-fail/coerce-to-bang-cast.rs b/src/test/compile-fail/coerce-to-bang-cast.rs index 5efb4dadc64..14a06b306d8 100644 --- a/src/test/compile-fail/coerce-to-bang-cast.rs +++ b/src/test/compile-fail/coerce-to-bang-cast.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(never_type)] + fn foo(x: usize, y: !, z: usize) { } fn cast_a() { diff --git a/src/test/compile-fail/coerce-to-bang.rs b/src/test/compile-fail/coerce-to-bang.rs index 15049232a4d..62ff09f4616 100644 --- a/src/test/compile-fail/coerce-to-bang.rs +++ b/src/test/compile-fail/coerce-to-bang.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(never_type)] + fn foo(x: usize, y: !, z: usize) { } fn call_foo_a() { diff --git a/src/test/compile-fail/const-err-early.rs b/src/test/compile-fail/const-err-early.rs index 3de0f1ff61e..6caec159d01 100644 --- a/src/test/compile-fail/const-err-early.rs +++ b/src/test/compile-fail/const-err-early.rs @@ -10,17 +10,17 @@ #![deny(const_err)] -pub const A: i8 = -std::i8::MIN; //~ ERROR E0080 -//~^ ERROR attempt to negate with overflow +pub const A: i8 = -std::i8::MIN; //~ ERROR const_err +//~^ ERROR this constant cannot be used //~| ERROR constant evaluation error -pub const B: u8 = 200u8 + 200u8; //~ ERROR E0080 -//~^ ERROR attempt to add with overflow -pub const C: u8 = 200u8 * 4; //~ ERROR E0080 -//~^ ERROR attempt to multiply with overflow -pub const D: u8 = 42u8 - (42u8 + 1); //~ ERROR E0080 -//~^ ERROR attempt to subtract with overflow +pub const B: u8 = 200u8 + 200u8; //~ ERROR const_err +//~^ ERROR this constant cannot be used +pub const C: u8 = 200u8 * 4; //~ ERROR const_err +//~^ ERROR this constant cannot be used +pub const D: u8 = 42u8 - (42u8 + 1); //~ ERROR const_err +//~^ ERROR this constant cannot be used pub const E: u8 = [5u8][1]; -//~^ ERROR E0080 +//~^ ERROR const_err fn main() { let _a = A; diff --git a/src/test/compile-fail/const-err-multi.rs b/src/test/compile-fail/const-err-multi.rs index d2355f57f17..6f0281b8bd0 100644 --- a/src/test/compile-fail/const-err-multi.rs +++ b/src/test/compile-fail/const-err-multi.rs @@ -14,12 +14,13 @@ pub const A: i8 = -std::i8::MIN; //~^ ERROR E0080 //~| ERROR attempt to negate with overflow //~| ERROR constant evaluation error +//~| ERROR this constant cannot be used pub const B: i8 = A; -//~^ ERROR E0080 +//~^ ERROR const_err pub const C: u8 = A as u8; -//~^ ERROR E0080 +//~^ ERROR const_err pub const D: i8 = 50 - A; -//~^ ERROR E0080 +//~^ ERROR const_err fn main() { let _ = (A, B, C, D); diff --git a/src/test/compile-fail/const-eval-overflow2.rs b/src/test/compile-fail/const-eval-overflow2.rs index a0d8f9672c0..faa8c3039b7 100644 --- a/src/test/compile-fail/const-eval-overflow2.rs +++ b/src/test/compile-fail/const-eval-overflow2.rs @@ -22,57 +22,57 @@ use std::{i8, i16, i32, i64, isize}; use std::{u8, u16, u32, u64, usize}; const VALS_I8: (i8,) = + //~^ ERROR this constant cannot be used ( i8::MIN - 1, - //~^ ERROR constant evaluation error - //~| ERROR attempt to subtract with overflow + //~^ ERROR attempt to subtract with overflow ); const VALS_I16: (i16,) = + //~^ ERROR this constant cannot be used ( i16::MIN - 1, - //~^ ERROR constant evaluation error - //~| ERROR attempt to subtract with overflow + //~^ ERROR attempt to subtract with overflow ); const VALS_I32: (i32,) = + //~^ ERROR this constant cannot be used ( i32::MIN - 1, - //~^ ERROR constant evaluation error - //~| ERROR attempt to subtract with overflow + //~^ ERROR attempt to subtract with overflow ); const VALS_I64: (i64,) = + //~^ ERROR this constant cannot be used ( i64::MIN - 1, - //~^ ERROR constant evaluation error - //~| ERROR attempt to subtract with overflow + //~^ ERROR attempt to subtract with overflow ); const VALS_U8: (u8,) = + //~^ ERROR this constant cannot be used ( u8::MIN - 1, - //~^ ERROR constant evaluation error - //~| ERROR attempt to subtract with overflow + //~^ ERROR attempt to subtract with overflow ); const VALS_U16: (u16,) = ( + //~^ ERROR this constant cannot be used u16::MIN - 1, - //~^ ERROR constant evaluation error - //~| ERROR attempt to subtract with overflow + //~^ ERROR attempt to subtract with overflow ); const VALS_U32: (u32,) = ( + //~^ ERROR this constant cannot be used u32::MIN - 1, - //~^ ERROR constant evaluation error - //~| ERROR attempt to subtract with overflow + //~^ ERROR attempt to subtract with overflow ); const VALS_U64: (u64,) = + //~^ ERROR this constant cannot be used ( u64::MIN - 1, - //~^ ERROR constant evaluation error - //~| ERROR attempt to subtract with overflow + //~^ ERROR attempt to subtract with overflow ); fn main() { diff --git a/src/test/compile-fail/const-eval-overflow2b.rs b/src/test/compile-fail/const-eval-overflow2b.rs index 08128f90e53..d827e680c5b 100644 --- a/src/test/compile-fail/const-eval-overflow2b.rs +++ b/src/test/compile-fail/const-eval-overflow2b.rs @@ -22,57 +22,57 @@ use std::{i8, i16, i32, i64, isize}; use std::{u8, u16, u32, u64, usize}; const VALS_I8: (i8,) = + //~^ ERROR this constant cannot be used ( i8::MAX + 1, - //~^ ERROR constant evaluation error - //~| ERROR attempt to add with overflow + //~^ ERROR attempt to add with overflow ); const VALS_I16: (i16,) = + //~^ ERROR this constant cannot be used ( i16::MAX + 1, - //~^ ERROR constant evaluation error - //~| ERROR attempt to add with overflow + //~^ ERROR attempt to add with overflow ); const VALS_I32: (i32,) = + //~^ ERROR this constant cannot be used ( i32::MAX + 1, - //~^ ERROR constant evaluation error - //~| ERROR attempt to add with overflow + //~^ ERROR attempt to add with overflow ); const VALS_I64: (i64,) = + //~^ ERROR this constant cannot be used ( i64::MAX + 1, - //~^ ERROR constant evaluation error - //~| ERROR attempt to add with overflow + //~^ ERROR attempt to add with overflow ); const VALS_U8: (u8,) = + //~^ ERROR this constant cannot be used ( u8::MAX + 1, - //~^ ERROR constant evaluation error - //~| ERROR attempt to add with overflow + //~^ ERROR attempt to add with overflow ); const VALS_U16: (u16,) = ( + //~^ ERROR this constant cannot be used u16::MAX + 1, - //~^ ERROR constant evaluation error - //~| ERROR attempt to add with overflow + //~^ ERROR attempt to add with overflow ); const VALS_U32: (u32,) = ( + //~^ ERROR this constant cannot be used u32::MAX + 1, - //~^ ERROR constant evaluation error - //~| ERROR attempt to add with overflow + //~^ ERROR attempt to add with overflow ); const VALS_U64: (u64,) = + //~^ ERROR this constant cannot be used ( u64::MAX + 1, - //~^ ERROR constant evaluation error - //~| ERROR attempt to add with overflow + //~^ ERROR attempt to add with overflow ); fn main() { diff --git a/src/test/compile-fail/const-eval-overflow2c.rs b/src/test/compile-fail/const-eval-overflow2c.rs index 31a1638cade..2fd46b038ef 100644 --- a/src/test/compile-fail/const-eval-overflow2c.rs +++ b/src/test/compile-fail/const-eval-overflow2c.rs @@ -22,57 +22,57 @@ use std::{i8, i16, i32, i64, isize}; use std::{u8, u16, u32, u64, usize}; const VALS_I8: (i8,) = + //~^ ERROR this constant cannot be used ( i8::MIN * 2, - //~^ ERROR constant evaluation error - //~| ERROR attempt to multiply with overflow + //~^ ERROR attempt to multiply with overflow ); const VALS_I16: (i16,) = + //~^ ERROR this constant cannot be used ( i16::MIN * 2, - //~^ ERROR constant evaluation error - //~| ERROR attempt to multiply with overflow + //~^ ERROR attempt to multiply with overflow ); const VALS_I32: (i32,) = + //~^ ERROR this constant cannot be used ( i32::MIN * 2, - //~^ ERROR constant evaluation error - //~| ERROR attempt to multiply with overflow + //~^ ERROR attempt to multiply with overflow ); const VALS_I64: (i64,) = + //~^ ERROR this constant cannot be used ( i64::MIN * 2, - //~^ ERROR constant evaluation error - //~| ERROR attempt to multiply with overflow + //~^ ERROR attempt to multiply with overflow ); const VALS_U8: (u8,) = + //~^ ERROR this constant cannot be used ( u8::MAX * 2, - //~^ ERROR constant evaluation error - //~| ERROR attempt to multiply with overflow + //~^ ERROR attempt to multiply with overflow ); const VALS_U16: (u16,) = ( + //~^ ERROR this constant cannot be used u16::MAX * 2, - //~^ ERROR constant evaluation error - //~| ERROR attempt to multiply with overflow + //~^ ERROR attempt to multiply with overflow ); const VALS_U32: (u32,) = ( + //~^ ERROR this constant cannot be used u32::MAX * 2, - //~^ ERROR constant evaluation error - //~| ERROR attempt to multiply with overflow + //~^ ERROR attempt to multiply with overflow ); const VALS_U64: (u64,) = + //~^ ERROR this constant cannot be used ( u64::MAX * 2, - //~^ ERROR constant evaluation error - //~| ERROR attempt to multiply with overflow + //~^ ERROR attempt to multiply with overflow ); fn main() { diff --git a/src/test/compile-fail/const-slice-oob.rs b/src/test/compile-fail/const-slice-oob.rs index 179ea9e853f..7da5a2f17ea 100644 --- a/src/test/compile-fail/const-slice-oob.rs +++ b/src/test/compile-fail/const-slice-oob.rs @@ -14,6 +14,7 @@ const FOO: &'static[u32] = &[1, 2, 3]; const BAR: u32 = FOO[5]; //~^ ERROR constant evaluation error [E0080] //~| index out of bounds: the len is 3 but the index is 5 +//~| WARN this constant cannot be used fn main() { let _ = BAR; diff --git a/src/test/compile-fail/defaulted-never-note.rs b/src/test/compile-fail/defaulted-never-note.rs index 798544f1649..ac8ac85824e 100644 --- a/src/test/compile-fail/defaulted-never-note.rs +++ b/src/test/compile-fail/defaulted-never-note.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// We need to opt inot the `!` feature in order to trigger the +// requirement that this is testing. +#![feature(never_type)] + #![allow(unused)] trait Deserialize: Sized { diff --git a/src/test/compile-fail/edition-raw-pointer-method-2015.rs b/src/test/compile-fail/edition-raw-pointer-method-2015.rs index fdc9b4f704c..b304443f631 100644 --- a/src/test/compile-fail/edition-raw-pointer-method-2015.rs +++ b/src/test/compile-fail/edition-raw-pointer-method-2015.rs @@ -9,7 +9,7 @@ // except according to those terms. // ignore-tidy-linelength -// compile-flags: -Zedition=2015 -Zunstable-options +// compile-flags: --edition=2015 -Zunstable-options // tests that editions work with the tyvar warning-turned-error diff --git a/src/test/compile-fail/edition-raw-pointer-method-2018.rs b/src/test/compile-fail/edition-raw-pointer-method-2018.rs index 58b34591029..d01cac019e3 100644 --- a/src/test/compile-fail/edition-raw-pointer-method-2018.rs +++ b/src/test/compile-fail/edition-raw-pointer-method-2018.rs @@ -9,7 +9,7 @@ // except according to those terms. // ignore-tidy-linelength -// compile-flags: -Zedition=2018 -Zunstable-options +// compile-flags: --edition=2018 -Zunstable-options // tests that editions work with the tyvar warning-turned-error diff --git a/src/test/compile-fail/extern-macro.rs b/src/test/compile-fail/extern-macro.rs index 4267103ab9a..08269ce5c7e 100644 --- a/src/test/compile-fail/extern-macro.rs +++ b/src/test/compile-fail/extern-macro.rs @@ -10,7 +10,7 @@ // #41719 -#![feature(use_extern_macros)] +#![feature(use_extern_macros, proc_macro_path_invoc)] fn main() { enum Foo {} diff --git a/src/test/compile-fail/inhabitedness-infinite-loop.rs b/src/test/compile-fail/inhabitedness-infinite-loop.rs index b9741e0add6..d11aacec196 100644 --- a/src/test/compile-fail/inhabitedness-infinite-loop.rs +++ b/src/test/compile-fail/inhabitedness-infinite-loop.rs @@ -10,6 +10,7 @@ // error-pattern:reached recursion limit +#![feature(never_type)] #![feature(exhaustive_patterns)] struct Foo<'a, T: 'a> { diff --git a/src/test/compile-fail/issue-43105.rs b/src/test/compile-fail/issue-43105.rs index c0af3b4b9e6..6fa65a541b3 100644 --- a/src/test/compile-fail/issue-43105.rs +++ b/src/test/compile-fail/issue-43105.rs @@ -11,7 +11,7 @@ fn xyz() -> u8 { 42 } const NUM: u8 = xyz(); -//~^ ERROR calls in constants are limited to constant functions, struct and enum constructors +//~^ ERROR calls in constants are limited to constant functions, tuple structs and tuple variants //~| ERROR constant evaluation error fn main() { diff --git a/src/test/compile-fail/issue32829.rs b/src/test/compile-fail/issue32829.rs index e0b847fc994..9a84322ad06 100644 --- a/src/test/compile-fail/issue32829.rs +++ b/src/test/compile-fail/issue32829.rs @@ -7,6 +7,9 @@ // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. + +// ignore-tidy-linelength + #![feature(const_fn)] const bad : u32 = { @@ -20,7 +23,7 @@ const bad_two : u32 = { { invalid(); //~^ ERROR: blocks in constants are limited to items and tail expressions - //~^^ ERROR: calls in constants are limited to constant functions, struct and enum + //~^^ ERROR: calls in constants are limited to constant functions, tuple structs and tuple variants 0 } }; @@ -44,7 +47,7 @@ static bad_five : u32 = { { invalid(); //~^ ERROR: blocks in statics are limited to items and tail expressions - //~^^ ERROR: calls in statics are limited to constant functions, struct and enum + //~^^ ERROR: calls in statics are limited to constant functions, tuple structs and tuple variants 0 } }; @@ -68,7 +71,7 @@ static mut bad_eight : u32 = { { invalid(); //~^ ERROR: blocks in statics are limited to items and tail expressions - //~^^ ERROR: calls in statics are limited to constant functions, struct and enum + //~^^ ERROR: calls in statics are limited to constant functions, tuple structs and tuple variants 0 } }; diff --git a/src/test/compile-fail/loop-break-value.rs b/src/test/compile-fail/loop-break-value.rs index 5ef46bb27fd..938f7fba2a0 100644 --- a/src/test/compile-fail/loop-break-value.rs +++ b/src/test/compile-fail/loop-break-value.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(never_type)] + fn main() { let val: ! = loop { break break; }; //~^ ERROR mismatched types diff --git a/src/test/compile-fail/macro-with-seps-err-msg.rs b/src/test/compile-fail/macro-with-seps-err-msg.rs index 0f123997ca1..6567a100d8c 100644 --- a/src/test/compile-fail/macro-with-seps-err-msg.rs +++ b/src/test/compile-fail/macro-with-seps-err-msg.rs @@ -10,6 +10,8 @@ // gate-test-use_extern_macros +#![feature(proc_macro_path_invoc)] + fn main() { globnar::brotz!(); //~ ERROR non-ident macro paths are experimental #[derive(foo::Bar)] struct T; //~ ERROR non-ident macro paths are experimental diff --git a/src/test/compile-fail/macros-nonfatal-errors.rs b/src/test/compile-fail/macros-nonfatal-errors.rs index 7046ee12b50..40412087cef 100644 --- a/src/test/compile-fail/macros-nonfatal-errors.rs +++ b/src/test/compile-fail/macros-nonfatal-errors.rs @@ -13,6 +13,7 @@ #![feature(asm)] #![feature(trace_macros, concat_idents)] +#![feature(proc_macro_path_invoc)] #[derive(Default)] //~ ERROR enum OrDeriveThis {} diff --git a/src/test/compile-fail/match-privately-empty.rs b/src/test/compile-fail/match-privately-empty.rs index e18c7d77ce3..8777ef2ffe3 100644 --- a/src/test/compile-fail/match-privately-empty.rs +++ b/src/test/compile-fail/match-privately-empty.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(never_type)] #![feature(exhaustive_patterns)] mod private { diff --git a/src/test/compile-fail/never-assign-dead-code.rs b/src/test/compile-fail/never-assign-dead-code.rs index 4e987d1ddce..0fb75b535c6 100644 --- a/src/test/compile-fail/never-assign-dead-code.rs +++ b/src/test/compile-fail/never-assign-dead-code.rs @@ -10,6 +10,7 @@ // Test that an assignment of type ! makes the rest of the block dead code. +#![feature(never_type)] #![feature(rustc_attrs)] #![warn(unused)] diff --git a/src/test/compile-fail/never-assign-wrong-type.rs b/src/test/compile-fail/never-assign-wrong-type.rs index 8c2de7d68d3..c0dd2cab749 100644 --- a/src/test/compile-fail/never-assign-wrong-type.rs +++ b/src/test/compile-fail/never-assign-wrong-type.rs @@ -10,6 +10,7 @@ // Test that we can't use another type in place of ! +#![feature(never_type)] #![deny(warnings)] fn main() { diff --git a/src/test/compile-fail/privacy/associated-item-privacy-inherent.rs b/src/test/compile-fail/privacy/associated-item-privacy-inherent.rs index 63cb6e82c25..b64829edaa2 100644 --- a/src/test/compile-fail/privacy/associated-item-privacy-inherent.rs +++ b/src/test/compile-fail/privacy/associated-item-privacy-inherent.rs @@ -10,6 +10,7 @@ #![feature(decl_macro, associated_type_defaults)] #![allow(unused, private_in_public)] +#![feature(proc_macro_path_invoc)] mod priv_nominal { pub struct Pub; diff --git a/src/test/compile-fail/privacy/associated-item-privacy-trait.rs b/src/test/compile-fail/privacy/associated-item-privacy-trait.rs index bdc0c680a92..062dc533617 100644 --- a/src/test/compile-fail/privacy/associated-item-privacy-trait.rs +++ b/src/test/compile-fail/privacy/associated-item-privacy-trait.rs @@ -10,6 +10,7 @@ // ignore-tidy-linelength +#![feature(proc_macro_path_invoc)] #![feature(decl_macro, associated_type_defaults)] #![allow(unused, private_in_public)] diff --git a/src/test/compile-fail/privacy/associated-item-privacy-type-binding.rs b/src/test/compile-fail/privacy/associated-item-privacy-type-binding.rs index c25616c5435..0dfa61a18ab 100644 --- a/src/test/compile-fail/privacy/associated-item-privacy-type-binding.rs +++ b/src/test/compile-fail/privacy/associated-item-privacy-type-binding.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(proc_macro_path_invoc)] #![feature(decl_macro, associated_type_defaults)] #![allow(unused, private_in_public)] diff --git a/src/test/compile-fail/private-inferred-type-3.rs b/src/test/compile-fail/private-inferred-type-3.rs index 0c393f02323..97d6b470d33 100644 --- a/src/test/compile-fail/private-inferred-type-3.rs +++ b/src/test/compile-fail/private-inferred-type-3.rs @@ -18,6 +18,7 @@ // error-pattern:type `fn(u8) -> ext::PubTupleStruct {ext::PubTupleStruct::{{constructor}}}` is priv // error-pattern:type `for<'r> fn(&'r ext::Pub<u8>) {<ext::Pub<u8>>::priv_method}` is private +#![feature(proc_macro_path_invoc)] #![feature(decl_macro)] extern crate private_inferred_type as ext; diff --git a/src/test/compile-fail/private-inferred-type.rs b/src/test/compile-fail/private-inferred-type.rs index 5af8b063c16..dfc0107e075 100644 --- a/src/test/compile-fail/private-inferred-type.rs +++ b/src/test/compile-fail/private-inferred-type.rs @@ -11,6 +11,7 @@ #![feature(associated_consts)] #![feature(decl_macro)] #![allow(private_in_public)] +#![feature(proc_macro_path_invoc)] mod m { fn priv_fn() {} diff --git a/src/test/compile-fail/rfc-2126-crate-paths/crate-path-non-absolute.rs b/src/test/compile-fail/rfc-2126-crate-paths/crate-path-non-absolute.rs index 75c2a5f5bc4..65f11c063ed 100644 --- a/src/test/compile-fail/rfc-2126-crate-paths/crate-path-non-absolute.rs +++ b/src/test/compile-fail/rfc-2126-crate-paths/crate-path-non-absolute.rs @@ -12,9 +12,10 @@ struct S; -mod m { +pub mod m { fn f() { - let s = crate::S; //~ ERROR `crate` can only be used in absolute paths + let s = ::m::crate::S; //~ ERROR failed to resolve + let s2 = crate::S; // no error } } diff --git a/src/test/compile-fail/rfc-2126-crate-paths/keyword-crate-as-identifier.rs b/src/test/compile-fail/rfc-2126-crate-paths/keyword-crate-as-identifier.rs index 2c94f7b0f59..bdd03be4356 100644 --- a/src/test/compile-fail/rfc-2126-crate-paths/keyword-crate-as-identifier.rs +++ b/src/test/compile-fail/rfc-2126-crate-paths/keyword-crate-as-identifier.rs @@ -11,5 +11,5 @@ #![feature(crate_in_paths)] fn main() { - let crate = 0; //~ ERROR `crate` can only be used in absolute paths + let crate = 0; //~ ERROR failed to resolve. `crate` in paths can only be used in start position } diff --git a/src/test/compile-fail/single-primitive-inherent-impl.rs b/src/test/compile-fail/single-primitive-inherent-impl.rs index 365387c3e5e..0a0f9ce4bd1 100644 --- a/src/test/compile-fail/single-primitive-inherent-impl.rs +++ b/src/test/compile-fail/single-primitive-inherent-impl.rs @@ -15,7 +15,7 @@ #![no_std] // OK -#[lang = "str"] +#[lang = "str_alloc"] impl str {} impl str { diff --git a/src/test/compile-fail/uninhabited-irrefutable.rs b/src/test/compile-fail/uninhabited-irrefutable.rs index 72b0afa6bd3..05a97b855e7 100644 --- a/src/test/compile-fail/uninhabited-irrefutable.rs +++ b/src/test/compile-fail/uninhabited-irrefutable.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(never_type)] #![feature(exhaustive_patterns)] mod foo { diff --git a/src/test/compile-fail/uninhabited-patterns.rs b/src/test/compile-fail/uninhabited-patterns.rs index e130df5c845..2cf4b78bdff 100644 --- a/src/test/compile-fail/uninhabited-patterns.rs +++ b/src/test/compile-fail/uninhabited-patterns.rs @@ -10,6 +10,7 @@ #![feature(box_patterns)] #![feature(box_syntax)] +#![feature(never_type)] #![feature(exhaustive_patterns)] #![feature(slice_patterns)] #![deny(unreachable_patterns)] diff --git a/src/test/compile-fail/unreachable-loop-patterns.rs b/src/test/compile-fail/unreachable-loop-patterns.rs index dca79bdfb87..cfd829e416e 100644 --- a/src/test/compile-fail/unreachable-loop-patterns.rs +++ b/src/test/compile-fail/unreachable-loop-patterns.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(never_type)] #![feature(exhaustive_patterns)] #![deny(unreachable_patterns)] diff --git a/src/test/compile-fail/unreachable-try-pattern.rs b/src/test/compile-fail/unreachable-try-pattern.rs index 0caf7d51234..df340095bb4 100644 --- a/src/test/compile-fail/unreachable-try-pattern.rs +++ b/src/test/compile-fail/unreachable-try-pattern.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(never_type)] #![feature(exhaustive_patterns, rustc_attrs)] #![warn(unreachable_code)] #![warn(unreachable_patterns)] diff --git a/src/test/run-fail/adjust_never.rs b/src/test/run-fail/adjust_never.rs index 7a4b5e59eeb..da68dc39f85 100644 --- a/src/test/run-fail/adjust_never.rs +++ b/src/test/run-fail/adjust_never.rs @@ -11,6 +11,9 @@ // Test that a variable of type ! can coerce to another type. // error-pattern:explicit + +#![feature(never_type)] + fn main() { let x: ! = panic!(); let y: u32 = x; diff --git a/src/test/run-fail/call-fn-never-arg.rs b/src/test/run-fail/call-fn-never-arg.rs index 56454586bb9..95101e70db9 100644 --- a/src/test/run-fail/call-fn-never-arg.rs +++ b/src/test/run-fail/call-fn-never-arg.rs @@ -12,6 +12,7 @@ // error-pattern:wowzers! +#![feature(never_type)] #![allow(unreachable_code)] fn foo(x: !) -> ! { diff --git a/src/test/run-fail/cast-never.rs b/src/test/run-fail/cast-never.rs index 0155332c51d..8f7b0c40538 100644 --- a/src/test/run-fail/cast-never.rs +++ b/src/test/run-fail/cast-never.rs @@ -11,6 +11,9 @@ // Test that we can explicitly cast ! to another type // error-pattern:explicit + +#![feature(never_type)] + fn main() { let x: ! = panic!(); let y: u32 = x as u32; diff --git a/src/test/run-fail/never-associated-type.rs b/src/test/run-fail/never-associated-type.rs index d9b8461a1d0..fdd21e08c20 100644 --- a/src/test/run-fail/never-associated-type.rs +++ b/src/test/run-fail/never-associated-type.rs @@ -12,6 +12,8 @@ // error-pattern:kapow! +#![feature(never_type)] + trait Foo { type Wow; diff --git a/src/test/run-fail/never-type-arg.rs b/src/test/run-fail/never-type-arg.rs index 0fe10d43910..826ca3a08c0 100644 --- a/src/test/run-fail/never-type-arg.rs +++ b/src/test/run-fail/never-type-arg.rs @@ -12,6 +12,8 @@ // error-pattern:oh no! +#![feature(never_type)] + struct Wub; impl PartialEq<!> for Wub { diff --git a/src/test/run-pass-fulldeps/auxiliary/cond_plugin.rs b/src/test/run-pass-fulldeps/auxiliary/cond_plugin.rs index 281ee70815e..9e1ae59c01b 100644 --- a/src/test/run-pass-fulldeps/auxiliary/cond_plugin.rs +++ b/src/test/run-pass-fulldeps/auxiliary/cond_plugin.rs @@ -11,7 +11,7 @@ // no-prefer-dynamic #![crate_type = "proc-macro"] -#![feature(proc_macro)] +#![feature(proc_macro, proc_macro_non_items)] extern crate proc_macro; diff --git a/src/test/run-pass-fulldeps/auxiliary/custom_derive_partial_eq.rs b/src/test/run-pass-fulldeps/auxiliary/custom_derive_partial_eq.rs index f485982e2d3..6d5e82c68cc 100644 --- a/src/test/run-pass-fulldeps/auxiliary/custom_derive_partial_eq.rs +++ b/src/test/run-pass-fulldeps/auxiliary/custom_derive_partial_eq.rs @@ -58,7 +58,7 @@ fn expand_deriving_partial_eq(cx: &mut ExtCtxt, span: Span, mitem: &MetaItem, it name: "eq", generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), - args: vec![borrowed_self()], + args: vec![(borrowed_self(), "other")], ret_ty: Literal(deriving::generic::ty::Path::new_local("bool")), attributes: attrs, is_unsafe: false, diff --git a/src/test/run-pass-fulldeps/auxiliary/hello_macro.rs b/src/test/run-pass-fulldeps/auxiliary/hello_macro.rs index cf6584e961a..a680698df9a 100644 --- a/src/test/run-pass-fulldeps/auxiliary/hello_macro.rs +++ b/src/test/run-pass-fulldeps/auxiliary/hello_macro.rs @@ -11,7 +11,7 @@ // no-prefer-dynamic #![crate_type = "proc-macro"] -#![feature(proc_macro, proc_macro_lib)] +#![feature(proc_macro, proc_macro_lib, proc_macro_non_items)] extern crate proc_macro; diff --git a/src/test/run-pass-fulldeps/auxiliary/proc_macro_def.rs b/src/test/run-pass-fulldeps/auxiliary/proc_macro_def.rs index d3670ae66fe..a280b3d87c6 100644 --- a/src/test/run-pass-fulldeps/auxiliary/proc_macro_def.rs +++ b/src/test/run-pass-fulldeps/auxiliary/proc_macro_def.rs @@ -11,7 +11,7 @@ // no-prefer-dynamic #![crate_type = "proc-macro"] -#![feature(proc_macro, proc_macro_lib)] +#![feature(proc_macro, proc_macro_lib, proc_macro_non_items)] extern crate proc_macro; diff --git a/src/test/run-pass-fulldeps/deriving-hygiene.rs b/src/test/run-pass-fulldeps/deriving-hygiene.rs new file mode 100644 index 00000000000..532f2456599 --- /dev/null +++ b/src/test/run-pass-fulldeps/deriving-hygiene.rs @@ -0,0 +1,25 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(rustc_private)] +extern crate serialize; + +pub const other: u8 = 1; +pub const f: u8 = 1; +pub const d: u8 = 1; +pub const s: u8 = 1; +pub const state: u8 = 1; +pub const cmp: u8 = 1; + +#[derive(Ord,Eq,PartialOrd,PartialEq,Debug,Decodable,Encodable,Hash)] +struct Foo {} + +fn main() { +} diff --git a/src/test/run-pass-fulldeps/macro-quote-cond.rs b/src/test/run-pass-fulldeps/macro-quote-cond.rs index cff743bdae6..52e8e75f262 100644 --- a/src/test/run-pass-fulldeps/macro-quote-cond.rs +++ b/src/test/run-pass-fulldeps/macro-quote-cond.rs @@ -11,7 +11,7 @@ // aux-build:cond_plugin.rs // ignore-stage1 -#![feature(proc_macro)] +#![feature(proc_macro, proc_macro_non_items)] extern crate cond_plugin; diff --git a/src/test/run-pass-fulldeps/macro-quote-test.rs b/src/test/run-pass-fulldeps/macro-quote-test.rs index eb77895e2d7..9bb8f691915 100644 --- a/src/test/run-pass-fulldeps/macro-quote-test.rs +++ b/src/test/run-pass-fulldeps/macro-quote-test.rs @@ -13,7 +13,7 @@ // aux-build:hello_macro.rs // ignore-stage1 -#![feature(proc_macro)] +#![feature(proc_macro, proc_macro_path_invoc, proc_macro_non_items)] extern crate hello_macro; diff --git a/src/test/run-pass-fulldeps/proc-macro/attr-args.rs b/src/test/run-pass-fulldeps/proc-macro/attr-args.rs index 2968cc7871d..bf7ac507ea5 100644 --- a/src/test/run-pass-fulldeps/proc-macro/attr-args.rs +++ b/src/test/run-pass-fulldeps/proc-macro/attr-args.rs @@ -12,7 +12,7 @@ // ignore-stage1 #![allow(warnings)] -#![feature(proc_macro)] +#![feature(proc_macro, proc_macro_path_invoc)] extern crate attr_args; use attr_args::attr_with_args; @@ -20,6 +20,6 @@ use attr_args::attr_with_args; #[attr_with_args(text = "Hello, world!")] fn foo() {} -#[::attr_args::identity - fn main() { assert_eq!(foo(), "Hello, world!"); }] +#[::attr_args::identity( + fn main() { assert_eq!(foo(), "Hello, world!"); })] struct Dummy; diff --git a/src/test/run-pass-fulldeps/proc-macro/attr-on-trait.rs b/src/test/run-pass-fulldeps/proc-macro/attr-on-trait.rs index 52a8652e65b..95e4f2211c6 100644 --- a/src/test/run-pass-fulldeps/proc-macro/attr-on-trait.rs +++ b/src/test/run-pass-fulldeps/proc-macro/attr-on-trait.rs @@ -11,7 +11,7 @@ // aux-build:attr-on-trait.rs // ignore-stage1 -#![feature(proc_macro)] +#![feature(proc_macro, proc_macro_path_invoc)] extern crate attr_on_trait; diff --git a/src/test/run-pass-fulldeps/proc-macro/attr-stmt-expr.rs b/src/test/run-pass-fulldeps/proc-macro/attr-stmt-expr.rs index 98316c62ef1..d928f8e5573 100644 --- a/src/test/run-pass-fulldeps/proc-macro/attr-stmt-expr.rs +++ b/src/test/run-pass-fulldeps/proc-macro/attr-stmt-expr.rs @@ -11,7 +11,7 @@ // aux-build:attr-stmt-expr.rs // ignore-stage1 -#![feature(proc_macro, stmt_expr_attributes)] +#![feature(proc_macro, stmt_expr_attributes, proc_macro_stmt, proc_macro_expr)] extern crate attr_stmt_expr; use attr_stmt_expr::{expect_let, expect_print_stmt, expect_expr, expect_print_expr, diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-args.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-args.rs index 93815d16837..5f12cc96e9f 100644 --- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-args.rs +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-args.rs @@ -20,7 +20,7 @@ use proc_macro::TokenStream; pub fn attr_with_args(args: TokenStream, input: TokenStream) -> TokenStream { let args = args.to_string(); - assert_eq!(args, r#"( text = "Hello, world!" )"#); + assert_eq!(args, r#"text = "Hello, world!""#); let input = input.to_string(); diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/count_compound_ops.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/count_compound_ops.rs index 063d8dc4053..5376d274045 100644 --- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/count_compound_ops.rs +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/count_compound_ops.rs @@ -10,7 +10,7 @@ // no-prefer-dynamic -#![feature(proc_macro)] +#![feature(proc_macro, proc_macro_non_items)] #![crate_type = "proc-macro"] extern crate proc_macro; diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/hygiene_example_codegen.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/hygiene_example_codegen.rs index 055e4e2fad7..b8562ffc344 100644 --- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/hygiene_example_codegen.rs +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/hygiene_example_codegen.rs @@ -10,7 +10,7 @@ // no-prefer-dynamic -#![feature(proc_macro)] +#![feature(proc_macro, proc_macro_non_items)] #![crate_type = "proc-macro"] extern crate proc_macro as proc_macro_renamed; // This does not break `quote!` diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/issue-50061.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/issue-50061.rs new file mode 100644 index 00000000000..b3cd3758e65 --- /dev/null +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/issue-50061.rs @@ -0,0 +1,22 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(proc_macro)] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn check(_a: TokenStream, b: TokenStream) -> TokenStream { + b.into_iter().collect() +} diff --git a/src/test/run-pass-fulldeps/proc-macro/bang-macro.rs b/src/test/run-pass-fulldeps/proc-macro/bang-macro.rs index ffa4731f1e6..82337022ac3 100644 --- a/src/test/run-pass-fulldeps/proc-macro/bang-macro.rs +++ b/src/test/run-pass-fulldeps/proc-macro/bang-macro.rs @@ -11,7 +11,7 @@ // aux-build:bang-macro.rs // ignore-stage1 -#![feature(proc_macro)] +#![feature(proc_macro, proc_macro_non_items)] extern crate bang_macro; use bang_macro::rewrite; diff --git a/src/test/run-pass-fulldeps/proc-macro/count_compound_ops.rs b/src/test/run-pass-fulldeps/proc-macro/count_compound_ops.rs index 00ad0e76ed0..3fbe5366b6a 100644 --- a/src/test/run-pass-fulldeps/proc-macro/count_compound_ops.rs +++ b/src/test/run-pass-fulldeps/proc-macro/count_compound_ops.rs @@ -11,7 +11,7 @@ // aux-build:count_compound_ops.rs // ignore-stage1 -#![feature(proc_macro)] +#![feature(proc_macro, proc_macro_non_items)] extern crate count_compound_ops; use count_compound_ops::count_compound_ops; diff --git a/src/test/run-pass-fulldeps/proc-macro/derive-b.rs b/src/test/run-pass-fulldeps/proc-macro/derive-b.rs index 995dc65729a..d4176c0efbf 100644 --- a/src/test/run-pass-fulldeps/proc-macro/derive-b.rs +++ b/src/test/run-pass-fulldeps/proc-macro/derive-b.rs @@ -11,7 +11,7 @@ // aux-build:derive-b.rs // ignore-stage1 -#![feature(proc_macro)] +#![feature(proc_macro, proc_macro_path_invoc)] extern crate derive_b; diff --git a/src/test/run-pass-fulldeps/proc-macro/hygiene_example.rs b/src/test/run-pass-fulldeps/proc-macro/hygiene_example.rs index 4cac7d19b4d..48de15b934d 100644 --- a/src/test/run-pass-fulldeps/proc-macro/hygiene_example.rs +++ b/src/test/run-pass-fulldeps/proc-macro/hygiene_example.rs @@ -12,7 +12,7 @@ // aux-build:hygiene_example.rs // ignore-stage1 -#![feature(proc_macro)] +#![feature(proc_macro, proc_macro_non_items)] extern crate hygiene_example; use hygiene_example::hello; diff --git a/src/test/run-pass-fulldeps/proc-macro/issue-42708.rs b/src/test/run-pass-fulldeps/proc-macro/issue-42708.rs index e53e94ae475..a6b7d93c279 100644 --- a/src/test/run-pass-fulldeps/proc-macro/issue-42708.rs +++ b/src/test/run-pass-fulldeps/proc-macro/issue-42708.rs @@ -11,7 +11,7 @@ // aux-build:issue-42708.rs // ignore-stage1 -#![feature(decl_macro, proc_macro)] +#![feature(decl_macro, proc_macro, proc_macro_path_invoc)] #![allow(unused)] extern crate issue_42708; diff --git a/src/test/run-pass-fulldeps/proc-macro/issue-50061.rs b/src/test/run-pass-fulldeps/proc-macro/issue-50061.rs new file mode 100644 index 00000000000..03f69c09277 --- /dev/null +++ b/src/test/run-pass-fulldeps/proc-macro/issue-50061.rs @@ -0,0 +1,31 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:issue-50061.rs +// ignore-stage1 + +#![feature(proc_macro, proc_macro_path_invoc, decl_macro)] + +extern crate issue_50061; + +macro inner(any_token $v: tt) { + $v +} + +macro outer($v: tt) { + inner!(any_token $v) +} + +#[issue_50061::check] +fn main() { + //! this doc comment forces roundtrip through a string + let checkit = 0; + outer!(checkit); +} diff --git a/src/test/run-pass-fulldeps/proc-macro/negative-token.rs b/src/test/run-pass-fulldeps/proc-macro/negative-token.rs index 418e692fa24..1cdf1daf560 100644 --- a/src/test/run-pass-fulldeps/proc-macro/negative-token.rs +++ b/src/test/run-pass-fulldeps/proc-macro/negative-token.rs @@ -11,7 +11,7 @@ // aux-build:negative-token.rs // ignore-stage1 -#![feature(proc_macro)] +#![feature(proc_macro, proc_macro_non_items)] extern crate negative_token; diff --git a/src/test/run-pass-fulldeps/proc_macro.rs b/src/test/run-pass-fulldeps/proc_macro.rs index cdda723585b..aad94c89f2a 100644 --- a/src/test/run-pass-fulldeps/proc_macro.rs +++ b/src/test/run-pass-fulldeps/proc_macro.rs @@ -12,7 +12,7 @@ // ignore-stage1 // ignore-cross-compile -#![feature(proc_macro)] +#![feature(proc_macro, proc_macro_non_items)] extern crate proc_macro_def; diff --git a/src/test/run-pass/allocator-alloc-one.rs b/src/test/run-pass/allocator-alloc-one.rs index d4fcdcf743b..12b115d0938 100644 --- a/src/test/run-pass/allocator-alloc-one.rs +++ b/src/test/run-pass/allocator-alloc-one.rs @@ -10,13 +10,11 @@ #![feature(allocator_api, nonnull)] -use std::alloc::{Alloc, Global}; +use std::alloc::{Alloc, Global, oom}; fn main() { unsafe { - let ptr = Global.alloc_one::<i32>().unwrap_or_else(|_| { - Global.oom() - }); + let ptr = Global.alloc_one::<i32>().unwrap_or_else(|_| oom()); *ptr.as_ptr() = 4; assert_eq!(*ptr.as_ptr(), 4); Global.dealloc_one(ptr); diff --git a/src/test/run-pass/auxiliary/using-target-feature-unstable.rs b/src/test/run-pass/auxiliary/using-target-feature-unstable.rs new file mode 100644 index 00000000000..8b7d0332fe9 --- /dev/null +++ b/src/test/run-pass/auxiliary/using-target-feature-unstable.rs @@ -0,0 +1,15 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(mmx_target_feature)] + +#[inline] +#[target_feature(enable = "mmx")] +pub unsafe fn foo() {} diff --git a/src/test/run-pass/compiletest-skip-trans.rs b/src/test/run-pass/compiletest-skip-trans.rs new file mode 100644 index 00000000000..d24a6506c2c --- /dev/null +++ b/src/test/run-pass/compiletest-skip-trans.rs @@ -0,0 +1,17 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that with the `skip-trans` option the test isn't executed. + +// skip-trans + +fn main() { + unreachable!(); +} diff --git a/src/test/run-pass/diverging-fallback-control-flow.rs b/src/test/run-pass/diverging-fallback-control-flow.rs index a96f98b9efd..723a98bcdfa 100644 --- a/src/test/run-pass/diverging-fallback-control-flow.rs +++ b/src/test/run-pass/diverging-fallback-control-flow.rs @@ -14,6 +14,8 @@ // These represent current behavior, but are pretty dubious. I would // like to revisit these and potentially change them. --nmatsakis +#![feature(never_type)] + trait BadDefault { fn default() -> Self; } diff --git a/src/test/run-pass/empty-types-in-patterns.rs b/src/test/run-pass/empty-types-in-patterns.rs index 87db4401929..86cf9b5ec47 100644 --- a/src/test/run-pass/empty-types-in-patterns.rs +++ b/src/test/run-pass/empty-types-in-patterns.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(never_type)] #![feature(exhaustive_patterns)] #![feature(slice_patterns)] #![allow(unreachable_patterns)] diff --git a/src/test/run-pass/format-hygiene.rs b/src/test/run-pass/format-hygiene.rs new file mode 100644 index 00000000000..6971f775231 --- /dev/null +++ b/src/test/run-pass/format-hygiene.rs @@ -0,0 +1,15 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub const arg0: u8 = 1; + +pub fn main() { + format!("{}", 1); +} diff --git a/src/test/run-pass/hygiene/issue-47311.rs b/src/test/run-pass/hygiene/issue-47311.rs index 3b6890cdce6..c4391ad0577 100644 --- a/src/test/run-pass/hygiene/issue-47311.rs +++ b/src/test/run-pass/hygiene/issue-47311.rs @@ -10,7 +10,7 @@ // ignore-pretty pretty-printing is unhygienic -#![feature(decl_macro)] +#![feature(decl_macro, proc_macro_path_invoc)] #![allow(unused)] macro m($S:ident, $x:ident) { diff --git a/src/test/run-pass/hygiene/issue-47312.rs b/src/test/run-pass/hygiene/issue-47312.rs index 5e83f3808d8..0cda0e7c7cc 100644 --- a/src/test/run-pass/hygiene/issue-47312.rs +++ b/src/test/run-pass/hygiene/issue-47312.rs @@ -10,7 +10,7 @@ // ignore-pretty pretty-printing is unhygienic -#![feature(decl_macro)] +#![feature(decl_macro, proc_macro_path_invoc)] #![allow(unused)] mod foo { diff --git a/src/test/run-pass/hygiene/legacy_interaction.rs b/src/test/run-pass/hygiene/legacy_interaction.rs index 683a15b99ae..5395ef35882 100644 --- a/src/test/run-pass/hygiene/legacy_interaction.rs +++ b/src/test/run-pass/hygiene/legacy_interaction.rs @@ -12,7 +12,7 @@ // aux-build:legacy_interaction.rs -#![feature(decl_macro)] +#![feature(decl_macro, proc_macro_path_invoc)] #[allow(unused)] extern crate legacy_interaction; diff --git a/src/test/run-pass/hygiene/lexical.rs b/src/test/run-pass/hygiene/lexical.rs index cb02a17fec3..73deda0777e 100644 --- a/src/test/run-pass/hygiene/lexical.rs +++ b/src/test/run-pass/hygiene/lexical.rs @@ -10,7 +10,7 @@ // ignore-pretty pretty-printing is unhygienic -#![feature(decl_macro)] +#![feature(decl_macro, proc_macro_path_invoc)] mod bar { mod baz { diff --git a/src/test/run-pass/hygiene/wrap_unhygienic_example.rs b/src/test/run-pass/hygiene/wrap_unhygienic_example.rs index 55206950214..66e83eb7cac 100644 --- a/src/test/run-pass/hygiene/wrap_unhygienic_example.rs +++ b/src/test/run-pass/hygiene/wrap_unhygienic_example.rs @@ -13,7 +13,7 @@ // aux-build:my_crate.rs // aux-build:unhygienic_example.rs -#![feature(decl_macro)] +#![feature(decl_macro, proc_macro_path_invoc)] extern crate unhygienic_example; extern crate my_crate; // (b) diff --git a/src/test/run-pass/hygiene/xcrate.rs b/src/test/run-pass/hygiene/xcrate.rs index 6df3a34d3c8..95d7ae6db60 100644 --- a/src/test/run-pass/hygiene/xcrate.rs +++ b/src/test/run-pass/hygiene/xcrate.rs @@ -12,7 +12,7 @@ // aux-build:xcrate.rs -#![feature(decl_macro)] +#![feature(decl_macro, proc_macro_path_invoc)] extern crate xcrate; diff --git a/src/test/run-pass/impl-for-never.rs b/src/test/run-pass/impl-for-never.rs index cf54e1c3bd5..794f5969bff 100644 --- a/src/test/run-pass/impl-for-never.rs +++ b/src/test/run-pass/impl-for-never.rs @@ -10,6 +10,8 @@ // Test that we can call static methods on ! both directly and when it appears in a generic +#![feature(never_type)] + trait StringifyType { fn stringify_type() -> &'static str; } diff --git a/src/test/run-pass/issue-44402.rs b/src/test/run-pass/issue-44402.rs index a5a0a5a5794..5cbd3446d9b 100644 --- a/src/test/run-pass/issue-44402.rs +++ b/src/test/run-pass/issue-44402.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(never_type)] #![feature(exhaustive_patterns)] // Regression test for inhabitedness check. The old diff --git a/src/test/run-pass/loop-break-value.rs b/src/test/run-pass/loop-break-value.rs index ffdd99ebf6e..39053769b24 100644 --- a/src/test/run-pass/loop-break-value.rs +++ b/src/test/run-pass/loop-break-value.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(never_type)] + #[allow(unused)] fn never_returns() { loop { diff --git a/src/test/run-pass/mir_calls_to_shims.rs b/src/test/run-pass/mir_calls_to_shims.rs index dda7a46f325..9641ed28293 100644 --- a/src/test/run-pass/mir_calls_to_shims.rs +++ b/src/test/run-pass/mir_calls_to_shims.rs @@ -11,6 +11,7 @@ // ignore-wasm32-bare compiled with panic=abort by default #![feature(fn_traits)] +#![feature(never_type)] use std::panic; diff --git a/src/test/run-pass/never-result.rs b/src/test/run-pass/never-result.rs index 8aa2a13ed8c..5c0af392f44 100644 --- a/src/test/run-pass/never-result.rs +++ b/src/test/run-pass/never-result.rs @@ -10,6 +10,8 @@ // Test that we can extract a ! through pattern matching then use it as several different types. +#![feature(never_type)] + fn main() { let x: Result<u32, !> = Ok(123); match x { diff --git a/src/test/run-pass/paths-in-macro-invocations.rs b/src/test/run-pass/paths-in-macro-invocations.rs index 69f8906778a..2e87809a84e 100644 --- a/src/test/run-pass/paths-in-macro-invocations.rs +++ b/src/test/run-pass/paths-in-macro-invocations.rs @@ -10,7 +10,7 @@ // aux-build:two_macros.rs -#![feature(use_extern_macros)] +#![feature(use_extern_macros, proc_macro_path_invoc)] extern crate two_macros; diff --git a/src/test/run-pass/realloc-16687.rs b/src/test/run-pass/realloc-16687.rs index afa3494c389..308792e5d89 100644 --- a/src/test/run-pass/realloc-16687.rs +++ b/src/test/run-pass/realloc-16687.rs @@ -15,7 +15,7 @@ #![feature(heap_api, allocator_api)] -use std::alloc::{Global, Alloc, Layout}; +use std::alloc::{Global, Alloc, Layout, oom}; use std::ptr::{self, NonNull}; fn main() { @@ -50,7 +50,7 @@ unsafe fn test_triangle() -> bool { println!("allocate({:?})", layout); } - let ret = Global.alloc(layout.clone()).unwrap_or_else(|_| Global.oom()); + let ret = Global.alloc(layout.clone()).unwrap_or_else(|_| oom()); if PRINT { println!("allocate({:?}) = {:?}", layout, ret); @@ -73,7 +73,7 @@ unsafe fn test_triangle() -> bool { } let ret = Global.realloc(NonNull::new_unchecked(ptr).as_opaque(), old.clone(), new.size()) - .unwrap_or_else(|_| Global.oom()); + .unwrap_or_else(|_| oom()); if PRINT { println!("reallocate({:?}, old={:?}, new={:?}) = {:?}", diff --git a/src/test/run-pass/regions-mock-trans.rs b/src/test/run-pass/regions-mock-trans.rs index 44be59f5c5b..60a7f70931d 100644 --- a/src/test/run-pass/regions-mock-trans.rs +++ b/src/test/run-pass/regions-mock-trans.rs @@ -12,7 +12,7 @@ #![feature(allocator_api)] -use std::alloc::{Alloc, Global, Layout}; +use std::alloc::{Alloc, Global, Layout, oom}; use std::ptr::NonNull; struct arena(()); @@ -33,7 +33,7 @@ struct Ccx { fn alloc<'a>(_bcx : &'a arena) -> &'a Bcx<'a> { unsafe { let ptr = Global.alloc(Layout::new::<Bcx>()) - .unwrap_or_else(|_| Global.oom()); + .unwrap_or_else(|_| oom()); &*(ptr.as_ptr() as *const _) } } diff --git a/src/test/compile-fail/rfc-2126-crate-paths/crate-visibility-ambiguity.rs b/src/test/run-pass/rfc-2126-crate-paths/crate-path-visibility-ambiguity.rs index 8c5a971c2f7..1a8d2d80ef4 100644 --- a/src/test/compile-fail/rfc-2126-crate-paths/crate-visibility-ambiguity.rs +++ b/src/test/run-pass/rfc-2126-crate-paths/crate-path-visibility-ambiguity.rs @@ -15,7 +15,7 @@ mod m { pub struct Z; pub struct S1(crate (::m::Z)); // OK pub struct S2(::crate ::m::Z); // OK - pub struct S3(crate ::m::Z); //~ ERROR `crate` can only be used in absolute paths + pub struct S3(crate ::m::Z); // OK } fn main() { diff --git a/src/test/run-pass/type-sizes.rs b/src/test/run-pass/type-sizes.rs index 0bb18d8729a..7bd9a1703ee 100644 --- a/src/test/run-pass/type-sizes.rs +++ b/src/test/run-pass/type-sizes.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(never_type)] use std::mem::size_of; diff --git a/src/test/run-pass/using-target-feature-unstable.rs b/src/test/run-pass/using-target-feature-unstable.rs new file mode 100644 index 00000000000..614c8d4e1d4 --- /dev/null +++ b/src/test/run-pass/using-target-feature-unstable.rs @@ -0,0 +1,20 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// only-x86_64 +// aux-build:using-target-feature-unstable.rs + +extern crate using_target_feature_unstable; + +fn main() { + unsafe { + using_target_feature_unstable::foo(); + } +} diff --git a/src/test/rustdoc-js/alias-1.js b/src/test/rustdoc-js/alias-1.js new file mode 100644 index 00000000000..496bd559b87 --- /dev/null +++ b/src/test/rustdoc-js/alias-1.js @@ -0,0 +1,17 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +const QUERY = '&'; + +const EXPECTED = { + 'others': [ + { 'path': 'std', 'name': 'reference' }, + ], +}; diff --git a/src/test/rustdoc-js/alias-2.js b/src/test/rustdoc-js/alias-2.js new file mode 100644 index 00000000000..f31786df67c --- /dev/null +++ b/src/test/rustdoc-js/alias-2.js @@ -0,0 +1,18 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +const QUERY = '+'; + +const EXPECTED = { + 'others': [ + { 'path': 'std::ops::AddAssign', 'name': 'AddAssign' }, + { 'path': 'std::ops::Add', 'name': 'Add' }, + ], +}; diff --git a/src/test/rustdoc-js/alias-3.js b/src/test/rustdoc-js/alias-3.js new file mode 100644 index 00000000000..d9e1ca5f760 --- /dev/null +++ b/src/test/rustdoc-js/alias-3.js @@ -0,0 +1,17 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +const QUERY = '!'; + +const EXPECTED = { + 'others': [ + { 'path': 'std', 'name': 'never' }, + ], +}; diff --git a/src/test/rustdoc-js/alias.js b/src/test/rustdoc-js/alias.js new file mode 100644 index 00000000000..a0500f24c17 --- /dev/null +++ b/src/test/rustdoc-js/alias.js @@ -0,0 +1,19 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +const QUERY = '['; + +const EXPECTED = { + 'others': [ + { 'path': 'std', 'name': 'slice' }, + { 'path': 'std::ops::IndexMut', 'name': 'IndexMut' }, + { 'path': 'std::ops::Index', 'name': 'Index' }, + ], +}; diff --git a/src/test/rustdoc-js/never.js b/src/test/rustdoc-js/never.js new file mode 100644 index 00000000000..d9e1ca5f760 --- /dev/null +++ b/src/test/rustdoc-js/never.js @@ -0,0 +1,17 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +const QUERY = '!'; + +const EXPECTED = { + 'others': [ + { 'path': 'std', 'name': 'never' }, + ], +}; diff --git a/src/test/rustdoc/issue-23511.rs b/src/test/rustdoc/issue-23511.rs index 50c31d309ee..ee0a5c1aa1b 100644 --- a/src/test/rustdoc/issue-23511.rs +++ b/src/test/rustdoc/issue-23511.rs @@ -14,7 +14,7 @@ pub mod str { #![doc(primitive = "str")] - #[lang = "str"] + #[lang = "str_alloc"] impl str { // @has search-index.js foo pub fn foo(&self) {} diff --git a/src/test/ui-fulldeps/proc-macro/parent-source-spans.rs b/src/test/ui-fulldeps/proc-macro/parent-source-spans.rs index 4c71afbac4d..f938700e515 100644 --- a/src/test/ui-fulldeps/proc-macro/parent-source-spans.rs +++ b/src/test/ui-fulldeps/proc-macro/parent-source-spans.rs @@ -11,7 +11,7 @@ // aux-build:parent-source-spans.rs // ignore-stage1 -#![feature(proc_macro, decl_macro)] +#![feature(proc_macro, decl_macro, proc_macro_non_items)] extern crate parent_source_spans; diff --git a/src/test/ui-fulldeps/proc-macro/three-equals.rs b/src/test/ui-fulldeps/proc-macro/three-equals.rs index ef2d1605290..66e34afcb13 100644 --- a/src/test/ui-fulldeps/proc-macro/three-equals.rs +++ b/src/test/ui-fulldeps/proc-macro/three-equals.rs @@ -11,7 +11,7 @@ // aux-build:three-equals.rs // ignore-stage1 -#![feature(proc_macro)] +#![feature(proc_macro, proc_macro_non_items)] extern crate three_equals; diff --git a/src/test/ui/associated-types-ICE-when-projecting-out-of-err.rs b/src/test/ui/associated-types-ICE-when-projecting-out-of-err.rs index 052575de4c2..75b60aa8d10 100644 --- a/src/test/ui/associated-types-ICE-when-projecting-out-of-err.rs +++ b/src/test/ui/associated-types-ICE-when-projecting-out-of-err.rs @@ -31,5 +31,5 @@ trait Add<RHS=Self> { fn ice<A>(a: A) { let r = loop {}; r = r + a; - //~^ ERROR the trait bound `!: Add<A>` is not satisfied + //~^ ERROR the trait bound `(): Add<A>` is not satisfied } diff --git a/src/test/ui/associated-types-ICE-when-projecting-out-of-err.stderr b/src/test/ui/associated-types-ICE-when-projecting-out-of-err.stderr index c22a645385a..7924ab74444 100644 --- a/src/test/ui/associated-types-ICE-when-projecting-out-of-err.stderr +++ b/src/test/ui/associated-types-ICE-when-projecting-out-of-err.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `!: Add<A>` is not satisfied +error[E0277]: the trait bound `(): Add<A>` is not satisfied --> $DIR/associated-types-ICE-when-projecting-out-of-err.rs:33:11 | LL | r = r + a; - | ^ the trait `Add<A>` is not implemented for `!` + | ^ the trait `Add<A>` is not implemented for `()` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-closures-two-mut.nll.stderr b/src/test/ui/borrowck/borrowck-closures-two-mut.nll.stderr deleted file mode 100644 index a21a6e36778..00000000000 --- a/src/test/ui/borrowck/borrowck-closures-two-mut.nll.stderr +++ /dev/null @@ -1,78 +0,0 @@ -error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast) - --> $DIR/borrowck-closures-two-mut.rs:24:24 - | -LL | let c1 = to_fn_mut(|| x = 4); - | -- - previous borrow occurs due to use of `x` in closure - | | - | first mutable borrow occurs here -LL | let c2 = to_fn_mut(|| x = 5); //~ ERROR cannot borrow `x` as mutable more than once - | ^^ - borrow occurs due to use of `x` in closure - | | - | second mutable borrow occurs here -LL | //~| ERROR cannot borrow `x` as mutable more than once -LL | } - | - first borrow ends here - -error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast) - --> $DIR/borrowck-closures-two-mut.rs:35:24 - | -LL | let c1 = to_fn_mut(|| set(&mut x)); - | -- - previous borrow occurs due to use of `x` in closure - | | - | first mutable borrow occurs here -LL | let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once - | ^^ - borrow occurs due to use of `x` in closure - | | - | second mutable borrow occurs here -LL | //~| ERROR cannot borrow `x` as mutable more than once -LL | } - | - first borrow ends here - -error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast) - --> $DIR/borrowck-closures-two-mut.rs:42:24 - | -LL | let c1 = to_fn_mut(|| x = 5); - | -- - previous borrow occurs due to use of `x` in closure - | | - | first mutable borrow occurs here -LL | let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once - | ^^ - borrow occurs due to use of `x` in closure - | | - | second mutable borrow occurs here -LL | //~| ERROR cannot borrow `x` as mutable more than once -LL | } - | - first borrow ends here - -error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast) - --> $DIR/borrowck-closures-two-mut.rs:49:24 - | -LL | let c1 = to_fn_mut(|| x = 5); - | -- - previous borrow occurs due to use of `x` in closure - | | - | first mutable borrow occurs here -LL | let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nested closure) - | ^^ - borrow occurs due to use of `x` in closure - | | - | second mutable borrow occurs here -... -LL | } - | - first borrow ends here - -error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast) - --> $DIR/borrowck-closures-two-mut.rs:61:24 - | -LL | let c1 = to_fn_mut(|| set(&mut *x.f)); - | -- - previous borrow occurs due to use of `x` in closure - | | - | first mutable borrow occurs here -LL | let c2 = to_fn_mut(|| set(&mut *x.f)); - | ^^ - borrow occurs due to use of `x` in closure - | | - | second mutable borrow occurs here -... -LL | } - | - first borrow ends here - -error: aborting due to 5 previous errors - -For more information about this error, try `rustc --explain E0499`. diff --git a/src/test/ui/borrowck/issue-45983.nll.stderr b/src/test/ui/borrowck/issue-45983.nll.stderr index ecd17edb079..1aec71fee34 100644 --- a/src/test/ui/borrowck/issue-45983.nll.stderr +++ b/src/test/ui/borrowck/issue-45983.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/issue-45983.rs:17:27 | LL | give_any(|y| x = Some(y)); @@ -16,7 +16,7 @@ error[E0594]: cannot assign to immutable item `x` LL | give_any(|y| x = Some(y)); | ^^^^^^^^^^^ cannot mutate | - = note: Value not mutable causing this error: `x` + = note: the value which is causing this path not to be mutable is...: `x` error[E0596]: cannot borrow immutable item `x` as mutable --> $DIR/issue-45983.rs:17:14 diff --git a/src/test/ui/borrowck/issue-7573.nll.stderr b/src/test/ui/borrowck/issue-7573.nll.stderr index c55c49604d0..84c6236eb0a 100644 --- a/src/test/ui/borrowck/issue-7573.nll.stderr +++ b/src/test/ui/borrowck/issue-7573.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/issue-7573.rs:27:31 | LL | let mut lines_to_use: Vec<&CrateId> = Vec::new(); diff --git a/src/test/ui/borrowck/regions-escape-bound-fn-2.nll.stderr b/src/test/ui/borrowck/regions-escape-bound-fn-2.nll.stderr index d34a716bb2b..ee3970aa8fd 100644 --- a/src/test/ui/borrowck/regions-escape-bound-fn-2.nll.stderr +++ b/src/test/ui/borrowck/regions-escape-bound-fn-2.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/regions-escape-bound-fn-2.rs:18:27 | LL | with_int(|y| x = Some(y)); diff --git a/src/test/ui/borrowck/regions-escape-bound-fn.nll.stderr b/src/test/ui/borrowck/regions-escape-bound-fn.nll.stderr index b69c172bcdc..07a4ab1dbb1 100644 --- a/src/test/ui/borrowck/regions-escape-bound-fn.nll.stderr +++ b/src/test/ui/borrowck/regions-escape-bound-fn.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/regions-escape-bound-fn.rs:18:22 | LL | with_int(|y| x = Some(y)); diff --git a/src/test/ui/borrowck/regions-escape-unboxed-closure.nll.stderr b/src/test/ui/borrowck/regions-escape-unboxed-closure.nll.stderr index 788654a2ecc..14c255ef527 100644 --- a/src/test/ui/borrowck/regions-escape-unboxed-closure.nll.stderr +++ b/src/test/ui/borrowck/regions-escape-unboxed-closure.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/regions-escape-unboxed-closure.rs:16:27 | LL | with_int(&mut |y| x = Some(y)); diff --git a/src/test/ui/chalkify/lower_env1.rs b/src/test/ui/chalkify/lower_env1.rs new file mode 100644 index 00000000000..fc20ad0e08b --- /dev/null +++ b/src/test/ui/chalkify/lower_env1.rs @@ -0,0 +1,24 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(rustc_attrs)] +#![allow(dead_code)] + +trait Foo { } + +#[rustc_dump_program_clauses] //~ ERROR program clause dump +trait Bar where Self: Foo { } + +#[rustc_dump_env_program_clauses] //~ ERROR program clause dump +fn bar<T: Bar>() { +} + +fn main() { +} diff --git a/src/test/ui/chalkify/lower_env1.stderr b/src/test/ui/chalkify/lower_env1.stderr new file mode 100644 index 00000000000..3a280f85e76 --- /dev/null +++ b/src/test/ui/chalkify/lower_env1.stderr @@ -0,0 +1,24 @@ +error: program clause dump + --> $DIR/lower_env1.rs:16:1 + | +LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: FromEnv(Self: Bar) :- FromEnv(Self: Bar). + = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar). + = note: Implemented(Self: Bar) :- FromEnv(Self: Bar). + +error: program clause dump + --> $DIR/lower_env1.rs:19:1 + | +LL | #[rustc_dump_env_program_clauses] //~ ERROR program clause dump + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: FromEnv(Self: Bar) :- FromEnv(Self: Bar). + = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar). + = note: Implemented(Self: Bar) :- FromEnv(Self: Bar). + = note: Implemented(Self: Foo) :- FromEnv(Self: Foo). + = note: Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized). + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/chalkify/lower_impl.rs b/src/test/ui/chalkify/lower_impl.rs index 671d77efbea..b38b87cdb12 100644 --- a/src/test/ui/chalkify/lower_impl.rs +++ b/src/test/ui/chalkify/lower_impl.rs @@ -12,7 +12,7 @@ trait Foo { } -#[rustc_dump_program_clauses] //~ ERROR Implemented(T: Foo) :- +#[rustc_dump_program_clauses] //~ ERROR program clause dump impl<T: 'static> Foo for T where T: Iterator<Item = i32> { } trait Bar { @@ -20,7 +20,7 @@ trait Bar { } impl<T> Bar for T where T: Iterator<Item = i32> { - #[rustc_dump_program_clauses] //~ ERROR Normalize(<T as Bar>::Assoc == std::vec::Vec<T>) :- + #[rustc_dump_program_clauses] //~ ERROR program clause dump type Assoc = Vec<T>; } diff --git a/src/test/ui/chalkify/lower_impl.stderr b/src/test/ui/chalkify/lower_impl.stderr index f253f9847d1..c497d76f8d4 100644 --- a/src/test/ui/chalkify/lower_impl.stderr +++ b/src/test/ui/chalkify/lower_impl.stderr @@ -1,14 +1,18 @@ -error: Implemented(T: Foo) :- ProjectionEq(<T as std::iter::Iterator>::Item == i32), TypeOutlives(T : 'static), Implemented(T: std::iter::Iterator), Implemented(T: std::marker::Sized). +error: program clause dump --> $DIR/lower_impl.rs:15:1 | -LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(T: Foo) :- +LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: Implemented(T: Foo) :- ProjectionEq(<T as std::iter::Iterator>::Item == i32), TypeOutlives(T : 'static), Implemented(T: std::iter::Iterator), Implemented(T: std::marker::Sized). -error: Normalize(<T as Bar>::Assoc == std::vec::Vec<T>) :- Implemented(T: Bar). +error: program clause dump --> $DIR/lower_impl.rs:23:5 | -LL | #[rustc_dump_program_clauses] //~ ERROR Normalize(<T as Bar>::Assoc == std::vec::Vec<T>) :- +LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: Normalize(<T as Bar>::Assoc == std::vec::Vec<T>) :- Implemented(T: Bar). error: aborting due to 2 previous errors diff --git a/src/test/ui/chalkify/lower_trait.rs b/src/test/ui/chalkify/lower_trait.rs index 74feb0105cc..7c0f233a645 100644 --- a/src/test/ui/chalkify/lower_trait.rs +++ b/src/test/ui/chalkify/lower_trait.rs @@ -10,10 +10,7 @@ #![feature(rustc_attrs)] -#[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :- - //~| ERROR FromEnv - //~| ERROR FromEnv - //~| ERROR FromEnv +#[rustc_dump_program_clauses] //~ ERROR program clause dump trait Foo<S, T, U> { fn s(S) -> S; fn t(T) -> T; diff --git a/src/test/ui/chalkify/lower_trait.stderr b/src/test/ui/chalkify/lower_trait.stderr index 45753c3bb90..55cd9699b06 100644 --- a/src/test/ui/chalkify/lower_trait.stderr +++ b/src/test/ui/chalkify/lower_trait.stderr @@ -1,26 +1,13 @@ -error: Implemented(Self: Foo<S, T, U>) :- FromEnv(Self: Foo<S, T, U>). +error: program clause dump --> $DIR/lower_trait.rs:13:1 | -LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :- +LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>). - --> $DIR/lower_trait.rs:13:1 - | -LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :- - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: FromEnv(T: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>). - --> $DIR/lower_trait.rs:13:1 | -LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :- - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: FromEnv(U: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>). - --> $DIR/lower_trait.rs:13:1 - | -LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :- - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>). + = note: FromEnv(T: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>). + = note: FromEnv(U: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>). + = note: Implemented(Self: Foo<S, T, U>) :- FromEnv(Self: Foo<S, T, U>). -error: aborting due to 4 previous errors +error: aborting due to previous error diff --git a/src/test/ui/chalkify/lower_trait_higher_rank.rs b/src/test/ui/chalkify/lower_trait_higher_rank.rs index e5eaf4591ec..47e9398d364 100644 --- a/src/test/ui/chalkify/lower_trait_higher_rank.rs +++ b/src/test/ui/chalkify/lower_trait_higher_rank.rs @@ -10,10 +10,7 @@ #![feature(rustc_attrs)] -#[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<F>) :- - //~| ERROR FromEnv - //~| ERROR FromEnv - //~| ERROR FromEnv +#[rustc_dump_program_clauses] //~ ERROR program clause dump trait Foo<F> where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8 { fn s(F) -> F; diff --git a/src/test/ui/chalkify/lower_trait_higher_rank.stderr b/src/test/ui/chalkify/lower_trait_higher_rank.stderr index 9aed0c018c9..7f6f503c6ff 100644 --- a/src/test/ui/chalkify/lower_trait_higher_rank.stderr +++ b/src/test/ui/chalkify/lower_trait_higher_rank.stderr @@ -1,26 +1,13 @@ -error: Implemented(Self: Foo<F>) :- FromEnv(Self: Foo<F>). +error: program clause dump --> $DIR/lower_trait_higher_rank.rs:13:1 | -LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<F>) :- +LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: FromEnv(F: std::marker::Sized) :- FromEnv(Self: Foo<F>). - --> $DIR/lower_trait_higher_rank.rs:13:1 - | -LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<F>) :- - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: FromEnv(F: std::ops::Fn<(&'a (u8, u16),)>) :- FromEnv(Self: Foo<F>). - --> $DIR/lower_trait_higher_rank.rs:13:1 | -LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<F>) :- - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: FromEnv(<F as std::ops::FnOnce<(&'a (u8, u16),)>>::Output == &'a u8) :- FromEnv(Self: Foo<F>). - --> $DIR/lower_trait_higher_rank.rs:13:1 - | -LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<F>) :- - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: FromEnv(<F as std::ops::FnOnce<(&'a (u8, u16),)>>::Output == &'a u8) :- FromEnv(Self: Foo<F>). + = note: FromEnv(F: std::marker::Sized) :- FromEnv(Self: Foo<F>). + = note: FromEnv(F: std::ops::Fn<(&'a (u8, u16),)>) :- FromEnv(Self: Foo<F>). + = note: Implemented(Self: Foo<F>) :- FromEnv(Self: Foo<F>). -error: aborting due to 4 previous errors +error: aborting due to previous error diff --git a/src/test/ui/chalkify/lower_trait_where_clause.rs b/src/test/ui/chalkify/lower_trait_where_clause.rs index b2ce3ca48b2..67ee7c28b6a 100644 --- a/src/test/ui/chalkify/lower_trait_where_clause.rs +++ b/src/test/ui/chalkify/lower_trait_where_clause.rs @@ -13,13 +13,7 @@ use std::fmt::{Debug, Display}; use std::borrow::Borrow; -#[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :- - //~| ERROR FromEnv - //~| ERROR FromEnv - //~| ERROR FromEnv - //~| ERROR FromEnv - //~| ERROR RegionOutlives - //~| ERROR TypeOutlives +#[rustc_dump_program_clauses] //~ ERROR program clause dump trait Foo<'a, 'b, S, T, U> where S: Debug, T: Borrow<U>, U: ?Sized, 'a: 'b, U: 'b { fn s(S) -> S; fn t(T) -> T; diff --git a/src/test/ui/chalkify/lower_trait_where_clause.stderr b/src/test/ui/chalkify/lower_trait_where_clause.stderr index a9ecaec3aff..68bc2ddf293 100644 --- a/src/test/ui/chalkify/lower_trait_where_clause.stderr +++ b/src/test/ui/chalkify/lower_trait_where_clause.stderr @@ -1,44 +1,16 @@ -error: Implemented(Self: Foo<'a, 'b, S, T, U>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). +error: program clause dump --> $DIR/lower_trait_where_clause.rs:16:1 | -LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :- +LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). - --> $DIR/lower_trait_where_clause.rs:16:1 - | -LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :- - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: FromEnv(T: std::marker::Sized) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). - --> $DIR/lower_trait_where_clause.rs:16:1 - | -LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :- - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: FromEnv(S: std::fmt::Debug) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). - --> $DIR/lower_trait_where_clause.rs:16:1 - | -LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :- - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: FromEnv(T: std::borrow::Borrow<U>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). - --> $DIR/lower_trait_where_clause.rs:16:1 - | -LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :- - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: RegionOutlives('a : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). - --> $DIR/lower_trait_where_clause.rs:16:1 | -LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :- - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: TypeOutlives(U : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). - --> $DIR/lower_trait_where_clause.rs:16:1 - | -LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :- - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 7 previous errors + = note: FromEnv(S: std::fmt::Debug) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). + = note: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). + = note: FromEnv(T: std::borrow::Borrow<U>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). + = note: FromEnv(T: std::marker::Sized) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). + = note: Implemented(Self: Foo<'a, 'b, S, T, U>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). + = note: RegionOutlives('a : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). + = note: TypeOutlives(U : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). + +error: aborting due to previous error diff --git a/src/test/ui/closure-expected-type/expect-region-supply-region.nll.stderr b/src/test/ui/closure-expected-type/expect-region-supply-region.nll.stderr index 18edf2addc5..bbae80e16ab 100644 --- a/src/test/ui/closure-expected-type/expect-region-supply-region.nll.stderr +++ b/src/test/ui/closure-expected-type/expect-region-supply-region.nll.stderr @@ -1,22 +1,22 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/expect-region-supply-region.rs:28:13 | LL | f = Some(x); //~ ERROR borrowed data cannot be stored outside of its closure | ^^^^^^^ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/expect-region-supply-region.rs:38:13 | LL | f = Some(x); //~ ERROR borrowed data cannot be stored outside of its closure | ^^^^^^^ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/expect-region-supply-region.rs:47:33 | LL | closure_expecting_bound(|x: &'x u32| { | ^^^^^^^ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/expect-region-supply-region.rs:52:13 | LL | f = Some(x); diff --git a/src/test/ui/const-eval/conditional_array_execution.rs b/src/test/ui/const-eval/conditional_array_execution.rs index 324bcf60e8f..dbddee862e0 100644 --- a/src/test/ui/const-eval/conditional_array_execution.rs +++ b/src/test/ui/const-eval/conditional_array_execution.rs @@ -8,11 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-pass + const X: u32 = 5; const Y: u32 = 6; const FOO: u32 = [X - Y, Y - X][(X < Y) as usize]; //~^ WARN attempt to subtract with overflow +//~| WARN this constant cannot be used fn main() { - println!("{}", FOO); //~ E0080 + println!("{}", FOO); + //~^ WARN constant evaluation error } diff --git a/src/test/ui/const-eval/conditional_array_execution.stderr b/src/test/ui/const-eval/conditional_array_execution.stderr index 9270dafbe65..713b1b36c08 100644 --- a/src/test/ui/const-eval/conditional_array_execution.stderr +++ b/src/test/ui/const-eval/conditional_array_execution.stderr @@ -1,17 +1,20 @@ warning: attempt to subtract with overflow - --> $DIR/conditional_array_execution.rs:13:19 + --> $DIR/conditional_array_execution.rs:15:19 | LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize]; | ^^^^^ | = note: #[warn(const_err)] on by default -error[E0080]: constant evaluation error - --> $DIR/conditional_array_execution.rs:17:20 +warning: this constant cannot be used + --> $DIR/conditional_array_execution.rs:15:1 | -LL | println!("{}", FOO); //~ E0080 - | ^^^ referenced constant has errors +LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow -error: aborting due to previous error +warning: constant evaluation error + --> $DIR/conditional_array_execution.rs:20:20 + | +LL | println!("{}", FOO); + | ^^^ referenced constant has errors -For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/const-eval/const_signed_pat.rs b/src/test/ui/const-eval/const_signed_pat.rs new file mode 100644 index 00000000000..f53d6f3fa0a --- /dev/null +++ b/src/test/ui/const-eval/const_signed_pat.rs @@ -0,0 +1,19 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-pass + +fn main() { + const MIN: i8 = -5; + match 5i8 { + MIN...-1 => {}, + _ => {}, + } +} diff --git a/src/test/ui/const-eval/issue-43197.rs b/src/test/ui/const-eval/issue-43197.rs index d5c4796d0b4..097fba4d3c4 100644 --- a/src/test/ui/const-eval/issue-43197.rs +++ b/src/test/ui/const-eval/issue-43197.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-pass + #![feature(const_fn)] const fn foo(x: u32) -> u32 { @@ -17,9 +19,11 @@ const fn foo(x: u32) -> u32 { fn main() { const X: u32 = 0-1; //~^ WARN attempt to subtract with overflow + //~| WARN this constant cannot be used const Y: u32 = foo(0-1); //~^ WARN attempt to subtract with overflow + //~| WARN this constant cannot be used println!("{} {}", X, Y); - //~^ ERROR constant evaluation error - //~| ERROR constant evaluation error + //~^ WARN constant evaluation error + //~| WARN constant evaluation error } diff --git a/src/test/ui/const-eval/issue-43197.stderr b/src/test/ui/const-eval/issue-43197.stderr index 2d51e6603b5..a22e8016296 100644 --- a/src/test/ui/const-eval/issue-43197.stderr +++ b/src/test/ui/const-eval/issue-43197.stderr @@ -1,29 +1,38 @@ warning: attempt to subtract with overflow - --> $DIR/issue-43197.rs:18:20 + --> $DIR/issue-43197.rs:20:20 | LL | const X: u32 = 0-1; | ^^^ | = note: #[warn(const_err)] on by default -error[E0080]: constant evaluation error - --> $DIR/issue-43197.rs:22:23 +warning: this constant cannot be used + --> $DIR/issue-43197.rs:20:5 | -LL | println!("{} {}", X, Y); - | ^ referenced constant has errors +LL | const X: u32 = 0-1; + | ^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow warning: attempt to subtract with overflow - --> $DIR/issue-43197.rs:20:24 + --> $DIR/issue-43197.rs:23:24 | LL | const Y: u32 = foo(0-1); | ^^^ -error[E0080]: constant evaluation error - --> $DIR/issue-43197.rs:22:26 +warning: this constant cannot be used + --> $DIR/issue-43197.rs:23:5 + | +LL | const Y: u32 = foo(0-1); + | ^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow + +warning: constant evaluation error + --> $DIR/issue-43197.rs:26:23 | LL | println!("{} {}", X, Y); - | ^ referenced constant has errors + | ^ referenced constant has errors -error: aborting due to 2 previous errors +warning: constant evaluation error + --> $DIR/issue-43197.rs:26:26 + | +LL | println!("{} {}", X, Y); + | ^ referenced constant has errors -For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/compile-fail/issue-44578.rs b/src/test/ui/const-eval/issue-44578.rs index 18cfb35113d..765113cfbb9 100644 --- a/src/test/compile-fail/issue-44578.rs +++ b/src/test/ui/const-eval/issue-44578.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-pass + trait Foo { const AMT: usize; } @@ -30,5 +32,6 @@ impl Foo for u16 { } fn main() { - println!("{}", <Bar<u16, u8> as Foo>::AMT); //~ E0080 + println!("{}", <Bar<u16, u8> as Foo>::AMT); //~ WARN const_err + //~^ WARN const_err } diff --git a/src/test/ui/const-eval/issue-44578.stderr b/src/test/ui/const-eval/issue-44578.stderr new file mode 100644 index 00000000000..01c6fa3623f --- /dev/null +++ b/src/test/ui/const-eval/issue-44578.stderr @@ -0,0 +1,14 @@ +warning: constant evaluation error + --> $DIR/issue-44578.rs:35:20 + | +LL | println!("{}", <Bar<u16, u8> as Foo>::AMT); //~ WARN const_err + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors + | + = note: #[warn(const_err)] on by default + +warning: constant evaluation error + --> $DIR/issue-44578.rs:35:20 + | +LL | println!("{}", <Bar<u16, u8> as Foo>::AMT); //~ WARN const_err + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors + diff --git a/src/test/ui/const-eval/promoted_errors.rs b/src/test/ui/const-eval/promoted_errors.rs new file mode 100644 index 00000000000..dc30c7f9cce --- /dev/null +++ b/src/test/ui/const-eval/promoted_errors.rs @@ -0,0 +1,28 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-pass +// compile-flags: -O +fn main() { + println!("{}", 0u32 - 1); + //~^ WARN const_err + //~| WARN const_err + let _x = 0u32 - 1; + //~^ WARN const_err + println!("{}", 1/(1-1)); + //~^ WARN const_err + //~| WARN const_err + let _x = 1/(1-1); + //~^ WARN const_err + //~| WARN const_err + println!("{}", 1/(false as u32)); + //~^ WARN const_err + let _x = 1/(false as u32); +} diff --git a/src/test/ui/const-eval/promoted_errors.stderr b/src/test/ui/const-eval/promoted_errors.stderr new file mode 100644 index 00000000000..a5db8cc9083 --- /dev/null +++ b/src/test/ui/const-eval/promoted_errors.stderr @@ -0,0 +1,50 @@ +warning: constant evaluation error + --> $DIR/promoted_errors.rs:14:20 + | +LL | println!("{}", 0u32 - 1); + | ^^^^^^^^ attempted to do overflowing math + | + = note: #[warn(const_err)] on by default + +warning: constant evaluation error + --> $DIR/promoted_errors.rs:14:20 + | +LL | println!("{}", 0u32 - 1); + | ^^^^^^^^ attempted to do overflowing math + +warning: constant evaluation error + --> $DIR/promoted_errors.rs:17:14 + | +LL | let _x = 0u32 - 1; + | ^^^^^^^^ attempted to do overflowing math + +warning: attempt to divide by zero + --> $DIR/promoted_errors.rs:19:20 + | +LL | println!("{}", 1/(1-1)); + | ^^^^^^^ + +warning: constant evaluation error + --> $DIR/promoted_errors.rs:19:20 + | +LL | println!("{}", 1/(1-1)); + | ^^^^^^^ attempted to do overflowing math + +warning: attempt to divide by zero + --> $DIR/promoted_errors.rs:22:14 + | +LL | let _x = 1/(1-1); + | ^^^^^^^ + +warning: constant evaluation error + --> $DIR/promoted_errors.rs:22:14 + | +LL | let _x = 1/(1-1); + | ^^^^^^^ attempted to do overflowing math + +warning: constant evaluation error + --> $DIR/promoted_errors.rs:25:20 + | +LL | println!("{}", 1/(false as u32)); + | ^^^^^^^^^^^^^^^^ attempted to do overflowing math + diff --git a/src/test/ui/const-eval/pub_const_err.rs b/src/test/ui/const-eval/pub_const_err.rs index bdb9f5b19a8..c6bf07649af 100644 --- a/src/test/ui/const-eval/pub_const_err.rs +++ b/src/test/ui/const-eval/pub_const_err.rs @@ -8,9 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![deny(const_err)] +// compile-pass #![crate_type = "lib"] pub const Z: u32 = 0 - 1; -//~^ ERROR attempt to subtract with overflow +//~^ WARN attempt to subtract with overflow +//~| WARN this constant cannot be used + +pub type Foo = [i32; 0 - 1]; +//~^ WARN attempt to subtract with overflow +//~| WARN this array length cannot be used diff --git a/src/test/ui/const-eval/pub_const_err.stderr b/src/test/ui/const-eval/pub_const_err.stderr index b77ec38ca16..2981ac20cd9 100644 --- a/src/test/ui/const-eval/pub_const_err.stderr +++ b/src/test/ui/const-eval/pub_const_err.stderr @@ -1,14 +1,26 @@ -error: attempt to subtract with overflow +warning: attempt to subtract with overflow --> $DIR/pub_const_err.rs:15:20 | LL | pub const Z: u32 = 0 - 1; | ^^^^^ | -note: lint level defined here - --> $DIR/pub_const_err.rs:11:9 + = note: #[warn(const_err)] on by default + +warning: this constant cannot be used + --> $DIR/pub_const_err.rs:15:1 | -LL | #![deny(const_err)] - | ^^^^^^^^^ +LL | pub const Z: u32 = 0 - 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow -error: aborting due to previous error +warning: attempt to subtract with overflow + --> $DIR/pub_const_err.rs:19:22 + | +LL | pub type Foo = [i32; 0 - 1]; + | ^^^^^ + +warning: this array length cannot be used + --> $DIR/pub_const_err.rs:19:22 + | +LL | pub type Foo = [i32; 0 - 1]; + | ^^^^^ attempt to subtract with overflow diff --git a/src/test/ui/const-eval/pub_const_err_bin.rs b/src/test/ui/const-eval/pub_const_err_bin.rs new file mode 100644 index 00000000000..d87cb7ed770 --- /dev/null +++ b/src/test/ui/const-eval/pub_const_err_bin.rs @@ -0,0 +1,21 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-pass + +pub const Z: u32 = 0 - 1; +//~^ WARN attempt to subtract with overflow +//~| WARN this constant cannot be used + +pub type Foo = [i32; 0 - 1]; +//~^ WARN attempt to subtract with overflow +//~| WARN this array length cannot be used + +fn main() {} diff --git a/src/test/ui/const-eval/pub_const_err_bin.stderr b/src/test/ui/const-eval/pub_const_err_bin.stderr new file mode 100644 index 00000000000..3e8966d854b --- /dev/null +++ b/src/test/ui/const-eval/pub_const_err_bin.stderr @@ -0,0 +1,26 @@ +warning: attempt to subtract with overflow + --> $DIR/pub_const_err_bin.rs:13:20 + | +LL | pub const Z: u32 = 0 - 1; + | ^^^^^ + | + = note: #[warn(const_err)] on by default + +warning: this constant cannot be used + --> $DIR/pub_const_err_bin.rs:13:1 + | +LL | pub const Z: u32 = 0 - 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow + +warning: attempt to subtract with overflow + --> $DIR/pub_const_err_bin.rs:17:22 + | +LL | pub type Foo = [i32; 0 - 1]; + | ^^^^^ + +warning: this array length cannot be used + --> $DIR/pub_const_err_bin.rs:17:22 + | +LL | pub type Foo = [i32; 0 - 1]; + | ^^^^^ attempt to subtract with overflow + diff --git a/src/test/ui/const-fn-error.stderr b/src/test/ui/const-fn-error.stderr index 077c4d60e64..767f28ff7b1 100644 --- a/src/test/ui/const-fn-error.stderr +++ b/src/test/ui/const-fn-error.stderr @@ -4,7 +4,7 @@ error[E0016]: blocks in constant functions are limited to items and tail express LL | let mut sum = 0; | ^ -error[E0015]: calls in constant functions are limited to constant functions, struct and enum constructors +error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants --> $DIR/const-fn-error.rs:18:14 | LL | for i in 0..x { diff --git a/src/test/ui/did_you_mean/issue-34126.nll.stderr b/src/test/ui/did_you_mean/issue-34126.nll.stderr index afdc26a75c7..81f858f6bfc 100644 --- a/src/test/ui/did_you_mean/issue-34126.nll.stderr +++ b/src/test/ui/did_you_mean/issue-34126.nll.stderr @@ -1,3 +1,9 @@ +error[E0596]: cannot borrow immutable item `self` as mutable + --> $DIR/issue-34126.rs:16:18 + | +LL | self.run(&mut self); //~ ERROR cannot borrow + | ^^^^^^^^^ cannot borrow as mutable + error[E0502]: cannot borrow `self` as mutable because it is also borrowed as immutable --> $DIR/issue-34126.rs:16:18 | @@ -8,6 +14,7 @@ LL | self.run(&mut self); //~ ERROR cannot borrow | immutable borrow occurs here | borrow later used here -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0502`. +Some errors occurred: E0502, E0596. +For more information about an error, try `rustc --explain E0502`. diff --git a/src/test/ui/did_you_mean/issue-35937.nll.stderr b/src/test/ui/did_you_mean/issue-35937.nll.stderr index 7b5f452d322..40b640b63cf 100644 --- a/src/test/ui/did_you_mean/issue-35937.nll.stderr +++ b/src/test/ui/did_you_mean/issue-35937.nll.stderr @@ -4,7 +4,7 @@ error[E0596]: cannot borrow immutable item `f.v` as mutable LL | f.v.push("cat".to_string()); //~ ERROR cannot borrow | ^^^ cannot borrow as mutable | - = note: Value not mutable causing this error: `f` + = note: the value which is causing this path not to be mutable is...: `f` error[E0384]: cannot assign twice to immutable variable `s.x` --> $DIR/issue-35937.rs:26:5 diff --git a/src/test/ui/did_you_mean/issue-38147-1.nll.stderr b/src/test/ui/did_you_mean/issue-38147-1.nll.stderr index 099479eaf2b..8e442677951 100644 --- a/src/test/ui/did_you_mean/issue-38147-1.nll.stderr +++ b/src/test/ui/did_you_mean/issue-38147-1.nll.stderr @@ -4,7 +4,7 @@ error[E0596]: cannot borrow immutable item `*self.s` as mutable LL | self.s.push('x'); //~ ERROR cannot borrow data mutably | ^^^^^^ cannot borrow as mutable | - = note: Value not mutable causing this error: `*self` + = note: the value which is causing this path not to be mutable is...: `*self` error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-38147-4.nll.stderr b/src/test/ui/did_you_mean/issue-38147-4.nll.stderr index 5649fc903a0..6808222cc32 100644 --- a/src/test/ui/did_you_mean/issue-38147-4.nll.stderr +++ b/src/test/ui/did_you_mean/issue-38147-4.nll.stderr @@ -4,7 +4,7 @@ error[E0596]: cannot borrow immutable item `*f.s` as mutable LL | f.s.push('x'); //~ ERROR cannot borrow data mutably | ^^^ cannot borrow as mutable | - = note: Value not mutable causing this error: `*f` + = note: the value which is causing this path not to be mutable is...: `*f` error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-39544.nll.stderr b/src/test/ui/did_you_mean/issue-39544.nll.stderr index 6e57796aa45..f5f5b675e77 100644 --- a/src/test/ui/did_you_mean/issue-39544.nll.stderr +++ b/src/test/ui/did_you_mean/issue-39544.nll.stderr @@ -4,7 +4,7 @@ error[E0596]: cannot borrow immutable item `z.x` as mutable LL | let _ = &mut z.x; //~ ERROR cannot borrow | ^^^^^^^^ cannot borrow as mutable | - = note: Value not mutable causing this error: `z` + = note: the value which is causing this path not to be mutable is...: `z` error[E0596]: cannot borrow immutable item `self.x` as mutable --> $DIR/issue-39544.rs:26:17 @@ -12,7 +12,7 @@ error[E0596]: cannot borrow immutable item `self.x` as mutable LL | let _ = &mut self.x; //~ ERROR cannot borrow | ^^^^^^^^^^^ cannot borrow as mutable | - = note: Value not mutable causing this error: `*self` + = note: the value which is causing this path not to be mutable is...: `*self` error[E0596]: cannot borrow immutable item `self.x` as mutable --> $DIR/issue-39544.rs:30:17 @@ -20,7 +20,7 @@ error[E0596]: cannot borrow immutable item `self.x` as mutable LL | let _ = &mut self.x; //~ ERROR cannot borrow | ^^^^^^^^^^^ cannot borrow as mutable | - = note: Value not mutable causing this error: `*self` + = note: the value which is causing this path not to be mutable is...: `*self` error[E0596]: cannot borrow immutable item `other.x` as mutable --> $DIR/issue-39544.rs:31:17 @@ -28,7 +28,7 @@ error[E0596]: cannot borrow immutable item `other.x` as mutable LL | let _ = &mut other.x; //~ ERROR cannot borrow | ^^^^^^^^^^^^ cannot borrow as mutable | - = note: Value not mutable causing this error: `*other` + = note: the value which is causing this path not to be mutable is...: `*other` error[E0596]: cannot borrow immutable item `self.x` as mutable --> $DIR/issue-39544.rs:35:17 @@ -36,7 +36,7 @@ error[E0596]: cannot borrow immutable item `self.x` as mutable LL | let _ = &mut self.x; //~ ERROR cannot borrow | ^^^^^^^^^^^ cannot borrow as mutable | - = note: Value not mutable causing this error: `*self` + = note: the value which is causing this path not to be mutable is...: `*self` error[E0596]: cannot borrow immutable item `other.x` as mutable --> $DIR/issue-39544.rs:36:17 @@ -44,7 +44,7 @@ error[E0596]: cannot borrow immutable item `other.x` as mutable LL | let _ = &mut other.x; //~ ERROR cannot borrow | ^^^^^^^^^^^^ cannot borrow as mutable | - = note: Value not mutable causing this error: `*other` + = note: the value which is causing this path not to be mutable is...: `*other` error[E0596]: cannot borrow immutable item `self.x` as mutable --> $DIR/issue-39544.rs:40:17 @@ -52,7 +52,7 @@ error[E0596]: cannot borrow immutable item `self.x` as mutable LL | let _ = &mut self.x; //~ ERROR cannot borrow | ^^^^^^^^^^^ cannot borrow as mutable | - = note: Value not mutable causing this error: `*self` + = note: the value which is causing this path not to be mutable is...: `*self` error[E0596]: cannot borrow immutable item `other.x` as mutable --> $DIR/issue-39544.rs:41:17 @@ -60,7 +60,7 @@ error[E0596]: cannot borrow immutable item `other.x` as mutable LL | let _ = &mut other.x; //~ ERROR cannot borrow | ^^^^^^^^^^^^ cannot borrow as mutable | - = note: Value not mutable causing this error: `*other` + = note: the value which is causing this path not to be mutable is...: `*other` error[E0596]: cannot borrow immutable item `other.x` as mutable --> $DIR/issue-39544.rs:45:17 @@ -68,7 +68,7 @@ error[E0596]: cannot borrow immutable item `other.x` as mutable LL | let _ = &mut other.x; //~ ERROR cannot borrow | ^^^^^^^^^^^^ cannot borrow as mutable | - = note: Value not mutable causing this error: `*other` + = note: the value which is causing this path not to be mutable is...: `*other` error[E0596]: cannot borrow immutable item `z.x` as mutable --> $DIR/issue-39544.rs:51:13 @@ -76,7 +76,7 @@ error[E0596]: cannot borrow immutable item `z.x` as mutable LL | let _ = &mut z.x; //~ ERROR cannot borrow | ^^^^^^^^ cannot borrow as mutable | - = note: Value not mutable causing this error: `z` + = note: the value which is causing this path not to be mutable is...: `z` error[E0596]: cannot borrow immutable item `w.x` as mutable --> $DIR/issue-39544.rs:52:13 @@ -84,7 +84,7 @@ error[E0596]: cannot borrow immutable item `w.x` as mutable LL | let _ = &mut w.x; //~ ERROR cannot borrow | ^^^^^^^^ cannot borrow as mutable | - = note: Value not mutable causing this error: `*w` + = note: the value which is causing this path not to be mutable is...: `*w` error[E0594]: cannot assign to immutable item `*x.0` --> $DIR/issue-39544.rs:58:5 diff --git a/src/test/ui/e0119/conflict-with-std.rs b/src/test/ui/e0119/conflict-with-std.rs index a9f747d09ec..ed9033ad53d 100644 --- a/src/test/ui/e0119/conflict-with-std.rs +++ b/src/test/ui/e0119/conflict-with-std.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(try_from)] + use std::marker::PhantomData; use std::convert::{TryFrom, AsRef}; diff --git a/src/test/ui/e0119/conflict-with-std.stderr b/src/test/ui/e0119/conflict-with-std.stderr index 417ff1de3f8..e8b2c84c0df 100644 --- a/src/test/ui/e0119/conflict-with-std.stderr +++ b/src/test/ui/e0119/conflict-with-std.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `std::convert::AsRef<Q>` for type `std::boxed::Box<Q>`: - --> $DIR/conflict-with-std.rs:15:1 + --> $DIR/conflict-with-std.rs:17:1 | LL | impl AsRef<Q> for Box<Q> { //~ ERROR conflicting implementations | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | impl AsRef<Q> for Box<Q> { //~ ERROR conflicting implementations where T: ?Sized; error[E0119]: conflicting implementations of trait `std::convert::From<S>` for type `S`: - --> $DIR/conflict-with-std.rs:22:1 + --> $DIR/conflict-with-std.rs:24:1 | LL | impl From<S> for S { //~ ERROR conflicting implementations | ^^^^^^^^^^^^^^^^^^ @@ -18,7 +18,7 @@ LL | impl From<S> for S { //~ ERROR conflicting implementations - impl<T> std::convert::From<T> for T; error[E0119]: conflicting implementations of trait `std::convert::TryFrom<X>` for type `X`: - --> $DIR/conflict-with-std.rs:29:1 + --> $DIR/conflict-with-std.rs:31:1 | LL | impl TryFrom<X> for X { //~ ERROR conflicting implementations | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/edition-lint-paths.rs b/src/test/ui/edition-lint-paths.rs new file mode 100644 index 00000000000..0b49e72ccd9 --- /dev/null +++ b/src/test/ui/edition-lint-paths.rs @@ -0,0 +1,41 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(crate_in_paths)] +#![deny(absolute_path_starting_with_module)] +#![allow(unused)] + +pub mod foo { + use ::bar::Bar; + //~^ ERROR Absolute + //~| WARN this was previously accepted + use super::bar::Bar2; + use crate::bar::Bar3; +} + + +use bar::Bar; +//~^ ERROR Absolute +//~| WARN this was previously accepted + +pub mod bar { + pub struct Bar; + pub type Bar2 = Bar; + pub type Bar3 = Bar; +} + +fn main() { + let x = ::bar::Bar; + //~^ ERROR Absolute + //~| WARN this was previously accepted + let x = bar::Bar; + let x = ::crate::bar::Bar; + let x = self::bar::Bar; +} diff --git a/src/test/ui/edition-lint-paths.stderr b/src/test/ui/edition-lint-paths.stderr new file mode 100644 index 00000000000..509527e0374 --- /dev/null +++ b/src/test/ui/edition-lint-paths.stderr @@ -0,0 +1,34 @@ +error: Absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition + --> $DIR/edition-lint-paths.rs:16:9 + | +LL | use ::bar::Bar; + | ^^^^^^^^^^ help: use `crate`: `crate::bar::Bar` + | +note: lint level defined here + --> $DIR/edition-lint-paths.rs:12:9 + | +LL | #![deny(absolute_path_starting_with_module)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = note: for more information, see issue TBD + +error: Absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition + --> $DIR/edition-lint-paths.rs:24:5 + | +LL | use bar::Bar; + | ^^^^^^^^ help: use `crate`: `crate::bar::Bar` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = note: for more information, see issue TBD + +error: Absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition + --> $DIR/edition-lint-paths.rs:35:13 + | +LL | let x = ::bar::Bar; + | ^^^^^^^^^^ help: use `crate`: `crate::bar::Bar` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = note: for more information, see issue TBD + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/error-codes/E0389.nll.stderr b/src/test/ui/error-codes/E0389.nll.stderr index 13ba653a5ca..0525e16239d 100644 --- a/src/test/ui/error-codes/E0389.nll.stderr +++ b/src/test/ui/error-codes/E0389.nll.stderr @@ -1,10 +1,10 @@ -error[E0594]: cannot assign to immutable item `fancy_ref.num` +error[E0594]: cannot assign to data in a `&` reference --> $DIR/E0389.rs:18:5 | +LL | let fancy_ref = &(&mut fancy); + | ------------- help: consider changing this to be a mutable reference: `&mut (&mut fancy)` LL | fancy_ref.num = 6; //~ ERROR E0389 - | ^^^^^^^^^^^^^^^^^ cannot mutate - | - = note: Value not mutable causing this error: `*fancy_ref` + | ^^^^^^^^^^^^^^^^^ `fancy_ref` is a `&` reference, so the data it refers to cannot be written error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.nll.stderr b/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.nll.stderr index e9f09795691..5ae6afa7b17 100644 --- a/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.nll.stderr +++ b/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/E0621-does-not-trigger-for-closures.rs:25:5 | LL | invoke(&x, |a, b| if a > b { a } else { b }); //~ ERROR E0495 diff --git a/src/test/ui/feature-gate-doc_alias.rs b/src/test/ui/feature-gate-doc_alias.rs new file mode 100644 index 00000000000..1503dfe81fb --- /dev/null +++ b/src/test/ui/feature-gate-doc_alias.rs @@ -0,0 +1,14 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[doc(alias = "foo")] //~ ERROR: #[doc(alias = "...")] is experimental +pub struct Foo; + +fn main() {} diff --git a/src/test/ui/feature-gate-doc_alias.stderr b/src/test/ui/feature-gate-doc_alias.stderr new file mode 100644 index 00000000000..a987e03c0aa --- /dev/null +++ b/src/test/ui/feature-gate-doc_alias.stderr @@ -0,0 +1,11 @@ +error[E0658]: #[doc(alias = "...")] is experimental (see issue #50146) + --> $DIR/feature-gate-doc_alias.rs:11:1 + | +LL | #[doc(alias = "foo")] //~ ERROR: #[doc(alias = "...")] is experimental + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(doc_alias)] to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-exhaustive-patterns.rs b/src/test/ui/feature-gate-exhaustive-patterns.rs index 477dd1b38eb..c83d9b56bc3 100644 --- a/src/test/ui/feature-gate-exhaustive-patterns.rs +++ b/src/test/ui/feature-gate-exhaustive-patterns.rs @@ -7,7 +7,7 @@ // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. - +#![feature(never_type)] fn foo() -> Result<u32, !> { Ok(123) } diff --git a/src/test/ui/feature-gate-generic_associated_types.rs b/src/test/ui/feature-gate-generic_associated_types.rs index 724ec2496f2..34706626866 100644 --- a/src/test/ui/feature-gate-generic_associated_types.rs +++ b/src/test/ui/feature-gate-generic_associated_types.rs @@ -15,6 +15,7 @@ trait PointerFamily<U> { //~^ ERROR generic associated types are unstable type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone; //~^ ERROR generic associated types are unstable + //~| ERROR where clauses on associated types are unstable } struct Foo; @@ -25,4 +26,10 @@ impl PointerFamily<u32> for Foo { //~^ ERROR generic associated types are unstable } +trait Bar { + type Assoc where Self: Sized; + //~^ ERROR where clauses on associated types are unstable +} + + fn main() {} diff --git a/src/test/ui/feature-gate-generic_associated_types.stderr b/src/test/ui/feature-gate-generic_associated_types.stderr index 5f23def88eb..d7891f13c6b 100644 --- a/src/test/ui/feature-gate-generic_associated_types.stderr +++ b/src/test/ui/feature-gate-generic_associated_types.stderr @@ -14,8 +14,16 @@ LL | type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone; | = help: add #![feature(generic_associated_types)] to the crate attributes to enable +error[E0658]: where clauses on associated types are unstable (see issue #44265) + --> $DIR/feature-gate-generic_associated_types.rs:16:5 + | +LL | type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(generic_associated_types)] to the crate attributes to enable + error[E0658]: generic associated types are unstable (see issue #44265) - --> $DIR/feature-gate-generic_associated_types.rs:22:5 + --> $DIR/feature-gate-generic_associated_types.rs:23:5 | LL | type Pointer<usize> = Box<usize>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -23,13 +31,21 @@ LL | type Pointer<usize> = Box<usize>; = help: add #![feature(generic_associated_types)] to the crate attributes to enable error[E0658]: generic associated types are unstable (see issue #44265) - --> $DIR/feature-gate-generic_associated_types.rs:24:5 + --> $DIR/feature-gate-generic_associated_types.rs:25:5 | LL | type Pointer2<u32> = Box<u32>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add #![feature(generic_associated_types)] to the crate attributes to enable -error: aborting due to 4 previous errors +error[E0658]: where clauses on associated types are unstable (see issue #44265) + --> $DIR/feature-gate-generic_associated_types.rs:30:5 + | +LL | type Assoc where Self: Sized; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(generic_associated_types)] to the crate attributes to enable + +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-never_type.rs b/src/test/ui/feature-gate-never_type.rs new file mode 100644 index 00000000000..ebbe17a821f --- /dev/null +++ b/src/test/ui/feature-gate-never_type.rs @@ -0,0 +1,27 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that ! errors when used in illegal positions with feature(never_type) disabled + +trait Foo { + type Wub; +} + +type Ma = (u32, !, i32); //~ ERROR type is experimental +type Meeshka = Vec<!>; //~ ERROR type is experimental +type Mow = &fn(!) -> !; //~ ERROR type is experimental +type Skwoz = &mut !; //~ ERROR type is experimental + +impl Foo for Meeshka { + type Wub = !; //~ ERROR type is experimental +} + +fn main() { +} diff --git a/src/test/ui/feature-gate-never_type.stderr b/src/test/ui/feature-gate-never_type.stderr new file mode 100644 index 00000000000..187be6d8291 --- /dev/null +++ b/src/test/ui/feature-gate-never_type.stderr @@ -0,0 +1,43 @@ +error[E0658]: The `!` type is experimental (see issue #35121) + --> $DIR/feature-gate-never_type.rs:17:17 + | +LL | type Ma = (u32, !, i32); //~ ERROR type is experimental + | ^ + | + = help: add #![feature(never_type)] to the crate attributes to enable + +error[E0658]: The `!` type is experimental (see issue #35121) + --> $DIR/feature-gate-never_type.rs:18:20 + | +LL | type Meeshka = Vec<!>; //~ ERROR type is experimental + | ^ + | + = help: add #![feature(never_type)] to the crate attributes to enable + +error[E0658]: The `!` type is experimental (see issue #35121) + --> $DIR/feature-gate-never_type.rs:19:16 + | +LL | type Mow = &fn(!) -> !; //~ ERROR type is experimental + | ^ + | + = help: add #![feature(never_type)] to the crate attributes to enable + +error[E0658]: The `!` type is experimental (see issue #35121) + --> $DIR/feature-gate-never_type.rs:20:19 + | +LL | type Skwoz = &mut !; //~ ERROR type is experimental + | ^ + | + = help: add #![feature(never_type)] to the crate attributes to enable + +error[E0658]: The `!` type is experimental (see issue #35121) + --> $DIR/feature-gate-never_type.rs:23:16 + | +LL | type Wub = !; //~ ERROR type is experimental + | ^ + | + = help: add #![feature(never_type)] to the crate attributes to enable + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate/issue-49983-see-issue-0.rs b/src/test/ui/feature-gate/issue-49983-see-issue-0.rs new file mode 100644 index 00000000000..1e0039aba04 --- /dev/null +++ b/src/test/ui/feature-gate/issue-49983-see-issue-0.rs @@ -0,0 +1,16 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate core; + +// error should not say "(see issue #0)" +#[allow(unused_imports)] use core::ptr::Unique; //~ ERROR use of unstable library feature + +fn main() {} diff --git a/src/test/ui/feature-gate/issue-49983-see-issue-0.stderr b/src/test/ui/feature-gate/issue-49983-see-issue-0.stderr new file mode 100644 index 00000000000..986a2d88e00 --- /dev/null +++ b/src/test/ui/feature-gate/issue-49983-see-issue-0.stderr @@ -0,0 +1,11 @@ +error[E0658]: use of unstable library feature 'ptr_internals': use NonNull instead and consider PhantomData<T> (if you also use #[may_dangle]), Send, and/or Sync + --> $DIR/issue-49983-see-issue-0.rs:14:30 + | +LL | #[allow(unused_imports)] use core::ptr::Unique; //~ ERROR use of unstable library feature + | ^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(ptr_internals)] to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/hygiene/fields-move.nll.stderr b/src/test/ui/hygiene/fields-move.nll.stderr new file mode 100644 index 00000000000..51f8067b8ce --- /dev/null +++ b/src/test/ui/hygiene/fields-move.nll.stderr @@ -0,0 +1,46 @@ +error[E0382]: use of moved value: `foo.x` + --> $DIR/fields-move.rs:38:42 + | +LL | $foo.x + | ------ value moved here +... +LL | assert_two_copies(copy_modern!(foo), foo.x); //~ ERROR use of moved value: `foo.x` + | ^^^^^ value used here after move + | + = note: move occurs because `foo.x` has type `NonCopy`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `foo.x` + --> $DIR/fields-move.rs:28:9 + | +LL | $foo.x + | ------ value moved here +... +LL | $foo.x //~ ERROR use of moved value: `foo.x` + | ^^^^^^ value used here after move +... +LL | assert_two_copies(copy_modern!(foo), foo.x); //~ ERROR use of moved value: `foo.x` + | ----- value moved here +LL | assert_two_copies(copy_legacy!(foo), foo.x); //~ ERROR use of moved value: `foo.x` + | ----------------- in this macro invocation + | + = note: move occurs because `foo.x` has type `NonCopy`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `foo.x` + --> $DIR/fields-move.rs:39:42 + | +LL | $foo.x + | ------ value moved here +... +LL | $foo.x //~ ERROR use of moved value: `foo.x` + | ------ value moved here +... +LL | assert_two_copies(copy_modern!(foo), foo.x); //~ ERROR use of moved value: `foo.x` + | ----- value moved here +LL | assert_two_copies(copy_legacy!(foo), foo.x); //~ ERROR use of moved value: `foo.x` + | ^^^^^ value used here after move + | + = note: move occurs because `foo.x` has type `NonCopy`, which does not implement the `Copy` trait + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/hygiene/fields-numeric-borrowck.nll.stderr b/src/test/ui/hygiene/fields-numeric-borrowck.nll.stderr new file mode 100644 index 00000000000..3a0a6f66d61 --- /dev/null +++ b/src/test/ui/hygiene/fields-numeric-borrowck.nll.stderr @@ -0,0 +1,13 @@ +error: compilation successful + --> $DIR/fields-numeric-borrowck.rs:13:1 + | +LL | / fn main() { #![rustc_error] // rust-lang/rust#49855 +LL | | let mut s = S(0); +LL | | let borrow1 = &mut s.0; +LL | | let S { 0: ref mut borrow2 } = s; +LL | | //~^ ERROR cannot borrow `s.0` as mutable more than once at a time +LL | | } + | |_^ + +error: aborting due to previous error + diff --git a/src/test/ui/hygiene/fields-numeric-borrowck.rs b/src/test/ui/hygiene/fields-numeric-borrowck.rs index 50ace39e709..975684fbd41 100644 --- a/src/test/ui/hygiene/fields-numeric-borrowck.rs +++ b/src/test/ui/hygiene/fields-numeric-borrowck.rs @@ -7,10 +7,10 @@ // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. - +#![feature(rustc_attrs)] struct S(u8); -fn main() { +fn main() { #![rustc_error] // rust-lang/rust#49855 let mut s = S(0); let borrow1 = &mut s.0; let S { 0: ref mut borrow2 } = s; diff --git a/src/test/ui/hygiene/fields.rs b/src/test/ui/hygiene/fields.rs index 64217770b13..ed155b28037 100644 --- a/src/test/ui/hygiene/fields.rs +++ b/src/test/ui/hygiene/fields.rs @@ -10,7 +10,7 @@ // ignore-pretty pretty-printing is unhygienic -#![feature(decl_macro)] +#![feature(decl_macro, proc_macro_path_invoc)] mod foo { struct S { x: u32 } diff --git a/src/test/ui/hygiene/globs.rs b/src/test/ui/hygiene/globs.rs index 7ba217061c6..f3f400aafeb 100644 --- a/src/test/ui/hygiene/globs.rs +++ b/src/test/ui/hygiene/globs.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(decl_macro)] +#![feature(decl_macro, proc_macro_path_invoc)] mod foo { pub fn f() {} diff --git a/src/test/ui/hygiene/impl_items.rs b/src/test/ui/hygiene/impl_items.rs index cdba559445d..4f997a790e6 100644 --- a/src/test/ui/hygiene/impl_items.rs +++ b/src/test/ui/hygiene/impl_items.rs @@ -10,7 +10,7 @@ // ignore-pretty pretty-printing is unhygienic -#![feature(decl_macro)] +#![feature(decl_macro, proc_macro_path_invoc)] mod foo { struct S; diff --git a/src/test/ui/hygiene/intercrate.rs b/src/test/ui/hygiene/intercrate.rs index 50fc985ba34..20ca918f026 100644 --- a/src/test/ui/hygiene/intercrate.rs +++ b/src/test/ui/hygiene/intercrate.rs @@ -14,7 +14,7 @@ // error-pattern:type `fn() -> u32 {intercrate::foo::bar::f}` is private -#![feature(decl_macro)] +#![feature(decl_macro, proc_macro_path_invoc)] extern crate intercrate; diff --git a/src/test/ui/hygiene/no_implicit_prelude.rs b/src/test/ui/hygiene/no_implicit_prelude.rs index c90c7b3093c..ea6a45fba6a 100644 --- a/src/test/ui/hygiene/no_implicit_prelude.rs +++ b/src/test/ui/hygiene/no_implicit_prelude.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(decl_macro)] +#![feature(decl_macro, proc_macro_path_invoc)] mod foo { pub macro m() { Vec::new(); ().clone() } diff --git a/src/test/ui/hygiene/privacy.rs b/src/test/ui/hygiene/privacy.rs index 987cad187d4..8a392db92f9 100644 --- a/src/test/ui/hygiene/privacy.rs +++ b/src/test/ui/hygiene/privacy.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(decl_macro)] +#![feature(decl_macro, proc_macro_path_invoc)] mod foo { fn f() {} diff --git a/src/test/ui/hygiene/trait_items.rs b/src/test/ui/hygiene/trait_items.rs index 3bd19cbc0ac..d0da6254b9b 100644 --- a/src/test/ui/hygiene/trait_items.rs +++ b/src/test/ui/hygiene/trait_items.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(decl_macro)] +#![feature(decl_macro, proc_macro_path_invoc)] mod foo { pub trait T { 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 438d29f0535..f7aaab4242c 100644 --- a/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr +++ b/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr @@ -8,10 +8,8 @@ LL | foo(|s| s.is_empty()); | ^^^^^^^^ | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following traits define an item `is_empty`, perhaps you need to implement one of them: + = note: the following trait defines an item `is_empty`, perhaps you need to implement it: candidate #1: `std::iter::ExactSizeIterator` - candidate #2: `core::slice::SliceExt` - candidate #3: `core::str::StrExt` error: aborting due to previous error diff --git a/src/test/ui/imports/macro-paths.rs b/src/test/ui/imports/macro-paths.rs index e709eeee14a..51e5257be1b 100644 --- a/src/test/ui/imports/macro-paths.rs +++ b/src/test/ui/imports/macro-paths.rs @@ -10,7 +10,7 @@ // aux-build:two_macros.rs -#![feature(use_extern_macros)] +#![feature(use_extern_macros, proc_macro_path_invoc)] extern crate two_macros; diff --git a/src/test/ui/imports/shadow_builtin_macros.rs b/src/test/ui/imports/shadow_builtin_macros.rs index 93de136c405..aad0a43be26 100644 --- a/src/test/ui/imports/shadow_builtin_macros.rs +++ b/src/test/ui/imports/shadow_builtin_macros.rs @@ -10,7 +10,7 @@ // aux-build:two_macros.rs -#![feature(use_extern_macros)] +#![feature(use_extern_macros, proc_macro_path_invoc)] mod foo { extern crate two_macros; diff --git a/src/test/ui/in-band-lifetimes/impl/dyn-trait.nll.stderr b/src/test/ui/in-band-lifetimes/impl/dyn-trait.nll.stderr index 34ee39c7164..ec8c4ecf102 100644 --- a/src/test/ui/in-band-lifetimes/impl/dyn-trait.nll.stderr +++ b/src/test/ui/in-band-lifetimes/impl/dyn-trait.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/dyn-trait.rs:33:16 | LL | static_val(x); //~ ERROR cannot infer diff --git a/src/test/ui/in-band-lifetimes/mismatched.nll.stderr b/src/test/ui/in-band-lifetimes/mismatched.nll.stderr index 0930583a7ee..cd2ebc341ea 100644 --- a/src/test/ui/in-band-lifetimes/mismatched.nll.stderr +++ b/src/test/ui/in-band-lifetimes/mismatched.nll.stderr @@ -1,10 +1,10 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/mismatched.rs:14:42 | LL | fn foo(x: &'a u32, y: &u32) -> &'a u32 { y } //~ ERROR explicit lifetime required | ^ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/mismatched.rs:16:46 | LL | fn foo2(x: &'a u32, y: &'b u32) -> &'a u32 { y } //~ ERROR lifetime mismatch diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait.nll.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait.nll.stderr index 5e42cab9974..886e3834d1d 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait.nll.stderr +++ b/src/test/ui/in-band-lifetimes/mismatched_trait.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/mismatched_trait.rs:16:9 | LL | y //~ ERROR explicit lifetime required diff --git a/src/test/ui/issue-13058.nll.stderr b/src/test/ui/issue-13058.nll.stderr index 604ad38ad23..146385f3de2 100644 --- a/src/test/ui/issue-13058.nll.stderr +++ b/src/test/ui/issue-13058.nll.stderr @@ -1,10 +1,10 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/issue-13058.rs:24:21 | LL | let cont_iter = cont.iter(); | ^^^^ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/issue-13058.rs:24:26 | LL | let cont_iter = cont.iter(); diff --git a/src/test/ui/issue-36400.nll.stderr b/src/test/ui/issue-36400.nll.stderr index 040e6300af6..80459937479 100644 --- a/src/test/ui/issue-36400.nll.stderr +++ b/src/test/ui/issue-36400.nll.stderr @@ -4,7 +4,7 @@ error[E0596]: cannot borrow immutable item `*x` as mutable LL | f(&mut *x); //~ ERROR cannot borrow immutable | ^^^^^^^ cannot borrow as mutable | - = note: Value not mutable causing this error: `x` + = note: the value which is causing this path not to be mutable is...: `x` error: aborting due to previous error diff --git a/src/test/ui/issue-45697-1.nll.stderr b/src/test/ui/issue-45697-1.nll.stderr deleted file mode 100644 index cf108691a0e..00000000000 --- a/src/test/ui/issue-45697-1.nll.stderr +++ /dev/null @@ -1,34 +0,0 @@ -error[E0506]: cannot assign to `*y.pointer` because it is borrowed (Ast) - --> $DIR/issue-45697-1.rs:30:9 - | -LL | let z = copy_borrowed_ptr(&mut y); - | - borrow of `*y.pointer` occurs here -LL | *y.pointer += 1; - | ^^^^^^^^^^^^^^^ assignment to borrowed `*y.pointer` occurs here - -error[E0503]: cannot use `*y.pointer` because it was mutably borrowed (Mir) - --> $DIR/issue-45697-1.rs:30:9 - | -LL | let z = copy_borrowed_ptr(&mut y); - | ------ borrow of `y` occurs here -LL | *y.pointer += 1; - | ^^^^^^^^^^^^^^^ use of borrowed `y` -... -LL | *z.pointer += 1; - | --------------- borrow later used here - -error[E0506]: cannot assign to `*y.pointer` because it is borrowed (Mir) - --> $DIR/issue-45697-1.rs:30:9 - | -LL | let z = copy_borrowed_ptr(&mut y); - | ------ borrow of `*y.pointer` occurs here -LL | *y.pointer += 1; - | ^^^^^^^^^^^^^^^ assignment to borrowed `*y.pointer` occurs here -... -LL | *z.pointer += 1; - | --------------- borrow later used here - -error: aborting due to 3 previous errors - -Some errors occurred: E0503, E0506. -For more information about an error, try `rustc --explain E0503`. diff --git a/src/test/ui/issue-46471-1.nll.stderr b/src/test/ui/issue-46471-1.nll.stderr deleted file mode 100644 index 0108056bc72..00000000000 --- a/src/test/ui/issue-46471-1.nll.stderr +++ /dev/null @@ -1,28 +0,0 @@ -error[E0597]: `z` does not live long enough (Ast) - --> $DIR/issue-46471-1.rs:16:14 - | -LL | &mut z - | ^ borrowed value does not live long enough -LL | }; - | - `z` dropped here while still borrowed -... -LL | } - | - borrowed value needs to live until here - -error[E0597]: `z` does not live long enough (Mir) - --> $DIR/issue-46471-1.rs:16:9 - | -LL | let y = { - | _____________- -LL | | let mut z = 0; -LL | | &mut z - | | ^^^^^^ borrowed value does not live long enough -LL | | }; - | | - - | | | - | |_____borrowed value only lives until here - | borrow later used here - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/issue-48636.rs b/src/test/ui/issue-48636.rs new file mode 100644 index 00000000000..03e45d88e6c --- /dev/null +++ b/src/test/ui/issue-48636.rs @@ -0,0 +1,17 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct S { + x: u8 + /// The id of the parent core + y: u8, +} +//~^^^ ERROR found a documentation comment that doesn't document anything +fn main() {} diff --git a/src/test/ui/issue-48636.stderr b/src/test/ui/issue-48636.stderr new file mode 100644 index 00000000000..4e014a5bd1d --- /dev/null +++ b/src/test/ui/issue-48636.stderr @@ -0,0 +1,13 @@ +error[E0585]: found a documentation comment that doesn't document anything + --> $DIR/issue-48636.rs:13:5 + | +LL | x: u8 + | - help: missing comma here: `,` +LL | /// The id of the parent core + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: doc comments must come before what they document, maybe a comment was intended with `//`? + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0585`. diff --git a/src/test/ui/lifetime-errors/42701_one_named_and_one_anonymous.nll.stderr b/src/test/ui/lifetime-errors/42701_one_named_and_one_anonymous.nll.stderr index 62ccea36bd3..d422a63bcad 100644 --- a/src/test/ui/lifetime-errors/42701_one_named_and_one_anonymous.nll.stderr +++ b/src/test/ui/lifetime-errors/42701_one_named_and_one_anonymous.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/42701_one_named_and_one_anonymous.rs:20:9 | LL | &*x //~ ERROR explicit lifetime diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.nll.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.nll.stderr index 78546594ef0..5451562cdfb 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.nll.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex1-return-one-existing-name-early-bound-in-struct.rs:21:21 | LL | other //~ ERROR explicit lifetime diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.nll.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.nll.stderr index 11bb1df3c78..e1dfeb0ac6a 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.nll.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex1-return-one-existing-name-if-else-2.rs:12:16 | LL | if x > y { x } else { y } //~ ERROR explicit lifetime diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.nll.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.nll.stderr index a619e6ca964..1e45914138d 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.nll.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex1-return-one-existing-name-if-else-3.rs:12:27 | LL | if x > y { x } else { y } //~ ERROR explicit lifetime diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.nll.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.nll.stderr index 92245173ce8..e264b3428c9 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.nll.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex1-return-one-existing-name-if-else-using-impl-2.rs:14:15 | LL | if x > y { x } else { y } //~ ERROR explicit lifetime diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.nll.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.nll.stderr index 32ef068b8b9..6119f3c5605 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.nll.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:18:36 | LL | if true { &self.field } else { x } //~ ERROR explicit lifetime diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.nll.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.nll.stderr index fd10b0d338c..71e9c34ac2b 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.nll.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex1-return-one-existing-name-if-else-using-impl.rs:21:20 | LL | if x > y { x } else { y } //~ ERROR lifetime mismatch diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.nll.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.nll.stderr index f17b24a0aca..5e49e4ec4a9 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.nll.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex1-return-one-existing-name-if-else.rs:12:27 | LL | if x > y { x } else { y } //~ ERROR explicit lifetime diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.nll.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.nll.stderr index b1663fe5eb6..6c16d6a608e 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.nll.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:18:5 | LL | x //~ ERROR lifetime mismatch diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.nll.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.nll.stderr index 19b8bd2f780..6dc96ace4d0 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.nll.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex1-return-one-existing-name-self-is-anon.rs:18:30 | LL | if true { x } else { self } //~ ERROR lifetime mismatch diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.nll.stderr b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.nll.stderr index 0b34e464b4b..a51d9307d07 100644 --- a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.nll.stderr +++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex2a-push-one-existing-name-2.rs:16:12 | LL | y.push(x); //~ ERROR explicit lifetime diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.nll.stderr b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.nll.stderr index 212b39966aa..c5f3510fa0e 100644 --- a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.nll.stderr +++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex2a-push-one-existing-name-early-bound.rs:17:12 | LL | x.push(y); //~ ERROR explicit lifetime required diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.nll.stderr b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.nll.stderr index ad39028154a..e50fd74faf4 100644 --- a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.nll.stderr +++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex2a-push-one-existing-name.rs:16:12 | LL | x.push(y); //~ ERROR explicit lifetime diff --git a/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.nll.stderr b/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.nll.stderr index 34daea7c9f4..283192c6843 100644 --- a/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.nll.stderr +++ b/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex2b-push-no-existing-names.rs:16:12 | LL | x.push(y); //~ ERROR lifetime mismatch diff --git a/src/test/ui/lifetime-errors/ex2c-push-inference-variable.nll.stderr b/src/test/ui/lifetime-errors/ex2c-push-inference-variable.nll.stderr index 96baa5c8ad2..2ca202b402c 100644 --- a/src/test/ui/lifetime-errors/ex2c-push-inference-variable.nll.stderr +++ b/src/test/ui/lifetime-errors/ex2c-push-inference-variable.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex2c-push-inference-variable.rs:16:13 | LL | let z = Ref { data: y.data }; diff --git a/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.nll.stderr b/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.nll.stderr index e5d47689b49..712c25f8929 100644 --- a/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.nll.stderr +++ b/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex2d-push-inference-variable-2.rs:17:13 | LL | let b = Ref { data: y.data }; diff --git a/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.nll.stderr b/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.nll.stderr index 668752f8e02..351966902a4 100644 --- a/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.nll.stderr +++ b/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex2e-push-inference-variable-3.rs:17:13 | LL | let b = Ref { data: y.data }; diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-2.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-2.nll.stderr index 45234249711..871a0b109b4 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-2.nll.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-2.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex3-both-anon-regions-2.rs:12:9 | LL | v = x; //~ ERROR lifetime mismatch diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-3.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-3.nll.stderr index 581088a9258..102981977e5 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-3.nll.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-3.nll.stderr @@ -1,10 +1,10 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex3-both-anon-regions-3.rs:12:13 | LL | z.push((x,y)); //~ ERROR lifetime mismatch | ^ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex3-both-anon-regions-3.rs:12:15 | LL | z.push((x,y)); //~ ERROR lifetime mismatch diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.nll.stderr index b15f5f4a0fc..191389b7706 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.nll.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex3-both-anon-regions-both-are-structs-2.rs:16:11 | LL | x.b = y.b; //~ ERROR lifetime mismatch diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.nll.stderr index 0ec73c2e778..159367cc9d2 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.nll.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex3-both-anon-regions-both-are-structs-3.rs:16:11 | LL | x.a = x.b; //~ ERROR lifetime mismatch diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.nll.stderr index 727a701d3f2..3bbcbdd6681 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.nll.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex3-both-anon-regions-both-are-structs-4.rs:16:11 | LL | x.a = x.b; //~ ERROR lifetime mismatch diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.nll.stderr index f010c87377e..9d1f6a3e36f 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.nll.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex3-both-anon-regions-both-are-structs-earlybound-regions.rs:18:12 | LL | x.push(y); //~ ERROR lifetime mismatch diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.nll.stderr index 2b48b176ae8..5df93fd5547 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.nll.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex3-both-anon-regions-both-are-structs-latebound-regions.rs:15:12 | LL | x.push(y); //~ ERROR lifetime mismatch diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.nll.stderr index c9ac04cb01e..cd602cf950b 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.nll.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex3-both-anon-regions-both-are-structs.rs:15:12 | LL | x.push(y); //~ ERROR lifetime mismatch diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-latebound-regions.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-latebound-regions.nll.stderr index 9c7fc8ac458..52c90839c32 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-latebound-regions.nll.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-latebound-regions.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex3-both-anon-regions-latebound-regions.rs:12:12 | LL | x.push(y); //~ ERROR lifetime mismatch diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr index 85a0b7c1345..9d6d68f518d 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex3-both-anon-regions-one-is-struct-2.rs:14:9 | LL | y = x.b; //~ ERROR lifetime mismatch diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.nll.stderr index 4e160001b87..e7fb67f117f 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.nll.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex3-both-anon-regions-one-is-struct-3.rs:14:11 | LL | y.b = x; //~ ERROR lifetime mismatch diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.nll.stderr index 7bbc3c4084f..af9e3a42664 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.nll.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex3-both-anon-regions-one-is-struct-4.rs:14:11 | LL | y.b = x; //~ ERROR lifetime mismatch diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.nll.stderr index 9fd7bbac247..5437beaab65 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.nll.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex3-both-anon-regions-one-is-struct.rs:17:11 | LL | x.b = y; //~ ERROR lifetime mismatch diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.nll.stderr index 528a846991c..42e1d42a32c 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.nll.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex3-both-anon-regions-return-type-is-anon.rs:17:5 | LL | x //~ ERROR lifetime mismatch diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.nll.stderr index f8c0b5940c9..26b0488cfdc 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.nll.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex3-both-anon-regions-self-is-anon.rs:17:19 | LL | if true { x } else { self } //~ ERROR lifetime mismatch diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-fn-items.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-fn-items.nll.stderr index 284f760435c..f58f33c9a9a 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-fn-items.nll.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-fn-items.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex3-both-anon-regions-using-fn-items.rs:11:10 | LL | y.push(z); //~ ERROR lifetime mismatch diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.nll.stderr index 389549a8464..4d54f6fe037 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.nll.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex3-both-anon-regions-using-impl-items.rs:15:16 | LL | x.push(y); //~ ERROR lifetime mismatch diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-trait-objects.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-trait-objects.nll.stderr index 185ea89275f..4bfb4ac2833 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-trait-objects.nll.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-trait-objects.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex3-both-anon-regions-using-trait-objects.rs:11:10 | LL | y.push(z); //~ ERROR lifetime mismatch diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions.nll.stderr index 629a97ab5ca..c25eedc770d 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions.nll.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions.nll.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ex3-both-anon-regions.rs:12:12 | LL | x.push(y); //~ ERROR lifetime mismatch diff --git a/src/test/ui/macros/macro-backtrace-invalid-internals.rs b/src/test/ui/macros/macro-backtrace-invalid-internals.rs index bff64ad4892..090ff817eb0 100644 --- a/src/test/ui/macros/macro-backtrace-invalid-internals.rs +++ b/src/test/ui/macros/macro-backtrace-invalid-internals.rs @@ -48,13 +48,13 @@ macro_rules! fake_anon_field_expr { macro_rules! real_method_stmt { () => { - 2.0.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}` + 2.0.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}` } } macro_rules! real_method_expr { () => { - 2.0.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}` + 2.0.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}` } } diff --git a/src/test/ui/macros/macro-backtrace-invalid-internals.stderr b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr index cb7d422b7f3..284960d2f6e 100644 --- a/src/test/ui/macros/macro-backtrace-invalid-internals.stderr +++ b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr @@ -25,17 +25,17 @@ LL | (1).0 //~ ERROR doesn't have fields LL | fake_anon_field_stmt!(); | ------------------------ in this macro invocation -error[E0689]: can't call method `powi` on ambiguous numeric type `{float}` +error[E0689]: can't call method `recip` on ambiguous numeric type `{float}` --> $DIR/macro-backtrace-invalid-internals.rs:51:15 | -LL | 2.0.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}` - | ^^^^ +LL | 2.0.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}` + | ^^^^^ ... LL | real_method_stmt!(); | -------------------- in this macro invocation help: you must specify a concrete type for this numeric value, like `f32` | -LL | 2.0_f32.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}` +LL | 2.0_f32.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}` | ^^^^^^^ error[E0599]: no method named `fake` found for type `{integer}` in the current scope @@ -65,17 +65,17 @@ LL | (1).0 //~ ERROR doesn't have fields LL | let _ = fake_anon_field_expr!(); | ----------------------- in this macro invocation -error[E0689]: can't call method `powi` on ambiguous numeric type `{float}` +error[E0689]: can't call method `recip` on ambiguous numeric type `{float}` --> $DIR/macro-backtrace-invalid-internals.rs:57:15 | -LL | 2.0.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}` - | ^^^^ +LL | 2.0.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}` + | ^^^^^ ... LL | let _ = real_method_expr!(); | ------------------- in this macro invocation help: you must specify a concrete type for this numeric value, like `f32` | -LL | 2.0_f32.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}` +LL | 2.0_f32.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}` | ^^^^^^^ error: aborting due to 8 previous errors diff --git a/src/test/ui/mir_check_nonconst.rs b/src/test/ui/mir_check_nonconst.rs new file mode 100644 index 00000000000..898ee8bbd44 --- /dev/null +++ b/src/test/ui/mir_check_nonconst.rs @@ -0,0 +1,21 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(dead_code)] + +struct Foo { a: u8 } +fn bar() -> Foo { + Foo { a: 5 } +} + +static foo: Foo = bar(); +//~^ ERROR calls in statics are limited to constant functions, tuple structs and tuple variants + +fn main() {} diff --git a/src/test/ui/mir_check_nonconst.stderr b/src/test/ui/mir_check_nonconst.stderr new file mode 100644 index 00000000000..1fddaf30576 --- /dev/null +++ b/src/test/ui/mir_check_nonconst.stderr @@ -0,0 +1,9 @@ +error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants + --> $DIR/mir_check_nonconst.rs:18:19 + | +LL | static foo: Foo = bar(); + | ^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/src/test/ui/print_type_sizes/uninhabited.rs b/src/test/ui/print_type_sizes/uninhabited.rs index 1908ef244cf..9ae86136a90 100644 --- a/src/test/ui/print_type_sizes/uninhabited.rs +++ b/src/test/ui/print_type_sizes/uninhabited.rs @@ -11,6 +11,7 @@ // compile-flags: -Z print-type-sizes // compile-pass +#![feature(never_type)] #![feature(start)] #[start] diff --git a/src/test/ui/reachable/expr_add.rs b/src/test/ui/reachable/expr_add.rs index 3e39b75d8c0..26760cfea44 100644 --- a/src/test/ui/reachable/expr_add.rs +++ b/src/test/ui/reachable/expr_add.rs @@ -7,7 +7,7 @@ // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. - +#![feature(never_type)] #![allow(unused_variables)] #![deny(unreachable_code)] diff --git a/src/test/ui/reachable/expr_assign.rs b/src/test/ui/reachable/expr_assign.rs index 73083af34d9..308f2483be5 100644 --- a/src/test/ui/reachable/expr_assign.rs +++ b/src/test/ui/reachable/expr_assign.rs @@ -7,7 +7,7 @@ // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. - +#![feature(never_type)] #![allow(unused_variables)] #![allow(unused_assignments)] #![allow(dead_code)] diff --git a/src/test/ui/reachable/expr_call.rs b/src/test/ui/reachable/expr_call.rs index 2772dd429d1..9696bdadf87 100644 --- a/src/test/ui/reachable/expr_call.rs +++ b/src/test/ui/reachable/expr_call.rs @@ -7,7 +7,7 @@ // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. - +#![feature(never_type)] #![allow(unused_variables)] #![allow(unused_assignments)] #![allow(dead_code)] diff --git a/src/test/ui/reachable/expr_cast.rs b/src/test/ui/reachable/expr_cast.rs index 88846b63841..fc0041daf7c 100644 --- a/src/test/ui/reachable/expr_cast.rs +++ b/src/test/ui/reachable/expr_cast.rs @@ -12,7 +12,7 @@ #![allow(unused_assignments)] #![allow(dead_code)] #![deny(unreachable_code)] -#![feature(type_ascription)] +#![feature(never_type, type_ascription)] fn a() { // the cast is unreachable: diff --git a/src/test/ui/reachable/expr_method.rs b/src/test/ui/reachable/expr_method.rs index 7dabb307097..c91646cfa1e 100644 --- a/src/test/ui/reachable/expr_method.rs +++ b/src/test/ui/reachable/expr_method.rs @@ -7,7 +7,7 @@ // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. - +#![feature(never_type)] #![allow(unused_variables)] #![allow(unused_assignments)] #![allow(dead_code)] diff --git a/src/test/ui/reachable/expr_type.rs b/src/test/ui/reachable/expr_type.rs index 2381ea2ac7a..ce12412ba74 100644 --- a/src/test/ui/reachable/expr_type.rs +++ b/src/test/ui/reachable/expr_type.rs @@ -12,7 +12,7 @@ #![allow(unused_assignments)] #![allow(dead_code)] #![deny(unreachable_code)] -#![feature(type_ascription)] +#![feature(never_type, type_ascription)] fn a() { // the cast is unreachable: diff --git a/src/test/ui/reachable/expr_unary.rs b/src/test/ui/reachable/expr_unary.rs index 4096865f4c6..5b7ea57b166 100644 --- a/src/test/ui/reachable/expr_unary.rs +++ b/src/test/ui/reachable/expr_unary.rs @@ -7,7 +7,7 @@ // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. - +#![feature(never_type)] #![allow(unused_variables)] #![allow(unused_assignments)] #![allow(dead_code)] diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test-should-panic.rs b/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test-should-panic.rs new file mode 100644 index 00000000000..73a0150c0bb --- /dev/null +++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test-should-panic.rs @@ -0,0 +1,26 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: --test + +#![feature(termination_trait_test)] +#![feature(test)] + +extern crate test; +use std::num::ParseIntError; +use test::Bencher; + +#[test] +#[should_panic] +fn not_a_num() -> Result<(), ParseIntError> { + //~^ ERROR functions using `#[should_panic]` must return `()` + let _: u32 = "abc".parse()?; + Ok(()) +} diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test-should-panic.stderr b/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test-should-panic.stderr new file mode 100644 index 00000000000..e3dab82df41 --- /dev/null +++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test-should-panic.stderr @@ -0,0 +1,12 @@ +error: functions using `#[should_panic]` must return `()` + --> $DIR/termination-trait-in-test-should-panic.rs:22:1 + | +LL | / fn not_a_num() -> Result<(), ParseIntError> { +LL | | //~^ ERROR functions using `#[should_panic]` must return `()` +LL | | let _: u32 = "abc".parse()?; +LL | | Ok(()) +LL | | } + | |_^ + +error: aborting due to previous error + diff --git a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-in-test.rs b/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test.rs index 11997eb6917..2cb4552a4b2 100644 --- a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-in-test.rs +++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test.rs @@ -9,6 +9,7 @@ // except according to those terms. // compile-flags: --test +// run-pass #![feature(termination_trait_test)] #![feature(test)] @@ -23,13 +24,6 @@ fn is_a_num() -> Result<(), ParseIntError> { Ok(()) } -#[test] -#[should_panic] -fn not_a_num() -> Result<(), ParseIntError> { - let _: u32 = "abc".parse()?; - Ok(()) -} - #[bench] fn test_a_positive_bench(_: &mut Bencher) -> Result<(), ParseIntError> { Ok(()) diff --git a/src/test/ui/rfc-2005-default-binding-mode/enum.nll.stderr b/src/test/ui/rfc-2005-default-binding-mode/enum.nll.stderr index 6ae5f777a93..b97bdeea409 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/enum.nll.stderr +++ b/src/test/ui/rfc-2005-default-binding-mode/enum.nll.stderr @@ -1,20 +1,26 @@ -error[E0594]: cannot assign to immutable item `*x` +error[E0594]: cannot assign to data in a `&` reference --> $DIR/enum.rs:19:5 | +LL | let Wrap(x) = &Wrap(3); + | - help: consider changing this to be a mutable reference: `&mut` LL | *x += 1; //~ ERROR cannot assign to immutable - | ^^^^^^^ cannot mutate + | ^^^^^^^ -error[E0594]: cannot assign to immutable item `*x` +error[E0594]: cannot assign to data in a `&` reference --> $DIR/enum.rs:23:9 | +LL | if let Some(x) = &Some(3) { + | - help: consider changing this to be a mutable reference: `&mut` LL | *x += 1; //~ ERROR cannot assign to immutable - | ^^^^^^^ cannot mutate + | ^^^^^^^ -error[E0594]: cannot assign to immutable item `*x` +error[E0594]: cannot assign to data in a `&` reference --> $DIR/enum.rs:29:9 | +LL | while let Some(x) = &Some(3) { + | - help: consider changing this to be a mutable reference: `&mut` LL | *x += 1; //~ ERROR cannot assign to immutable - | ^^^^^^^ cannot mutate + | ^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.nll.stderr b/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.nll.stderr index 7138c4ac06e..3ee4dc07bb8 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.nll.stderr +++ b/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.nll.stderr @@ -1,20 +1,26 @@ -error[E0594]: cannot assign to immutable item `*n` +error[E0594]: cannot assign to data in a `&` reference --> $DIR/explicit-mut.rs:17:13 | +LL | Some(n) => { + | - help: consider changing this to be a mutable reference: `&mut` LL | *n += 1; //~ ERROR cannot assign to immutable - | ^^^^^^^ cannot mutate + | ^^^^^^^ -error[E0594]: cannot assign to immutable item `*n` +error[E0594]: cannot assign to data in a `&` reference --> $DIR/explicit-mut.rs:25:13 | +LL | Some(n) => { + | - help: consider changing this to be a mutable reference: `&mut` LL | *n += 1; //~ ERROR cannot assign to immutable - | ^^^^^^^ cannot mutate + | ^^^^^^^ -error[E0594]: cannot assign to immutable item `*n` +error[E0594]: cannot assign to data in a `&` reference --> $DIR/explicit-mut.rs:33:13 | +LL | Some(n) => { + | - help: consider changing this to be a mutable reference: `&mut` LL | *n += 1; //~ ERROR cannot assign to immutable - | ^^^^^^^ cannot mutate + | ^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr index 505ee95088f..26e9ea4dc0b 100644 --- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr +++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr @@ -24,7 +24,7 @@ error[E0596]: cannot borrow immutable item `*f.f` as mutable LL | f.f.call_mut(()) | ^^^ cannot borrow as mutable | - = note: Value not mutable causing this error: `*f` + = note: the value which is causing this path not to be mutable is...: `*f` error[E0507]: cannot move out of borrowed content --> $DIR/borrowck-call-is-borrow-issue-12224.rs:66:13 diff --git a/src/test/ui/span/borrowck-object-mutability.nll.stderr b/src/test/ui/span/borrowck-object-mutability.nll.stderr index 100b5ae150a..9b5e084bd37 100644 --- a/src/test/ui/span/borrowck-object-mutability.nll.stderr +++ b/src/test/ui/span/borrowck-object-mutability.nll.stderr @@ -10,7 +10,7 @@ error[E0596]: cannot borrow immutable item `*x` as mutable LL | x.borrowed_mut(); //~ ERROR cannot borrow | ^ cannot borrow as mutable | - = note: Value not mutable causing this error: `x` + = note: the value which is causing this path not to be mutable is...: `x` error: aborting due to 2 previous errors diff --git a/src/test/ui/span/destructor-restrictions.nll.stderr b/src/test/ui/span/destructor-restrictions.nll.stderr index e69de29bb2d..5de246cbb73 100644 --- a/src/test/ui/span/destructor-restrictions.nll.stderr +++ b/src/test/ui/span/destructor-restrictions.nll.stderr @@ -0,0 +1,16 @@ +error[E0597]: `*a` does not live long enough + --> $DIR/destructor-restrictions.rs:18:10 + | +LL | *a.borrow() + 1 + | ^--------- + | | + | borrowed value does not live long enough + | borrow may end up in a temporary, created here +LL | }; //~^ ERROR `*a` does not live long enough + | -- temporary later dropped here, potentially using the reference + | | + | borrowed value only lives until here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/dropck_vec_cycle_checked.nll.stderr b/src/test/ui/span/dropck_vec_cycle_checked.nll.stderr index 41edd04c92e..b7f8b85f46c 100644 --- a/src/test/ui/span/dropck_vec_cycle_checked.nll.stderr +++ b/src/test/ui/span/dropck_vec_cycle_checked.nll.stderr @@ -1,5 +1,5 @@ error[E0597]: `c1` does not live long enough - --> $DIR/dropck_vec_cycle_checked.rs:118:24 + --> $DIR/dropck_vec_cycle_checked.rs:121:24 | LL | c3.v[0].v.set(Some(&c1)); | ^^^ borrowed value does not live long enough @@ -11,7 +11,7 @@ LL | } | borrow later used here, when `c1` is dropped error[E0597]: `c2` does not live long enough - --> $DIR/dropck_vec_cycle_checked.rs:110:24 + --> $DIR/dropck_vec_cycle_checked.rs:113:24 | LL | c1.v[0].v.set(Some(&c2)); | ^^^ borrowed value does not live long enough @@ -23,7 +23,7 @@ LL | } | borrow later used here, when `c1` is dropped error[E0597]: `c3` does not live long enough - --> $DIR/dropck_vec_cycle_checked.rs:112:24 + --> $DIR/dropck_vec_cycle_checked.rs:115:24 | LL | c1.v[1].v.set(Some(&c3)); | ^^^ borrowed value does not live long enough diff --git a/src/test/ui/span/dropck_vec_cycle_checked.rs b/src/test/ui/span/dropck_vec_cycle_checked.rs index 0560900e858..ece58d21ba9 100644 --- a/src/test/ui/span/dropck_vec_cycle_checked.rs +++ b/src/test/ui/span/dropck_vec_cycle_checked.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: -Z nll-subminimal-causes +// (Work around rust-lang/rust#49998 by opting into nll-subminimal-causes.) + // Reject mixing cyclic structure and Drop when using Vec. // // (Compare against compile-fail/dropck_arr_cycle_checked.rs) diff --git a/src/test/ui/span/dropck_vec_cycle_checked.stderr b/src/test/ui/span/dropck_vec_cycle_checked.stderr index 63b0ab52d39..a6bc8da6f7c 100644 --- a/src/test/ui/span/dropck_vec_cycle_checked.stderr +++ b/src/test/ui/span/dropck_vec_cycle_checked.stderr @@ -1,5 +1,5 @@ error[E0597]: `c2` does not live long enough - --> $DIR/dropck_vec_cycle_checked.rs:110:25 + --> $DIR/dropck_vec_cycle_checked.rs:113:25 | LL | c1.v[0].v.set(Some(&c2)); | ^^ borrowed value does not live long enough @@ -10,7 +10,7 @@ LL | } = note: values in a scope are dropped in the opposite order they are created error[E0597]: `c3` does not live long enough - --> $DIR/dropck_vec_cycle_checked.rs:112:25 + --> $DIR/dropck_vec_cycle_checked.rs:115:25 | LL | c1.v[1].v.set(Some(&c3)); | ^^ borrowed value does not live long enough @@ -21,7 +21,7 @@ LL | } = note: values in a scope are dropped in the opposite order they are created error[E0597]: `c2` does not live long enough - --> $DIR/dropck_vec_cycle_checked.rs:114:25 + --> $DIR/dropck_vec_cycle_checked.rs:117:25 | LL | c2.v[0].v.set(Some(&c2)); | ^^ borrowed value does not live long enough @@ -32,7 +32,7 @@ LL | } = note: values in a scope are dropped in the opposite order they are created error[E0597]: `c3` does not live long enough - --> $DIR/dropck_vec_cycle_checked.rs:116:25 + --> $DIR/dropck_vec_cycle_checked.rs:119:25 | LL | c2.v[1].v.set(Some(&c3)); | ^^ borrowed value does not live long enough @@ -43,7 +43,7 @@ LL | } = note: values in a scope are dropped in the opposite order they are created error[E0597]: `c1` does not live long enough - --> $DIR/dropck_vec_cycle_checked.rs:118:25 + --> $DIR/dropck_vec_cycle_checked.rs:121:25 | LL | c3.v[0].v.set(Some(&c1)); | ^^ borrowed value does not live long enough @@ -54,7 +54,7 @@ LL | } = note: values in a scope are dropped in the opposite order they are created error[E0597]: `c2` does not live long enough - --> $DIR/dropck_vec_cycle_checked.rs:120:25 + --> $DIR/dropck_vec_cycle_checked.rs:123:25 | LL | c3.v[1].v.set(Some(&c2)); | ^^ borrowed value does not live long enough diff --git a/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.nll.stderr b/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.nll.stderr index e69de29bb2d..56f2d14390e 100644 --- a/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.nll.stderr +++ b/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.nll.stderr @@ -0,0 +1,30 @@ +error[E0597]: `y` does not live long enough + --> $DIR/issue-23338-locals-die-before-temps-of-body.rs:20:5 + | +LL | y.borrow().clone() + | ^--------- + | | + | borrowed value does not live long enough + | borrow may end up in a temporary, created here +LL | } + | - + | | + | borrowed value only lives until here + | temporary later dropped here, potentially using the reference + +error[E0597]: `y` does not live long enough + --> $DIR/issue-23338-locals-die-before-temps-of-body.rs:27:9 + | +LL | y.borrow().clone() + | ^--------- + | | + | borrowed value does not live long enough + | borrow may end up in a temporary, created here +LL | }; + | -- temporary later dropped here, potentially using the reference + | | + | borrowed value only lives until here + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/wf-method-late-bound-regions.nll.stderr b/src/test/ui/span/wf-method-late-bound-regions.nll.stderr index a175cf1b38a..063ac376b05 100644 --- a/src/test/ui/span/wf-method-late-bound-regions.nll.stderr +++ b/src/test/ui/span/wf-method-late-bound-regions.nll.stderr @@ -1,14 +1,14 @@ -error: compilation successful - --> $DIR/wf-method-late-bound-regions.rs:25:1 +error[E0597]: `pointer` does not live long enough + --> $DIR/wf-method-late-bound-regions.rs:30:18 | -LL | / fn main() { #![rustc_error] // rust-lang/rust#49855 -LL | | let f = Foo(None); -LL | | let f2 = f; -LL | | let dangling = { -... | -LL | | println!("{}", dangling); -LL | | } - | |_^ +LL | f2.xmute(&pointer) + | ^^^^^^^^ borrowed value does not live long enough +LL | }; + | - borrowed value only lives until here +LL | //~^^ ERROR `pointer` does not live long enough +LL | println!("{}", dangling); + | -------- borrow later used here error: aborting due to previous error +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/wf-method-late-bound-regions.rs b/src/test/ui/span/wf-method-late-bound-regions.rs index 317cd395d0a..d58c29d4a32 100644 --- a/src/test/ui/span/wf-method-late-bound-regions.rs +++ b/src/test/ui/span/wf-method-late-bound-regions.rs @@ -11,7 +11,7 @@ // A method's receiver must be well-formed, even if it has late-bound regions. // Because of this, a method's substs being well-formed does not imply that // the method's implied bounds are met. -#![feature(rustc_attrs)] + struct Foo<'b>(Option<&'b ()>); trait Bar<'b> { @@ -22,7 +22,7 @@ impl<'b> Bar<'b> for Foo<'b> { fn xmute<'a>(&'a self, u: &'b u32) -> &'a u32 { u } } -fn main() { #![rustc_error] // rust-lang/rust#49855 +fn main() { let f = Foo(None); let f2 = f; let dangling = { diff --git a/src/test/ui/suggestions/method-on-ambiguous-numeric-type.rs b/src/test/ui/suggestions/method-on-ambiguous-numeric-type.rs index fa5bafab871..2e452f9671f 100644 --- a/src/test/ui/suggestions/method-on-ambiguous-numeric-type.rs +++ b/src/test/ui/suggestions/method-on-ambiguous-numeric-type.rs @@ -9,10 +9,10 @@ // except according to those terms. fn main() { - let x = 2.0.powi(2); - //~^ ERROR can't call method `powi` on ambiguous numeric type `{float}` + let x = 2.0.recip(); + //~^ ERROR can't call method `recip` on ambiguous numeric type `{float}` let y = 2.0; - let x = y.powi(2); - //~^ ERROR can't call method `powi` on ambiguous numeric type `{float}` + let x = y.recip(); + //~^ ERROR can't call method `recip` on ambiguous numeric type `{float}` println!("{:?}", x); } diff --git a/src/test/ui/suggestions/method-on-ambiguous-numeric-type.stderr b/src/test/ui/suggestions/method-on-ambiguous-numeric-type.stderr index 92ad2280615..477b4c3821d 100644 --- a/src/test/ui/suggestions/method-on-ambiguous-numeric-type.stderr +++ b/src/test/ui/suggestions/method-on-ambiguous-numeric-type.stderr @@ -1,18 +1,18 @@ -error[E0689]: can't call method `powi` on ambiguous numeric type `{float}` +error[E0689]: can't call method `recip` on ambiguous numeric type `{float}` --> $DIR/method-on-ambiguous-numeric-type.rs:12:17 | -LL | let x = 2.0.powi(2); - | ^^^^ +LL | let x = 2.0.recip(); + | ^^^^^ help: you must specify a concrete type for this numeric value, like `f32` | -LL | let x = 2.0_f32.powi(2); +LL | let x = 2.0_f32.recip(); | ^^^^^^^ -error[E0689]: can't call method `powi` on ambiguous numeric type `{float}` +error[E0689]: can't call method `recip` on ambiguous numeric type `{float}` --> $DIR/method-on-ambiguous-numeric-type.rs:15:15 | -LL | let x = y.powi(2); - | ^^^^ +LL | let x = y.recip(); + | ^^^^^ help: you must specify a type for this binding, like `f32` | LL | let y: f32 = 2.0; diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr index f8ea891914e..10a03786d7b 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr @@ -1,22 +1,22 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/dyn-trait-underscore.rs:20:14 | LL | Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime | ^^^^^ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/dyn-trait-underscore.rs:20:20 | LL | Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime | ^^^^ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/dyn-trait-underscore.rs:20:5 | LL | Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime | ^^^^^^^^ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/dyn-trait-underscore.rs:20:5 | LL | Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime diff --git a/src/test/ui/update-references.sh b/src/test/ui/update-references.sh index c2c842fcc49..4fc11daaa3a 100755 --- a/src/test/ui/update-references.sh +++ b/src/test/ui/update-references.sh @@ -31,18 +31,17 @@ MYDIR=$(dirname $0) BUILD_DIR="$1" shift +shopt -s nullglob + while [[ "$1" != "" ]]; do - STDERR_NAME="${1/%.rs/.stderr}" - STDOUT_NAME="${1/%.rs/.stdout}" + for EXT in "stderr" "stdout"; do + for OUT_NAME in $BUILD_DIR/${1%.rs}.*$EXT; do + OUT_BASE=`basename "$OUT_NAME"` + if ! (diff $OUT_NAME $MYDIR/$OUT_BASE >& /dev/null); then + echo updating $MYDIR/$OUT_BASE + cp $OUT_NAME $MYDIR + fi + done + done shift - if [ -f $BUILD_DIR/$STDOUT_NAME ] && \ - ! (diff $BUILD_DIR/$STDOUT_NAME $MYDIR/$STDOUT_NAME >& /dev/null); then - echo updating $MYDIR/$STDOUT_NAME - cp $BUILD_DIR/$STDOUT_NAME $MYDIR/$STDOUT_NAME - fi - if [ -f $BUILD_DIR/$STDERR_NAME ] && \ - ! (diff $BUILD_DIR/$STDERR_NAME $MYDIR/$STDERR_NAME >& /dev/null); then - echo updating $MYDIR/$STDERR_NAME - cp $BUILD_DIR/$STDERR_NAME $MYDIR/$STDERR_NAME - fi done diff --git a/src/tools/cargo b/src/tools/cargo -Subproject 008c3690846798d678f4a0a45ee46cc9ff6dc90 +Subproject 0a1add2d8689ad12a86f6c32d0a5cd0393dc5d8 diff --git a/src/tools/clippy b/src/tools/clippy -Subproject 8ec61a613ad1278b18a4770332b6da128704fdd +Subproject c5b39a5917ffc0f1349b6e414fa3b874fdcf842 diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 41fc67a66f4..365b47447f2 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -101,7 +101,7 @@ pub enum CompareMode { } impl CompareMode { - fn to_str(&self) -> &'static str { + pub(crate) fn to_str(&self) -> &'static str { match *self { CompareMode::Nll => "nll" } diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 3795704466a..73dd079cf0c 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -228,6 +228,8 @@ pub struct TestProps { pub check_test_line_numbers_match: bool, // The test must be compiled and run successfully. Only used in UI tests for now. pub run_pass: bool, + // Skip any codegen step and running the executable. Only for run-pass. + pub skip_trans: bool, // Do not pass `-Z ui-testing` to UI tests pub disable_ui_testing_normalization: bool, // customized normalization rules @@ -260,6 +262,7 @@ impl TestProps { compile_pass: false, check_test_line_numbers_match: false, run_pass: false, + skip_trans: false, disable_ui_testing_normalization: false, normalize_stdout: vec![], normalize_stderr: vec![], @@ -381,6 +384,10 @@ impl TestProps { config.parse_compile_pass(ln) || self.run_pass; } + if !self.skip_trans { + self.skip_trans = config.parse_skip_trans(ln); + } + if !self.disable_ui_testing_normalization { self.disable_ui_testing_normalization = config.parse_disable_ui_testing_normalization(ln); @@ -524,6 +531,10 @@ impl Config { self.parse_name_directive(line, "run-pass") } + fn parse_skip_trans(&self, line: &str) -> bool { + self.parse_name_directive(line, "skip-trans") + } + fn parse_env(&self, line: &str, name: &str) -> Option<(String, String)> { self.parse_name_value_directive(line, name).map(|nv| { // nv is either FOO or FOO=BAR diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index ae4f4aa4046..37f7af0abe8 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -626,7 +626,7 @@ pub fn make_test(config: &Config, testpaths: &TestPaths) -> test::TestDescAndFn // Debugging emscripten code doesn't make sense today let ignore = early_props.ignore - || (!up_to_date(config, testpaths, &early_props) && config.compare_mode.is_none()) + || !up_to_date(config, testpaths, &early_props) || (config.mode == DebugInfoGdb || config.mode == DebugInfoLldb) && config.target.contains("emscripten"); @@ -642,10 +642,15 @@ pub fn make_test(config: &Config, testpaths: &TestPaths) -> test::TestDescAndFn } fn stamp(config: &Config, testpaths: &TestPaths) -> PathBuf { + let mode_suffix = match config.compare_mode { + Some(ref mode) => format!("-{}", mode.to_str()), + None => format!(""), + }; let stamp_name = format!( - "{}-{}.stamp", + "{}-{}{}.stamp", testpaths.file.file_name().unwrap().to_str().unwrap(), - config.stage_id + config.stage_id, + mode_suffix ); config .build_base @@ -728,7 +733,11 @@ pub fn make_test_name(config: &Config, testpaths: &TestPaths) -> test::TestName let path = PathBuf::from(config.src_base.file_name().unwrap()) .join(&testpaths.relative_dir) .join(&testpaths.file.file_name().unwrap()); - test::DynTestName(format!("[{}] {}", config.mode, path.display())) + let mode_suffix = match config.compare_mode { + Some(ref mode) => format!(" ({})", mode.to_str()), + None => format!(""), + }; + test::DynTestName(format!("[{}{}] {}", config.mode, mode_suffix, path.display())) } pub fn make_test_closure(config: &Config, testpaths: &TestPaths) -> test::TestFn { diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index e79aefb7236..85434bb8a69 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -26,7 +26,7 @@ use std::collections::VecDeque; use std::collections::HashMap; use std::collections::HashSet; use std::env; -use std::ffi::OsString; +use std::ffi::{OsStr, OsString}; use std::fs::{self, create_dir_all, File}; use std::fmt; use std::io::prelude::*; @@ -72,6 +72,26 @@ impl Mismatch { } } +trait PathBufExt { + /// Append an extension to the path, even if it already has one. + fn with_extra_extension<S: AsRef<OsStr>>(&self, extension: S) -> PathBuf; +} + +impl PathBufExt for PathBuf { + fn with_extra_extension<S: AsRef<OsStr>>(&self, extension: S) -> PathBuf { + if extension.as_ref().len() == 0 { + self.clone() + } else { + let mut fname = self.file_name().unwrap().to_os_string(); + if !extension.as_ref().to_str().unwrap().starts_with(".") { + fname.push("."); + } + fname.push(extension); + self.with_file_name(fname) + } + } +} + // Produces a diff between the expected output and actual output. pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec<Mismatch> { let mut line_number = 1; @@ -323,9 +343,11 @@ impl<'test> TestCx<'test> { "run-pass tests with expected warnings should be moved to ui/" ); - let proc_res = self.exec_compiled_test(); - if !proc_res.status.success() { - self.fatal_proc_rec("test run failed!", &proc_res); + if !self.props.skip_trans { + let proc_res = self.exec_compiled_test(); + if !proc_res.status.success() { + self.fatal_proc_rec("test run failed!", &proc_res); + } } } @@ -1677,6 +1699,11 @@ impl<'test> TestCx<'test> { } } + if self.props.skip_trans { + assert!(!self.props.compile_flags.iter().any(|s| s.starts_with("--emit"))); + rustc.args(&["--emit", "metadata"]); + } + if !is_rustdoc { if self.config.target == "wasm32-unknown-unknown" { // rustc.arg("-g"); // get any backtrace at all on errors @@ -1725,20 +1752,14 @@ impl<'test> TestCx<'test> { } fn make_exe_name(&self) -> PathBuf { - let mut f = self.output_base_name(); + let mut f = self.output_base_name_stage(); // FIXME: This is using the host architecture exe suffix, not target! if self.config.target.contains("emscripten") { - let mut fname = f.file_name().unwrap().to_os_string(); - fname.push(".js"); - f.set_file_name(&fname); + f = f.with_extra_extension("js"); } else if self.config.target.contains("wasm32") { - let mut fname = f.file_name().unwrap().to_os_string(); - fname.push(".wasm"); - f.set_file_name(&fname); + f = f.with_extra_extension("wasm"); } else if !env::consts::EXE_SUFFIX.is_empty() { - let mut fname = f.file_name().unwrap().to_os_string(); - fname.push(env::consts::EXE_SUFFIX); - f.set_file_name(&fname); + f = f.with_extra_extension(env::consts::EXE_SUFFIX); } f } @@ -1846,25 +1867,28 @@ impl<'test> TestCx<'test> { } fn aux_output_dir_name(&self) -> PathBuf { - let f = self.output_base_name(); - let mut fname = f.file_name().unwrap().to_os_string(); - fname.push(&format!("{}.aux", self.config.mode.disambiguator())); - f.with_file_name(&fname) + self.output_base_name_stage() + .with_extra_extension(self.config.mode.disambiguator()) + .with_extra_extension(".aux") } fn output_testname(&self, filepath: &Path) -> PathBuf { PathBuf::from(filepath.file_stem().unwrap()) } - /// Given a test path like `compile-fail/foo/bar.rs` Returns a name like - /// - /// <output>/foo/bar-stage1 + /// Given a test path like `compile-fail/foo/bar.rs` returns a name like + /// `/path/to/build/<triple>/test/compile-fail/foo/bar`. fn output_base_name(&self) -> PathBuf { let dir = self.config.build_base.join(&self.testpaths.relative_dir); // Note: The directory `dir` is created during `collect_tests_from_dir` dir.join(&self.output_testname(&self.testpaths.file)) - .with_extension(&self.config.stage_id) + } + + /// Same as `output_base_name`, but includes the stage ID as an extension, + /// such as: `.../compile-fail/foo/bar.stage1-<triple>` + fn output_base_name_stage(&self) -> PathBuf { + self.output_base_name().with_extension(&self.config.stage_id) } fn maybe_dump_to_stdout(&self, out: &str, err: &str) { @@ -1989,7 +2013,7 @@ impl<'test> TestCx<'test> { fn run_rustdoc_test(&self) { assert!(self.revision.is_none(), "revisions not relevant here"); - let out_dir = self.output_base_name(); + let out_dir = self.output_base_name_stage(); let _ = fs::remove_dir_all(&out_dir); create_dir_all(&out_dir).unwrap(); @@ -2391,7 +2415,7 @@ impl<'test> TestCx<'test> { .unwrap(); let src_root = cwd.join(&src_root); - let tmpdir = cwd.join(self.output_base_name()); + let tmpdir = cwd.join(self.output_base_name_stage()); if tmpdir.exists() { self.aggressive_rm_rf(&tmpdir).unwrap(); } @@ -2811,17 +2835,21 @@ impl<'test> TestCx<'test> { normalized } - fn load_expected_output(&self, kind: &str) -> String { + fn expected_output_path(&self, kind: &str) -> PathBuf { let mut path = expected_output_path(&self.testpaths, self.revision, &self.config.compare_mode, kind); - if !path.exists() && self.config.compare_mode.is_some() { // fallback! path = expected_output_path(&self.testpaths, self.revision, &None, kind); } + path + } + + fn load_expected_output(&self, kind: &str) -> String { + let path = self.expected_output_path(kind); if path.exists() { match self.load_expected_output_from_path(&path) { Ok(x) => x, @@ -2875,7 +2903,12 @@ impl<'test> TestCx<'test> { } } - let output_file = self.output_base_name().with_extension(kind); + let mode = self.config.compare_mode.as_ref().map_or("", |m| m.to_str()); + let output_file = self.output_base_name() + .with_extra_extension(self.revision.unwrap_or("")) + .with_extra_extension(mode) + .with_extra_extension(kind); + match File::create(&output_file).and_then(|mut f| f.write_all(actual.as_bytes())) { Ok(()) => {} Err(e) => self.fatal(&format!( diff --git a/src/tools/miri b/src/tools/miri -Subproject d4712ca37500f26bbcbf97edcb27820717f769f +Subproject f48fed70d4447445b586a35c4ae88683542ffc7 diff --git a/src/tools/rls b/src/tools/rls -Subproject 7bda1161a37ff51f254ff0a7862abe6dc54fdb3 +Subproject 9144e223a5b90e078366275ff3dcdd406e62eae diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml index 554e3c0cd5f..5e11646ee4c 100644 --- a/src/tools/rustbook/Cargo.toml +++ b/src/tools/rustbook/Cargo.toml @@ -8,6 +8,6 @@ license = "MIT/Apache-2.0" clap = "2.25.0" [dependencies.mdbook] -version = "0.1.5" +version = "0.1.7" default-features = false features = ["search"] diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index 1e6c4336a9e..6992f2ba123 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -144,6 +144,7 @@ function main(argv) { var toolchain = argv[2]; var mainJs = readFile("build/" + toolchain + "/doc/main.js"); + var ALIASES = readFile("build/" + toolchain + "/doc/aliases.js"); var searchIndex = readFile("build/" + toolchain + "/doc/search-index.js").split("\n"); if (searchIndex[searchIndex.length - 1].length === 0) { searchIndex.pop(); @@ -161,6 +162,7 @@ function main(argv) { "execSearch"]; finalJS += 'window = { "currentCrate": "std" };\n'; + finalJS += ALIASES; finalJS += loadThings(arraysToLoad, 'array', extractArrayVariable, mainJs); finalJS += loadThings(variablesToLoad, 'variable', extractVariable, mainJs); finalJS += loadThings(functionsToLoad, 'function', extractFunction, mainJs); diff --git a/src/tools/rustfmt b/src/tools/rustfmt -Subproject dd807e24656c91b4ad22d3cac146edd86315e63 +Subproject ac8ae0062544743aaea1719a34f299b66f2b7dc diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 63f40110225..8caf39fc27b 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -45,7 +45,8 @@ static EXCEPTIONS: &'static [&'static str] = &[ "fuchsia-zircon", // BSD-3-Clause, rustdoc, rustc, cargo (jobserver & tempdir) "cssparser-macros", // MPL-2.0, rustdoc "selectors", // MPL-2.0, rustdoc - "clippy_lints", // MPL-2.0 rls + "clippy_lints", // MPL-2.0, rls + "colored", // MPL-2.0, rustfmt ]; /// Which crates to check against the whitelist? diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index bda58bc09f7..351005ff4b8 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -12,38 +12,26 @@ use std::path::Path; -// See rust-lang/rust#48879: In addition to the mapping from `foo.rs` -// to `foo.stderr`/`foo.stdout`, we also can optionally have -// `foo.$mode.stderr`, where $mode is one of the strings on this list, -// as an alternative to use when running under that mode. -static COMPARE_MODE_NAMES: [&'static str; 1] = ["nll"]; - pub fn check(path: &Path, bad: &mut bool) { super::walk_many(&[&path.join("test/ui"), &path.join("test/ui-fulldeps")], &mut |_| false, &mut |file_path| { if let Some(ext) = file_path.extension() { - if (ext == "stderr" || ext == "stdout") && !file_path.with_extension("rs").exists() { - - // rust-lang/rust#48879: this fn used to be beautful - // because Path API special-cases replacing - // extensions. That works great for ".stderr" but not - // so well for ".nll.stderr". To support the latter, - // we explicitly search backwards for mode's starting - // point and build corresponding source name. - let filename = file_path.file_name().expect("need filename") - .to_str().expect("need UTF-8 filename"); - let found_matching_prefix = COMPARE_MODE_NAMES.iter().any(|mode| { - if let Some(r_idx) = filename.rfind(&format!(".{}", mode)) { - let source_name = format!("{}.rs", &filename[0..r_idx]); - let source_path = file_path.with_file_name(source_name); - source_path.exists() - } else { - false - } - }); - - if !found_matching_prefix { + if ext == "stderr" || ext == "stdout" { + // Test output filenames have the format: + // $testname.stderr + // $testname.$mode.stderr + // $testname.$revision.stderr + // $testname.$revision.$mode.stderr + // + // For now, just make sure that there is a corresponding + // $testname.rs file. + let testname = file_path.file_name().unwrap() + .to_str().unwrap() + .splitn(2, '.').next().unwrap(); + if !file_path.with_file_name(testname) + .with_extension("rs") + .exists() { println!("Stray file with UI testing output: {:?}", file_path); *bad = true; } |
