diff --git a/config.toml.example b/config.toml.example index c9a7b57438ae9..9dd3002506e41 100644 --- a/config.toml.example +++ b/config.toml.example @@ -271,6 +271,9 @@ # Whether or not `panic!`s generate backtraces (RUST_BACKTRACE) #backtrace = true +# Build rustc with experimental parallelization +#experimental-parallel-queries = false + # The default linker that will be hard-coded into the generated compiler for # targets that don't specify linker explicitly in their target specifications. # Note that this is not the linker used to link said compiler. diff --git a/src/Cargo.lock b/src/Cargo.lock index 93979f0affc0d..371e505e9bed5 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1,20 +1,3 @@ -[[package]] -name = "advapi32-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "aho-corasick" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "aho-corasick" version = "0.6.4" @@ -199,7 +182,7 @@ dependencies = [ "git2-curl 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "home 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "home 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ignore 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "jobserver 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -587,15 +570,6 @@ dependencies = [ "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "env_logger" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "env_logger" version = "0.5.5" @@ -794,14 +768,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "home" -version = "0.3.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "advapi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "userenv-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1073,14 +1045,6 @@ dependencies = [ "toml-query 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "memchr" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "memchr" version = "2.0.1" @@ -1339,13 +1303,13 @@ dependencies = [ [[package]] name = "racer" -version = "2.0.12" +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.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.5 (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)", "syntex_syntax 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1412,18 +1376,6 @@ version = "0.1.0" name = "reformat_with_range" version = "0.1.0" -[[package]] -name = "regex" -version = "0.1.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "regex" version = "0.2.7" @@ -1436,11 +1388,6 @@ dependencies = [ "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "regex-syntax" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "regex-syntax" version = "0.5.0" @@ -1481,7 +1428,7 @@ dependencies = [ "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.12 (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.0 (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.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1545,7 +1492,7 @@ name = "rls-vfs" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "racer 2.0.12 (registry+https://github.com/rust-lang/crates.io-index)", + "racer 2.0.13 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2114,11 +2061,6 @@ name = "scoped-tls" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "scopeguard" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "scopeguard" version = "0.3.3" @@ -2436,23 +2378,6 @@ dependencies = [ "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "thread-id" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "thread_local" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "thread_local" version = "0.3.5" @@ -2603,11 +2528,6 @@ dependencies = [ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "utf8-ranges" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "utf8-ranges" version = "1.0.0" @@ -2700,8 +2620,6 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] -"checksum advapi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e06588080cb19d0acb6739808aafa5f26bfb2ca015b2b6370028b44cf7cb8a9a" -"checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66" "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" "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" @@ -2741,7 +2659,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "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.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f" "checksum env_logger 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f0628f04f7c26ebccf40d7fc2c1cf92236c05ec88cf2132641cc956812312f0f" "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" @@ -2762,7 +2679,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum globset 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e96ab92362c06811385ae9a34d2698e8a1160745e0c78fbb434a44c8de3fabc" "checksum handlebars 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fb04af2006ea09d985fef82b81e0eb25337e51b691c76403332378a53d521edc" "checksum hex 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "459d3cf58137bb02ad4adeef5036377ff59f066dbb82517b7192e3a5462a2abc" -"checksum home 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9f25ae61099d8f3fee8b483df0bd4ecccf4b2731897aad40d50eca1b641fe6db" +"checksum home 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8f94f6fbdc000a6eba0c8cf08632b2091bb59141d36ac321a2a96d6365e5e4dc" "checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e" "checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d" "checksum if_chain 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "61bb90bdd39e3af69b0172dfc6130f6cd6332bf040fbb9bdd4401d37adbd48b8" @@ -2788,7 +2705,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum lzma-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c1b93b78f89e8737dac81837fc8f5521ac162abcba902e1a3db949d55346d1da" "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" "checksum mdbook 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fef236caad7ba3b5b3944df946f19ab3e190bca53c111dd00fe05fa8d879f2fd" -"checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" "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" @@ -2817,16 +2733,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eca14c727ad12702eb4b6bfb5a232287dcf8385cb8ca83a3eeaf6519c44c408" -"checksum racer 2.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "034f1c4528581c40a60e96875467c03315868084e08ff4ceb46a00f7be3b16b4" +"checksum racer 2.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "40d44bc30fc8d403b665286b2c9a83466ddbf69297668fb02b785c3e58eb8e0d" "checksum radix_trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "211c49b6a9995cac0fd1dd9ca60b42cf3a51e151a12eb954b3a9e75513426ee8" "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" "checksum rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "485541959c8ecc49865526fe6c4de9653dd6e60d829d6edf0be228167b60372d" "checksum rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d24ad214285a7729b174ed6d3bcfcb80177807f959d95fafd5bfc5c4f201ac8" "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.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" "checksum regex 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a62bf8bb734ab90b7f234b681b01af396e5d39b028906c210dc04fa1d5e9e5b3" -"checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" "checksum regex-syntax 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "48d7391e7e90e06eaf3aefbe4652464153ecfec64806f3bf77ffc59638a63e77" "checksum remove_dir_all 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5d2f806b0fcdabd98acd380dc8daef485e22bcb7cddc811d1337967f2528cf5" "checksum rls-analysis 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fd4b9a3a3f2345854e39768e6425d1c893855da217183d1c0b3ff6f1664b6b6d" @@ -2846,7 +2760,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "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 scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8674d439c964889e2476f474a3bf198cc9e199e77499960893bac5de7e9218a4" -"checksum scopeguard 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "59a076157c1e2dc561d8de585151ee6965d910dd4dcb5dabb7ae3e83981a6c57" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" @@ -2875,8 +2788,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum termcolor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "56c456352e44f9f91f774ddeeed27c1ec60a2455ed66d692059acfb1d731bda1" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" -"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" -"checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" "checksum thread_local 0.3.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" @@ -2894,7 +2805,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f808aadd8cfec6ef90e4a14eb46f24511824d1ac596b9682703c87056c8678b7" "checksum url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e7d099f1ee52f823d4bdd60c93c3602043c728f5db3b97bdb548467f7bddea" "checksum userenv-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d28ea36bbd9192d75bd9fa9b39f96ddb986eaee824adae5d53b6e51919b2f3" -"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" "checksum vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0a7d8bed3178a8fb112199d466eeca9ed09a14ba8ad67718179b4fd5487d0b" "checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c" diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 2e094a8898206..eb23236638b13 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -321,11 +321,13 @@ impl<'a> Builder<'a> { test::RunMake), Kind::Bench => describe!(test::Crate, test::CrateLibrustc), Kind::Doc => describe!(doc::UnstableBook, doc::UnstableBookGen, doc::TheBook, - doc::Standalone, doc::Std, doc::Test, doc::Rustc, doc::ErrorIndex, doc::Nomicon, - doc::Reference, doc::Rustdoc, doc::RustByExample, doc::CargoBook), - Kind::Dist => describe!(dist::Docs, dist::Mingw, dist::Rustc, dist::DebuggerScripts, - dist::Std, dist::Analysis, dist::Src, dist::PlainSourceTarball, dist::Cargo, - dist::Rls, dist::Rustfmt, dist::Extended, dist::HashSign), + doc::Standalone, doc::Std, doc::Test, doc::WhitelistedRustc, doc::Rustc, + doc::ErrorIndex, doc::Nomicon, doc::Reference, doc::Rustdoc, doc::RustByExample, + doc::CargoBook), + Kind::Dist => describe!(dist::Docs, dist::RustcDocs, dist::Mingw, dist::Rustc, + dist::DebuggerScripts, dist::Std, dist::Analysis, dist::Src, + dist::PlainSourceTarball, dist::Cargo, dist::Rls, dist::Rustfmt, dist::Extended, + dist::HashSign), Kind::Install => describe!(install::Docs, install::Std, install::Cargo, install::Rls, install::Rustfmt, install::Analysis, install::Src, install::Rustc), } diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 33bcfaa80ca31..a9dccea827b6e 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -40,17 +40,18 @@ impl Step for Std { let target = self.target; let compiler = builder.compiler(0, build.build); - let _folder = build.fold_output(|| format!("stage{}-std", compiler.stage)); - println!("Checking std artifacts ({} -> {})", &compiler.host, target); - let out_dir = build.stage_out(compiler, Mode::Libstd); build.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); + + let _folder = build.fold_output(|| format!("stage{}-std", compiler.stage)); + println!("Checking std artifacts ({} -> {})", &compiler.host, target); run_cargo(build, &mut cargo, &libstd_stamp(build, compiler, target), true); + let libdir = builder.sysroot_libdir(compiler, target); add_to_sysroot(&libdir, &libstd_stamp(build, compiler, target)); } @@ -86,19 +87,20 @@ impl Step for Rustc { let compiler = builder.compiler(0, build.build); let target = self.target; - let _folder = build.fold_output(|| format!("stage{}-rustc", compiler.stage)); - println!("Checking compiler artifacts ({} -> {})", &compiler.host, target); - let stage_out = builder.stage_out(compiler, Mode::Librustc); build.clear_if_dirty(&stage_out, &libstd_stamp(build, compiler, target)); build.clear_if_dirty(&stage_out, &libtest_stamp(build, compiler, target)); let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "check"); rustc_cargo(build, &mut cargo); + + let _folder = build.fold_output(|| format!("stage{}-rustc", compiler.stage)); + println!("Checking compiler artifacts ({} -> {})", &compiler.host, target); run_cargo(build, &mut cargo, &librustc_stamp(build, compiler, target), true); + let libdir = builder.sysroot_libdir(compiler, target); add_to_sysroot(&libdir, &librustc_stamp(build, compiler, target)); } @@ -128,16 +130,18 @@ impl Step for Test { let target = self.target; let compiler = builder.compiler(0, build.build); - let _folder = build.fold_output(|| format!("stage{}-test", compiler.stage)); - println!("Checking test artifacts ({} -> {})", &compiler.host, target); let out_dir = build.stage_out(compiler, Mode::Libtest); build.clear_if_dirty(&out_dir, &libstd_stamp(build, compiler, target)); let mut cargo = builder.cargo(compiler, Mode::Libtest, target, "check"); test_cargo(build, &compiler, target, &mut cargo); + + let _folder = build.fold_output(|| format!("stage{}-test", compiler.stage)); + println!("Checking test artifacts ({} -> {})", &compiler.host, target); run_cargo(build, &mut cargo, &libtest_stamp(build, compiler, target), true); + let libdir = builder.sysroot_libdir(compiler, target); add_to_sysroot(&libdir, &libtest_stamp(build, compiler, target)); } diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 2640248373c3d..fafa446338189 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -93,10 +93,6 @@ impl Step for Std { return; } - let _folder = build.fold_output(|| format!("stage{}-std", compiler.stage)); - println!("Building stage{} std artifacts ({} -> {})", compiler.stage, - &compiler.host, target); - if target.contains("musl") { let libdir = builder.sysroot_libdir(compiler, target); copy_musl_third_party_objects(build, target, &libdir); @@ -106,6 +102,10 @@ impl Step for Std { build.clear_if_dirty(&out_dir, &builder.rustc(compiler)); let mut cargo = builder.cargo(compiler, Mode::Libstd, target, "build"); std_cargo(builder, &compiler, target, &mut cargo); + + let _folder = build.fold_output(|| format!("stage{}-std", compiler.stage)); + println!("Building stage{} std artifacts ({} -> {})", compiler.stage, + &compiler.host, target); run_cargo(build, &mut cargo, &libstd_stamp(build, compiler, target), @@ -360,13 +360,14 @@ impl Step for Test { return; } - let _folder = build.fold_output(|| format!("stage{}-test", compiler.stage)); - println!("Building stage{} test artifacts ({} -> {})", compiler.stage, - &compiler.host, target); let out_dir = build.stage_out(compiler, Mode::Libtest); build.clear_if_dirty(&out_dir, &libstd_stamp(build, compiler, target)); let mut cargo = builder.cargo(compiler, Mode::Libtest, target, "build"); test_cargo(build, &compiler, target, &mut cargo); + + let _folder = build.fold_output(|| format!("stage{}-test", compiler.stage)); + println!("Building stage{} test artifacts ({} -> {})", compiler.stage, + &compiler.host, target); run_cargo(build, &mut cargo, &libtest_stamp(build, compiler, target), @@ -482,16 +483,16 @@ impl Step for Rustc { target: build.build, }); - let _folder = build.fold_output(|| format!("stage{}-rustc", compiler.stage)); - println!("Building stage{} compiler artifacts ({} -> {})", - compiler.stage, &compiler.host, target); - let stage_out = builder.stage_out(compiler, Mode::Librustc); build.clear_if_dirty(&stage_out, &libstd_stamp(build, compiler, target)); build.clear_if_dirty(&stage_out, &libtest_stamp(build, compiler, target)); let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "build"); rustc_cargo(build, &mut cargo); + + let _folder = build.fold_output(|| format!("stage{}-rustc", compiler.stage)); + println!("Building stage{} compiler artifacts ({} -> {})", + compiler.stage, &compiler.host, target); run_cargo(build, &mut cargo, &librustc_stamp(build, compiler, target), @@ -634,8 +635,6 @@ impl Step for CodegenBackend { .arg(build.src.join("src/librustc_trans/Cargo.toml")); rustc_cargo_env(build, &mut cargo); - let _folder = build.fold_output(|| format!("stage{}-rustc_trans", compiler.stage)); - match &*self.backend { "llvm" | "emscripten" => { // Build LLVM for our target. This will implicitly build the @@ -685,6 +684,8 @@ impl Step for CodegenBackend { let tmp_stamp = build.cargo_out(compiler, Mode::Librustc, target) .join(".tmp.stamp"); + + let _folder = build.fold_output(|| format!("stage{}-rustc_trans", compiler.stage)); let files = run_cargo(build, cargo.arg("--features").arg(features), &tmp_stamp, diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 97da7cae07f7c..a5c373d5d5e77 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -44,6 +44,7 @@ def v(*args): o("docs", "build.docs", "build standard library documentation") o("compiler-docs", "build.compiler-docs", "build compiler documentation") o("optimize-tests", "rust.optimize-tests", "build tests with optimizations") +o("experimental-parallel-queries", "rust.experimental-parallel-queries", "build rustc with experimental parallelization") o("test-miri", "rust.test-miri", "run miri's test suite") o("debuginfo-tests", "rust.debuginfo-tests", "build tests with debugger metadata") o("quiet-tests", "rust.quiet-tests", "enable quieter output when running tests") diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index eca06eac7f307..23b7b265a94be 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -102,7 +102,7 @@ impl Step for Docs { let dst = image.join("share/doc/rust/html"); t!(fs::create_dir_all(&dst)); - let src = build.out.join(host).join("doc"); + let src = build.doc_out(host); cp_r(&src, &dst); let mut cmd = rust_installer(builder); @@ -120,14 +120,69 @@ impl Step for Docs { build.run(&mut cmd); t!(fs::remove_dir_all(&image)); - // As part of this step, *also* copy the docs directory to a directory which - // buildbot typically uploads. - if host == build.build { - let dst = distdir(build).join("doc").join(build.rust_package_vers()); - t!(fs::create_dir_all(&dst)); - cp_r(&src, &dst); + distdir(build).join(format!("{}-{}.tar.gz", name, host)) + } +} + +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct RustcDocs { + pub stage: u32, + pub host: Interned, +} + +impl Step for RustcDocs { + type Output = PathBuf; + const DEFAULT: bool = true; + + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/librustc") + } + + fn make_run(run: RunConfig) { + run.builder.ensure(RustcDocs { + stage: run.builder.top_stage, + host: run.target, + }); + } + + /// Builds the `rustc-docs` installer component. + fn run(self, builder: &Builder) -> PathBuf { + let build = builder.build; + let host = self.host; + + let name = pkgname(build, "rustc-docs"); + + println!("Dist compiler docs ({})", host); + if !build.config.compiler_docs { + println!("\tskipping - compiler docs disabled"); + return distdir(build).join(format!("{}-{}.tar.gz", name, host)); } + builder.default_doc(None); + + let image = tmpdir(build).join(format!("{}-{}-image", name, host)); + let _ = fs::remove_dir_all(&image); + + let dst = image.join("share/doc/rust/html"); + t!(fs::create_dir_all(&dst)); + let src = build.compiler_doc_out(host); + cp_r(&src, &dst); + + let mut cmd = rust_installer(builder); + cmd.arg("generate") + .arg("--product-name=Rustc-Documentation") + .arg("--rel-manifest-dir=rustlib") + .arg("--success-message=Rustc-documentation-is-installed.") + .arg("--image-dir").arg(&image) + .arg("--work-dir").arg(&tmpdir(build)) + .arg("--output-dir").arg(&distdir(build)) + .arg(format!("--package-name={}-{}", name, host)) + .arg("--component-name=rustc-docs") + .arg("--legacy-manifest-dirs=rustlib,cargo") + .arg("--bulk-dirs=share/doc/rust/html"); + build.run(&mut cmd); + t!(fs::remove_dir_all(&image)); + distdir(build).join(format!("{}-{}.tar.gz", name, host)) } } @@ -1186,7 +1241,6 @@ impl Step for Rustfmt { let build = builder.build; let stage = self.stage; let target = self.target; - assert!(build.config.extended); println!("Dist Rustfmt stage{} ({})", stage, target); let src = build.src.join("src/tools/rustfmt"); diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 5bc582b3507bb..44073a5b07572 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -17,12 +17,13 @@ //! Everything here is basically just a shim around calling either `rustbook` or //! `rustdoc`. +use std::collections::HashSet; use std::fs::{self, File}; use std::io::prelude::*; use std::io; use std::path::{PathBuf, Path}; -use Mode; +use {Build, Mode}; use build_helper::up_to_date; use util::{cp_r, symlink_dir}; @@ -483,21 +484,17 @@ impl Step for Std { let mut cargo = builder.cargo(compiler, Mode::Libstd, target, "doc"); compile::std_cargo(builder, &compiler, target, &mut cargo); - // We don't want to build docs for internal std dependencies unless - // in compiler-docs mode. When not in that mode, we whitelist the crates - // for which docs must be built. - if !build.config.compiler_docs { - cargo.arg("--no-deps"); - for krate in &["alloc", "core", "std", "std_unicode"] { - cargo.arg("-p").arg(krate); - // Create all crate output directories first to make sure rustdoc uses - // relative links. - // FIXME: Cargo should probably do this itself. - t!(fs::create_dir_all(out_dir.join(krate))); - } + // Keep a whitelist so we do not build internal stdlib crates, these will be + // build by the rustc step later if enabled. + cargo.arg("--no-deps"); + for krate in &["alloc", "core", "std", "std_unicode"] { + cargo.arg("-p").arg(krate); + // Create all crate output directories first to make sure rustdoc uses + // relative links. + // FIXME: Cargo should probably do this itself. + t!(fs::create_dir_all(out_dir.join(krate))); } - build.run(&mut cargo); cp_r(&my_out, &out); } @@ -564,12 +561,12 @@ impl Step for Test { } #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Rustc { +pub struct WhitelistedRustc { stage: u32, target: Interned, } -impl Step for Rustc { +impl Step for WhitelistedRustc { type Output = (); const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; @@ -580,21 +577,26 @@ impl Step for Rustc { } fn make_run(run: RunConfig) { - run.builder.ensure(Rustc { + run.builder.ensure(WhitelistedRustc { stage: run.builder.top_stage, target: run.target, }); } - /// Generate all compiler documentation. + /// Generate whitelisted compiler crate documentation. /// - /// This will generate all documentation for the compiler libraries and their - /// dependencies. This is largely just a wrapper around `cargo doc`. + /// This will generate all documentation for crates that are whitelisted + /// to be included in the standard documentation. This documentation is + /// included in the standard Rust documentation, so we should always + /// document it and symlink to merge with the rest of the std and test + /// documentation. We don't build other compiler documentation + /// here as we want to be able to keep it separate from the standard + /// documentation. This is largely just a wrapper around `cargo doc`. fn run(self, builder: &Builder) { let build = builder.build; let stage = self.stage; let target = self.target; - println!("Documenting stage{} compiler ({})", stage, target); + println!("Documenting stage{} whitelisted compiler ({})", stage, target); let out = build.doc_out(target); t!(fs::create_dir_all(&out)); let compiler = builder.compiler(stage, build.build); @@ -620,17 +622,12 @@ impl Step for Rustc { let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "doc"); compile::rustc_cargo(build, &mut cargo); - if build.config.compiler_docs { - // src/rustc/Cargo.toml contains a bin crate called rustc which - // would otherwise overwrite the docs for the real rustc lib crate. - cargo.arg("-p").arg("rustc_driver"); - } else { - // Like with libstd above if compiler docs aren't enabled then we're not - // documenting internal dependencies, so we have a whitelist. - cargo.arg("--no-deps"); - for krate in &["proc_macro"] { - cargo.arg("-p").arg(krate); - } + // We don't want to build docs for internal compiler dependencies in this + // step (there is another step for that). Therefore, we whitelist the crates + // for which docs must be built. + cargo.arg("--no-deps"); + for krate in &["proc_macro"] { + cargo.arg("-p").arg(krate); } build.run(&mut cargo); @@ -638,6 +635,103 @@ impl Step for Rustc { } } +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Rustc { + stage: u32, + target: Interned, +} + +impl Step for Rustc { + type Output = (); + const DEFAULT: bool = true; + const ONLY_HOSTS: bool = true; + + fn should_run(run: ShouldRun) -> ShouldRun { + let builder = run.builder; + run.krate("rustc-main").default_condition(builder.build.config.docs) + } + + fn make_run(run: RunConfig) { + run.builder.ensure(Rustc { + stage: run.builder.top_stage, + target: run.target, + }); + } + + /// Generate compiler documentation. + /// + /// This will generate all documentation for compiler and dependencies. + /// Compiler documentation is distributed separately, so we make sure + /// we do not merge it with the other documentation from std, test and + /// proc_macros. This is largely just a wrapper around `cargo doc`. + fn run(self, builder: &Builder) { + let build = builder.build; + let stage = self.stage; + let target = self.target; + println!("Documenting stage{} compiler ({})", stage, target); + let out = build.compiler_doc_out(target); + t!(fs::create_dir_all(&out)); + let compiler = builder.compiler(stage, build.build); + let rustdoc = builder.rustdoc(compiler.host); + let compiler = if build.force_use_stage1(compiler, target) { + builder.compiler(1, compiler.host) + } else { + compiler + }; + + if !build.config.compiler_docs { + println!("\tskipping - compiler docs disabled"); + return; + } + + // Build libstd docs so that we generate relative links + builder.ensure(Std { stage, target }); + + builder.ensure(compile::Rustc { compiler, target }); + let out_dir = build.stage_out(compiler, Mode::Librustc) + .join(target).join("doc"); + // We do not symlink to the same shared folder that already contains std library + // documentation from previous steps as we do not want to include that. + build.clear_if_dirty(&out, &rustdoc); + t!(symlink_dir_force(&out, &out_dir)); + + let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "doc"); + compile::rustc_cargo(build, &mut cargo); + + // Only include compiler crates, no dependencies of those, such as `libc`. + cargo.arg("--no-deps"); + + // Find dependencies for top level crates. + let mut compiler_crates = HashSet::new(); + for root_crate in &["rustc", "rustc_driver"] { + let interned_root_crate = INTERNER.intern_str(root_crate); + find_compiler_crates(&build, &interned_root_crate, &mut compiler_crates); + } + + for krate in &compiler_crates { + cargo.arg("-p").arg(krate); + } + + build.run(&mut cargo); + } +} + +fn find_compiler_crates( + build: &Build, + name: &Interned, + crates: &mut HashSet> +) { + // Add current crate. + crates.insert(*name); + + // Look for dependencies. + for dep in build.crates.get(name).unwrap().deps.iter() { + if build.crates.get(dep).unwrap().is_local(build) { + find_compiler_crates(build, dep, crates); + } + } +} + #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct ErrorIndex { target: Interned, diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index b778ba33d89cc..b2c8ac24d72d8 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -511,6 +511,11 @@ impl Build { self.out.join(&*target).join("doc") } + /// Output directory for all documentation for a target + fn compiler_doc_out(&self, target: Interned) -> PathBuf { + self.out.join(&*target).join("compiler-doc") + } + /// Output directory for some generated md crate documentation for a target (temporary) fn md_doc_out(&self, target: Interned) -> Interned { INTERNER.intern_path(self.out.join(&*target).join("md-doc")) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index a5ccbd4ec1b00..76f1a4efbf014 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -530,8 +530,6 @@ impl Step for Tidy { fn run(self, builder: &Builder) { let build = builder.build; - let _folder = build.fold_output(|| "tidy"); - println!("tidy check"); let mut cmd = builder.tool_cmd(Tool::Tidy); cmd.arg(build.src.join("src")); cmd.arg(&build.initial_cargo); @@ -541,6 +539,9 @@ impl Step for Tidy { if build.config.quiet_tests { cmd.arg("--quiet"); } + + let _folder = build.fold_output(|| "tidy"); + println!("tidy check"); try_run(build, &mut cmd); } @@ -841,9 +842,6 @@ impl Step for Compiletest { builder.ensure(native::TestHelpers { target }); builder.ensure(RemoteCopyLibs { compiler, target }); - let _folder = build.fold_output(|| format!("test_{}", suite)); - println!("Check compiletest suite={} mode={} ({} -> {})", - suite, mode, &compiler.host, target); let mut cmd = builder.tool_cmd(Tool::Compiletest); // compiletest currently has... a lot of arguments, so let's just pass all @@ -1003,6 +1001,9 @@ impl Step for Compiletest { build.ci_env.force_coloring_in_ci(&mut cmd); + let _folder = build.fold_output(|| format!("test_{}", suite)); + println!("Check compiletest suite={} mode={} ({} -> {})", + suite, mode, &compiler.host, target); let _time = util::timeit(); try_run(build, &mut cmd); } @@ -1147,20 +1148,21 @@ impl Step for ErrorIndex { builder.ensure(compile::Std { compiler, target: compiler.host }); - let _folder = build.fold_output(|| "test_error_index"); - println!("Testing error-index stage{}", compiler.stage); - let dir = testdir(build, compiler.host); t!(fs::create_dir_all(&dir)); let output = dir.join("error-index.md"); - let _time = util::timeit(); - build.run(builder.tool_cmd(Tool::ErrorIndex) - .arg("markdown") - .arg(&output) - .env("CFG_BUILD", &build.build) - .env("RUSTC_ERROR_METADATA_DST", build.extended_error_dir())); + let mut tool = builder.tool_cmd(Tool::ErrorIndex); + tool.arg("markdown") + .arg(&output) + .env("CFG_BUILD", &build.build) + .env("RUSTC_ERROR_METADATA_DST", build.extended_error_dir()); + + let _folder = build.fold_output(|| "test_error_index"); + println!("Testing error-index stage{}", compiler.stage); + let _time = util::timeit(); + build.run(&mut tool); markdown_test(builder, compiler, &output); } } @@ -1405,11 +1407,6 @@ impl Step for Crate { } _ => panic!("can only test libraries"), }; - let _folder = build.fold_output(|| { - format!("{}_stage{}-{}", test_kind.subcommand(), compiler.stage, krate) - }); - println!("{} {} stage{} ({} -> {})", test_kind, krate, compiler.stage, - &compiler.host, target); // Build up the base `cargo test` command. // @@ -1441,8 +1438,6 @@ impl Step for Crate { cargo.arg("--quiet"); } - let _time = util::timeit(); - if target.contains("emscripten") { cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target)), build.config.nodejs.as_ref().expect("nodejs not configured")); @@ -1470,6 +1465,13 @@ impl Step for Crate { format!("{} run", builder.tool_exe(Tool::RemoteTestClient).display())); } + + let _folder = build.fold_output(|| { + format!("{}_stage{}-{}", test_kind.subcommand(), compiler.stage, krate) + }); + println!("{} {} stage{} ({} -> {})", test_kind, krate, compiler.stage, + &compiler.host, target); + let _time = util::timeit(); try_run(build, &mut cargo); } } @@ -1518,12 +1520,6 @@ impl Step for CrateRustdoc { target, test_kind.subcommand(), "src/tools/rustdoc"); - let _folder = build.fold_output(|| { - format!("{}_stage{}-rustdoc", test_kind.subcommand(), compiler.stage) - }); - println!("{} rustdoc stage{} ({} -> {})", test_kind, compiler.stage, - &compiler.host, target); - if test_kind.subcommand() == "test" && !build.fail_fast { cargo.arg("--no-fail-fast"); } @@ -1537,6 +1533,11 @@ impl Step for CrateRustdoc { cargo.arg("--quiet"); } + let _folder = build.fold_output(|| { + format!("{}_stage{}-rustdoc", test_kind.subcommand(), compiler.stage) + }); + println!("{} rustdoc stage{} ({} -> {})", test_kind, compiler.stage, + &compiler.host, target); let _time = util::timeit(); try_run(build, &mut cargo); diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 5f5b10a07b865..d308cecb27521 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -112,11 +112,11 @@ impl Step for ToolBuild { Mode::Tool => panic!("unexpected Mode::Tool for tool build") } - let _folder = build.fold_output(|| format!("stage{}-{}", compiler.stage, tool)); - println!("Building stage{} tool {} ({})", compiler.stage, tool, target); - let mut cargo = prepare_tool_cargo(builder, compiler, target, "build", path); cargo.arg("--features").arg(self.extra_features.join(" ")); + + let _folder = build.fold_output(|| format!("stage{}-{}", compiler.stage, tool)); + println!("Building stage{} tool {} ({})", compiler.stage, tool, target); let is_expected = build.try_run(&mut cargo); build.save_toolstate(tool, if is_expected { ToolState::TestFail @@ -339,9 +339,6 @@ impl Step for Rustdoc { builder.ensure(compile::Rustc { compiler: build_compiler, target }); - let _folder = build.fold_output(|| format!("stage{}-rustdoc", target_compiler.stage)); - println!("Building rustdoc for stage{} ({})", target_compiler.stage, target_compiler.host); - let mut cargo = prepare_tool_cargo(builder, build_compiler, target, @@ -352,7 +349,10 @@ impl Step for Rustdoc { cargo.env("RUSTC_DEBUGINFO", builder.config.rust_debuginfo.to_string()) .env("RUSTC_DEBUGINFO_LINES", builder.config.rust_debuginfo_lines.to_string()); + let _folder = build.fold_output(|| format!("stage{}-rustdoc", target_compiler.stage)); + println!("Building rustdoc for stage{} ({})", target_compiler.stage, target_compiler.host); build.run(&mut cargo); + // Cargo adds a number of paths to the dylib search path on windows, which results in // the wrong rustdoc being executed. To avoid the conflicting rustdocs, we name the "tool" // rustdoc a different name. diff --git a/src/ci/docker/dist-x86_64-linux/Dockerfile b/src/ci/docker/dist-x86_64-linux/Dockerfile index 3b98b0aa926bd..28c97e8c6dbf9 100644 --- a/src/ci/docker/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/dist-x86_64-linux/Dockerfile @@ -84,7 +84,8 @@ ENV HOSTS=x86_64-unknown-linux-gnu ENV RUST_CONFIGURE_ARGS \ --enable-full-tools \ --enable-sanitizers \ - --enable-profiler + --enable-profiler \ + --enable-compiler-docs ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS # This is the only builder which will create source tarballs diff --git a/src/ci/docker/x86_64-gnu-debug/Dockerfile b/src/ci/docker/x86_64-gnu-debug/Dockerfile index 95d41028595f8..ff6ab1013b4c2 100644 --- a/src/ci/docker/x86_64-gnu-debug/Dockerfile +++ b/src/ci/docker/x86_64-gnu-debug/Dockerfile @@ -16,6 +16,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh +ENV PARALLEL_CHECK 1 ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ --enable-debug \ diff --git a/src/ci/run.sh b/src/ci/run.sh index 9a26043c92c13..44eae0d180047 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -74,6 +74,13 @@ fi # sccache server at the start of the build, but no need to worry if this fails. SCCACHE_IDLE_TIMEOUT=10800 sccache --start-server || true +if [ "$PARALLEL_CHECK" != "" ]; then + $SRC/configure --enable-experimental-parallel-queries + python2.7 ../x.py check + rm -f config.toml + rm -rf build +fi + travis_fold start configure travis_time_start $SRC/configure $RUST_CONFIGURE_ARGS diff --git a/src/doc/book b/src/doc/book index 98921e9de849a..b889e1e30c5e9 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 98921e9de849acdaeaed08cfad6758bb89769b7d +Subproject commit b889e1e30c5e9953834aa9fa6c982bb28df46ac9 diff --git a/src/doc/nomicon b/src/doc/nomicon index ad5ddd62c098d..6a8f0a27e9a58 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit ad5ddd62c098d5b424151beda574ae7df2154df1 +Subproject commit 6a8f0a27e9a58c55c89d07bc43a176fdae5e051c diff --git a/src/doc/reference b/src/doc/reference index 254df654a9b75..76296346e97c3 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 254df654a9b75abf6ca08806535dbe1fad41be3f +Subproject commit 76296346e97c3702974d3398fdb94af9e10111a2 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index ebb28c95b2ea6..d5ec87eabe573 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit ebb28c95b2ea68b96eddb9e71aff4d32eacc74f0 +Subproject commit d5ec87eabe5733cc2348c7dada89fc67c086f391 diff --git a/src/doc/unstable-book/src/language-features/generators.md b/src/doc/unstable-book/src/language-features/generators.md index e8e2132dca254..8e888de90a951 100644 --- a/src/doc/unstable-book/src/language-features/generators.md +++ b/src/doc/unstable-book/src/language-features/generators.md @@ -36,11 +36,11 @@ fn main() { return "foo" }; - match generator.resume() { + match unsafe { generator.resume() } { GeneratorState::Yielded(1) => {} _ => panic!("unexpected value from resume"), } - match generator.resume() { + match unsafe { generator.resume() } { GeneratorState::Complete("foo") => {} _ => panic!("unexpected value from resume"), } @@ -69,9 +69,9 @@ fn main() { }; println!("1"); - generator.resume(); + unsafe { generator.resume() }; println!("3"); - generator.resume(); + unsafe { generator.resume() }; println!("5"); } ``` @@ -92,7 +92,7 @@ The `Generator` trait in `std::ops` currently looks like: pub trait Generator { type Yield; type Return; - fn resume(&mut self) -> GeneratorState; + unsafe fn resume(&mut self) -> GeneratorState; } ``` @@ -175,8 +175,8 @@ fn main() { return ret }; - generator.resume(); - generator.resume(); + unsafe { generator.resume() }; + unsafe { generator.resume() }; } ``` @@ -200,7 +200,7 @@ fn main() { type Yield = i32; type Return = &'static str; - fn resume(&mut self) -> GeneratorState { + unsafe fn resume(&mut self) -> GeneratorState { use std::mem; match mem::replace(self, __Generator::Done) { __Generator::Start(s) => { @@ -223,8 +223,8 @@ fn main() { __Generator::Start(ret) }; - generator.resume(); - generator.resume(); + unsafe { generator.resume() }; + unsafe { generator.resume() }; } ``` diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index abe2071973bc8..bfd806f99e784 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -892,7 +892,7 @@ impl Generator for Box { type Yield = T::Yield; type Return = T::Return; - fn resume(&mut self) -> GeneratorState { + unsafe fn resume(&mut self) -> GeneratorState { (**self).resume() } } diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 9fec90914985d..e253122ffd6b6 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -1576,7 +1576,6 @@ impl FromUtf8Error { /// Basic usage: /// /// ``` - /// #![feature(from_utf8_error_as_bytes)] /// // some invalid bytes, in a vector /// let bytes = vec![0, 159]; /// @@ -1584,7 +1583,7 @@ impl FromUtf8Error { /// /// assert_eq!(&[0, 159], value.unwrap_err().as_bytes()); /// ``` - #[unstable(feature = "from_utf8_error_as_bytes", reason = "recently added", issue = "40895")] + #[stable(feature = "from_utf8_error_as_bytes", since = "1.26.0")] pub fn as_bytes(&self) -> &[u8] { &self.bytes[..] } diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index 826420a0c001c..d25f498b99efe 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -63,6 +63,11 @@ /// This trait can be used with `#[derive]` if all fields are `Clone`. The `derive`d /// implementation of [`clone`] calls [`clone`] on each field. /// +/// ## Closures +/// +/// Closure types automatically implement `Clone` if they capture no value from the environment +/// or if all such captured values implement `Clone` themselves. +/// /// ## How can I implement `Clone`? /// /// Types that are [`Copy`] should have a trivial implementation of `Clone`. More formally: diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 3ecd73873c091..62994ed15cc6d 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -406,6 +406,18 @@ impl<'a> Arguments<'a> { /// macro validates the format string at compile-time so usage of the [`write`] /// and [`format`] functions can be safely performed. /// +/// You can use the `Arguments<'a>` that [`format_args!`] returns in `Debug` +/// and `Display` contexts as seen below. The example also shows that `Debug` +/// and `Display` format to the same thing: the interpolated format string +/// in `format_args!`. +/// +/// ```rust +/// let display = format!("{:?}", format_args!("{} foo {:?}", 1, 2)); +/// let debug = format!("{}", format_args!("{} foo {:?}", 1, 2)); +/// assert_eq!("1 foo 2", display); +/// assert_eq!(display, debug); +/// ``` +/// /// [`format_args!`]: ../../std/macro.format_args.html /// [`format`]: ../../std/fmt/fn.format.html /// [`write`]: ../../std/fmt/fn.write.html @@ -1553,10 +1565,12 @@ impl<'a> Formatter<'a> { /// /// ```rust /// use std::fmt; + /// use std::net::Ipv4Addr; /// /// struct Foo { /// bar: i32, /// baz: String, + /// addr: Ipv4Addr, /// } /// /// impl fmt::Debug for Foo { @@ -1564,12 +1578,19 @@ impl<'a> Formatter<'a> { /// fmt.debug_struct("Foo") /// .field("bar", &self.bar) /// .field("baz", &self.baz) + /// .field("addr", &format_args!("{}", self.addr)) /// .finish() /// } /// } /// - /// // prints "Foo { bar: 10, baz: "Hello World" }" - /// println!("{:?}", Foo { bar: 10, baz: "Hello World".to_string() }); + /// assert_eq!( + /// "Foo { bar: 10, baz: \"Hello World\", addr: 127.0.0.1 }", + /// format!("{:?}", Foo { + /// bar: 10, + /// baz: "Hello World".to_string(), + /// addr: Ipv4Addr::new(127, 0, 0, 1), + /// }) + /// ); /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] pub fn debug_struct<'b>(&'b mut self, name: &str) -> DebugStruct<'b, 'a> { @@ -1583,20 +1604,24 @@ impl<'a> Formatter<'a> { /// /// ```rust /// use std::fmt; + /// use std::marker::PhantomData; /// - /// struct Foo(i32, String); + /// struct Foo(i32, String, PhantomData); /// - /// impl fmt::Debug for Foo { + /// impl fmt::Debug for Foo { /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { /// fmt.debug_tuple("Foo") /// .field(&self.0) /// .field(&self.1) + /// .field(&format_args!("_")) /// .finish() /// } /// } /// - /// // prints "Foo(10, "Hello World")" - /// println!("{:?}", Foo(10, "Hello World".to_string())); + /// assert_eq!( + /// "Foo(10, \"Hello\", _)", + /// format!("{:?}", Foo(10, "Hello".to_string(), PhantomData::)) + /// ); /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] pub fn debug_tuple<'b>(&'b mut self, name: &str) -> DebugTuple<'b, 'a> { @@ -1646,6 +1671,41 @@ impl<'a> Formatter<'a> { /// // prints "{10, 11}" /// println!("{:?}", Foo(vec![10, 11])); /// ``` + /// + /// [`format_args!`]: ../../std/macro.format_args.html + /// + /// In this more complex example, we use [`format_args!`] and `.debug_set()` + /// to build a list of match arms: + /// + /// ```rust + /// use std::fmt; + /// + /// struct Arm<'a, L: 'a, R: 'a>(&'a (L, R)); + /// struct Table<'a, K: 'a, V: 'a>(&'a [(K, V)], V); + /// + /// impl<'a, L, R> fmt::Debug for Arm<'a, L, R> + /// where + /// L: 'a + fmt::Debug, R: 'a + fmt::Debug + /// { + /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + /// L::fmt(&(self.0).0, fmt)?; + /// fmt.write_str(" => ")?; + /// R::fmt(&(self.0).1, fmt) + /// } + /// } + /// + /// impl<'a, K, V> fmt::Debug for Table<'a, K, V> + /// where + /// K: 'a + fmt::Debug, V: 'a + fmt::Debug + /// { + /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + /// fmt.debug_set() + /// .entries(self.0.iter().map(Arm)) + /// .entry(&Arm(&(format_args!("_"), &self.1))) + /// .finish() + /// } + /// } + /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] pub fn debug_set<'b>(&'b mut self) -> DebugSet<'b, 'a> { builders::debug_set_new(self) diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index f8a33961811c0..7d0174a178abf 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -166,6 +166,11 @@ pub trait Unsize { /// are allowed to access `x` after the assignment. Under the hood, both a copy and a move /// can result in bits being copied in memory, although this is sometimes optimized away. /// +/// ## Closures +/// +/// Closure types automatically implement `Copy` if they capture no value from the environment +/// or if all such captured values implement `Copy` themselves. +/// /// ## How can I implement `Copy`? /// /// There are two ways to implement `Copy` on your type. The simplest is to use `derive`: diff --git a/src/libcore/ops/generator.rs b/src/libcore/ops/generator.rs index dc7669d195c13..4b70c5398be4f 100644 --- a/src/libcore/ops/generator.rs +++ b/src/libcore/ops/generator.rs @@ -56,11 +56,11 @@ pub enum GeneratorState { /// return "foo" /// }; /// -/// match generator.resume() { +/// match unsafe { generator.resume() } { /// GeneratorState::Yielded(1) => {} /// _ => panic!("unexpected return from resume"), /// } -/// match generator.resume() { +/// match unsafe { generator.resume() } { /// GeneratorState::Complete("foo") => {} /// _ => panic!("unexpected return from resume"), /// } @@ -98,6 +98,10 @@ pub trait Generator { /// generator will continue executing until it either yields or returns, at /// which point this function will return. /// + /// The function is unsafe because it can be used on an immovable generator. + /// After such a call, the immovable generator must not move again, but + /// this is not enforced by the compiler. + /// /// # Return value /// /// The `GeneratorState` enum returned from this function indicates what @@ -116,7 +120,7 @@ pub trait Generator { /// been returned previously. While generator literals in the language are /// guaranteed to panic on resuming after `Complete`, this is not guaranteed /// for all implementations of the `Generator` trait. - fn resume(&mut self) -> GeneratorState; + unsafe fn resume(&mut self) -> GeneratorState; } #[unstable(feature = "generator_trait", issue = "43122")] @@ -125,7 +129,7 @@ impl<'a, T> Generator for &'a mut T { type Yield = T::Yield; type Return = T::Return; - fn resume(&mut self) -> GeneratorState { + unsafe fn resume(&mut self) -> GeneratorState { (**self).resume() } } diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs deleted file mode 100644 index 81fa0374f549e..0000000000000 --- a/src/libgetopts/lib.rs +++ /dev/null @@ -1,1622 +0,0 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Simple getopt alternative. -//! -//! Construct a vector of options, either by using `reqopt`, `optopt`, and `optflag` -//! or by building them from components yourself, and pass them to `getopts`, -//! along with a vector of actual arguments (not including `argv[0]`). You'll -//! either get a failure code back, or a match. You'll have to verify whether -//! the amount of 'free' arguments in the match is what you expect. Use `opt_*` -//! accessors to get argument values out of the matches object. -//! -//! Single-character options are expected to appear on the command line with a -//! single preceding dash; multiple-character options are expected to be -//! proceeded by two dashes. Options that expect an argument accept their -//! argument following either a space or an equals sign. Single-character -//! options don't require the space. -//! -//! # Example -//! -//! The following example shows simple command line parsing for an application -//! that requires an input file to be specified, accepts an optional output -//! file name following `-o`, and accepts both `-h` and `--help` as optional flags. -//! -//! ```{.rust} -//! #![feature(rustc_private)] -//! -//! extern crate getopts; -//! use getopts::{optopt,optflag,getopts,OptGroup,usage}; -//! use std::env; -//! -//! fn do_work(inp: &str, out: Option) { -//! println!("{}", inp); -//! match out { -//! Some(x) => println!("{}", x), -//! None => println!("No Output"), -//! } -//! } -//! -//! fn print_usage(program: &str, opts: &[OptGroup]) { -//! let brief = format!("Usage: {} [options]", program); -//! print!("{}", usage(&brief, opts)); -//! } -//! -//! fn main() { -//! let args: Vec = env::args().collect(); -//! -//! let program = args[0].clone(); -//! -//! let opts = &[ -//! optopt("o", "", "set output file name", "NAME"), -//! optflag("h", "help", "print this help menu") -//! ]; -//! let matches = match getopts(&args[1..], opts) { -//! Ok(m) => { m } -//! Err(f) => { panic!(f.to_string()) } -//! }; -//! if matches.opt_present("h") { -//! print_usage(&program, opts); -//! return; -//! } -//! let output = matches.opt_str("o"); -//! let input = if !matches.free.is_empty() { -//! matches.free[0].clone() -//! } else { -//! print_usage(&program, opts); -//! return; -//! }; -//! do_work(&input, output); -//! } -//! ``` - -#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", - html_favicon_url = "https://doc.rust-lang.org/favicon.ico", - html_root_url = "https://doc.rust-lang.org/nightly/", - html_playground_url = "https://play.rust-lang.org/", - test(attr(deny(warnings))))] - -#![deny(missing_docs)] -#![deny(warnings)] - -use self::Name::*; -use self::HasArg::*; -use self::Occur::*; -use self::Fail::*; -use self::Optval::*; -use self::SplitWithinState::*; -use self::Whitespace::*; -use self::LengthLimit::*; - -use std::fmt; -use std::iter::repeat; -use std::result; - -/// Name of an option. Either a string or a single char. -#[derive(Clone, PartialEq, Eq, Debug)] -pub enum Name { - /// A string representing the long name of an option. - /// For example: "help" - Long(String), - /// A char representing the short name of an option. - /// For example: 'h' - Short(char), -} - -/// Describes whether an option has an argument. -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub enum HasArg { - /// The option requires an argument. - Yes, - /// The option takes no argument. - No, - /// The option argument is optional. - Maybe, -} - -/// Describes how often an option may occur. -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub enum Occur { - /// The option occurs once. - Req, - /// The option occurs at most once. - Optional, - /// The option occurs zero or more times. - Multi, -} - -/// A description of a possible option. -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct Opt { - /// Name of the option - pub name: Name, - /// Whether it has an argument - pub hasarg: HasArg, - /// How often it can occur - pub occur: Occur, - /// Which options it aliases - pub aliases: Vec, -} - -/// One group of options, e.g., both `-h` and `--help`, along with -/// their shared description and properties. -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct OptGroup { - /// Short name of the option, e.g. `h` for a `-h` option - pub short_name: String, - /// Long name of the option, e.g. `help` for a `--help` option - pub long_name: String, - /// Hint for argument, e.g. `FILE` for a `-o FILE` option - pub hint: String, - /// Description for usage help text - pub desc: String, - /// Whether option has an argument - pub hasarg: HasArg, - /// How often it can occur - pub occur: Occur, -} - -/// Describes whether an option is given at all or has a value. -#[derive(Clone, PartialEq, Eq, Debug)] -enum Optval { - Val(String), - Given, -} - -/// The result of checking command line arguments. Contains a vector -/// of matches and a vector of free strings. -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct Matches { - /// Options that matched - opts: Vec, - /// Values of the Options that matched - vals: Vec>, - /// Free string fragments - pub free: Vec, -} - -/// The type returned when the command line does not conform to the -/// expected format. Use the `Debug` implementation to output detailed -/// information. -#[derive(Clone, PartialEq, Eq, Debug)] -pub enum Fail { - /// The option requires an argument but none was passed. - ArgumentMissing(String), - /// The passed option is not declared among the possible options. - UnrecognizedOption(String), - /// A required option is not present. - OptionMissing(String), - /// A single occurrence option is being used multiple times. - OptionDuplicated(String), - /// There's an argument being passed to a non-argument option. - UnexpectedArgument(String), -} - -/// The type of failure that occurred. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -#[allow(missing_docs)] -pub enum FailType { - ArgumentMissing_, - UnrecognizedOption_, - OptionMissing_, - OptionDuplicated_, - UnexpectedArgument_, -} - -/// The result of parsing a command line with a set of options. -pub type Result = result::Result; - -impl Name { - fn from_str(nm: &str) -> Name { - if nm.len() == 1 { - Short(nm.chars().next().unwrap()) - } else { - Long(nm.to_owned()) - } - } - - fn to_string(&self) -> String { - match *self { - Short(ch) => ch.to_string(), - Long(ref s) => s.to_owned(), - } - } -} - -impl OptGroup { - /// Translate OptGroup into Opt. - /// (Both short and long names correspond to different Opts). - pub fn long_to_short(&self) -> Opt { - let OptGroup { - short_name, - long_name, - hasarg, - occur, - .. - } = (*self).clone(); - - match (short_name.len(), long_name.len()) { - (0, 0) => panic!("this long-format option was given no name"), - (0, _) => { - Opt { - name: Long((long_name)), - hasarg, - occur, - aliases: Vec::new(), - } - } - (1, 0) => { - Opt { - name: Short(short_name.chars().next().unwrap()), - hasarg, - occur, - aliases: Vec::new(), - } - } - (1, _) => { - Opt { - name: Long((long_name)), - hasarg, - occur, - aliases: vec![Opt { - name: Short(short_name.chars().next().unwrap()), - hasarg, - occur, - aliases: Vec::new(), - }], - } - } - _ => panic!("something is wrong with the long-form opt"), - } - } -} - -impl Matches { - fn opt_vals(&self, nm: &str) -> Vec { - match find_opt(&self.opts[..], Name::from_str(nm)) { - Some(id) => self.vals[id].clone(), - None => panic!("No option '{}' defined", nm), - } - } - - fn opt_val(&self, nm: &str) -> Option { - let vals = self.opt_vals(nm); - if vals.is_empty() { - None - } else { - Some(vals[0].clone()) - } - } - - /// Returns true if an option was matched. - pub fn opt_present(&self, nm: &str) -> bool { - !self.opt_vals(nm).is_empty() - } - - /// Returns the number of times an option was matched. - pub fn opt_count(&self, nm: &str) -> usize { - self.opt_vals(nm).len() - } - - /// Returns true if any of several options were matched. - pub fn opts_present(&self, names: &[String]) -> bool { - for nm in names { - match find_opt(&self.opts, Name::from_str(&**nm)) { - Some(id) if !self.vals[id].is_empty() => return true, - _ => (), - }; - } - false - } - - /// Returns the string argument supplied to one of several matching options or `None`. - pub fn opts_str(&self, names: &[String]) -> Option { - for nm in names { - if let Some(Val(ref s)) = self.opt_val(&nm[..]) { - return Some(s.clone()) - } - } - None - } - - /// Returns a vector of the arguments provided to all matches of the given - /// option. - /// - /// Used when an option accepts multiple values. - pub fn opt_strs(&self, nm: &str) -> Vec { - let mut acc: Vec = Vec::new(); - let r = self.opt_vals(nm); - for v in &r { - match *v { - Val(ref s) => acc.push((*s).clone()), - _ => (), - } - } - acc - } - - /// Returns the string argument supplied to a matching option or `None`. - pub fn opt_str(&self, nm: &str) -> Option { - let vals = self.opt_vals(nm); - if vals.is_empty() { - return None::; - } - match vals[0] { - Val(ref s) => Some((*s).clone()), - _ => None, - } - } - - - /// Returns the matching string, a default, or none. - /// - /// Returns none if the option was not present, `def` if the option was - /// present but no argument was provided, and the argument if the option was - /// present and an argument was provided. - pub fn opt_default(&self, nm: &str, def: &str) -> Option { - let vals = self.opt_vals(nm); - if vals.is_empty() { - None - } else { - match vals[0] { - Val(ref s) => Some((*s).clone()), - _ => Some(def.to_owned()), - } - } - } -} - -fn is_arg(arg: &str) -> bool { - arg.len() > 1 && arg.as_bytes()[0] == b'-' -} - -fn find_opt(opts: &[Opt], nm: Name) -> Option { - // Search main options. - let pos = opts.iter().position(|opt| opt.name == nm); - if pos.is_some() { - return pos; - } - - // Search in aliases. - for candidate in opts { - if candidate.aliases.iter().position(|opt| opt.name == nm).is_some() { - return opts.iter().position(|opt| opt.name == candidate.name); - } - } - - None -} - -/// Create a long option that is required and takes an argument. -/// -/// * `short_name` - e.g. `"h"` for a `-h` option, or `""` for none -/// * `long_name` - e.g. `"help"` for a `--help` option, or `""` for none -/// * `desc` - Description for usage help -/// * `hint` - Hint that is used in place of the argument in the usage help, -/// e.g. `"FILE"` for a `-o FILE` option -pub fn reqopt(short_name: &str, long_name: &str, desc: &str, hint: &str) -> OptGroup { - let len = short_name.len(); - assert!(len == 1 || len == 0); - OptGroup { - short_name: short_name.to_owned(), - long_name: long_name.to_owned(), - hint: hint.to_owned(), - desc: desc.to_owned(), - hasarg: Yes, - occur: Req, - } -} - -/// Create a long option that is optional and takes an argument. -/// -/// * `short_name` - e.g. `"h"` for a `-h` option, or `""` for none -/// * `long_name` - e.g. `"help"` for a `--help` option, or `""` for none -/// * `desc` - Description for usage help -/// * `hint` - Hint that is used in place of the argument in the usage help, -/// e.g. `"FILE"` for a `-o FILE` option -pub fn optopt(short_name: &str, long_name: &str, desc: &str, hint: &str) -> OptGroup { - let len = short_name.len(); - assert!(len == 1 || len == 0); - OptGroup { - short_name: short_name.to_owned(), - long_name: long_name.to_owned(), - hint: hint.to_owned(), - desc: desc.to_owned(), - hasarg: Yes, - occur: Optional, - } -} - -/// Create a long option that is optional and does not take an argument. -/// -/// * `short_name` - e.g. `"h"` for a `-h` option, or `""` for none -/// * `long_name` - e.g. `"help"` for a `--help` option, or `""` for none -/// * `desc` - Description for usage help -pub fn optflag(short_name: &str, long_name: &str, desc: &str) -> OptGroup { - let len = short_name.len(); - assert!(len == 1 || len == 0); - OptGroup { - short_name: short_name.to_owned(), - long_name: long_name.to_owned(), - hint: "".to_owned(), - desc: desc.to_owned(), - hasarg: No, - occur: Optional, - } -} - -/// Create a long option that can occur more than once and does not -/// take an argument. -/// -/// * `short_name` - e.g. `"h"` for a `-h` option, or `""` for none -/// * `long_name` - e.g. `"help"` for a `--help` option, or `""` for none -/// * `desc` - Description for usage help -pub fn optflagmulti(short_name: &str, long_name: &str, desc: &str) -> OptGroup { - let len = short_name.len(); - assert!(len == 1 || len == 0); - OptGroup { - short_name: short_name.to_owned(), - long_name: long_name.to_owned(), - hint: "".to_owned(), - desc: desc.to_owned(), - hasarg: No, - occur: Multi, - } -} - -/// Create a long option that is optional and takes an optional argument. -/// -/// * `short_name` - e.g. `"h"` for a `-h` option, or `""` for none -/// * `long_name` - e.g. `"help"` for a `--help` option, or `""` for none -/// * `desc` - Description for usage help -/// * `hint` - Hint that is used in place of the argument in the usage help, -/// e.g. `"FILE"` for a `-o FILE` option -pub fn optflagopt(short_name: &str, long_name: &str, desc: &str, hint: &str) -> OptGroup { - let len = short_name.len(); - assert!(len == 1 || len == 0); - OptGroup { - short_name: short_name.to_owned(), - long_name: long_name.to_owned(), - hint: hint.to_owned(), - desc: desc.to_owned(), - hasarg: Maybe, - occur: Optional, - } -} - -/// Create a long option that is optional, takes an argument, and may occur -/// multiple times. -/// -/// * `short_name` - e.g. `"h"` for a `-h` option, or `""` for none -/// * `long_name` - e.g. `"help"` for a `--help` option, or `""` for none -/// * `desc` - Description for usage help -/// * `hint` - Hint that is used in place of the argument in the usage help, -/// e.g. `"FILE"` for a `-o FILE` option -pub fn optmulti(short_name: &str, long_name: &str, desc: &str, hint: &str) -> OptGroup { - let len = short_name.len(); - assert!(len == 1 || len == 0); - OptGroup { - short_name: short_name.to_owned(), - long_name: long_name.to_owned(), - hint: hint.to_owned(), - desc: desc.to_owned(), - hasarg: Yes, - occur: Multi, - } -} - -/// Create a generic option group, stating all parameters explicitly -pub fn opt(short_name: &str, - long_name: &str, - desc: &str, - hint: &str, - hasarg: HasArg, - occur: Occur) - -> OptGroup { - let len = short_name.len(); - assert!(len == 1 || len == 0); - OptGroup { - short_name: short_name.to_owned(), - long_name: long_name.to_owned(), - hint: hint.to_owned(), - desc: desc.to_owned(), - hasarg, - occur, - } -} - -impl fmt::Display for Fail { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - ArgumentMissing(ref nm) => write!(f, "Argument to option '{}' missing.", *nm), - UnrecognizedOption(ref nm) => write!(f, "Unrecognized option: '{}'.", *nm), - OptionMissing(ref nm) => write!(f, "Required option '{}' missing.", *nm), - OptionDuplicated(ref nm) => write!(f, "Option '{}' given more than once.", *nm), - UnexpectedArgument(ref nm) => write!(f, "Option '{}' does not take an argument.", *nm), - } - } -} - -/// Parse command line arguments according to the provided options. -/// -/// On success returns `Ok(Matches)`. Use methods such as `opt_present` -/// `opt_str`, etc. to interrogate results. -/// # Panics -/// -/// Returns `Err(Fail)` on failure: use the `Debug` implementation of `Fail` to display -/// information about it. -pub fn getopts(args: &[String], optgrps: &[OptGroup]) -> Result { - let opts: Vec = optgrps.iter().map(|x| x.long_to_short()).collect(); - let n_opts = opts.len(); - - fn f(_x: usize) -> Vec { - Vec::new() - } - - let mut vals: Vec<_> = (0..n_opts).map(f).collect(); - let mut free: Vec = Vec::new(); - let l = args.len(); - let mut i = 0; - while i < l { - let cur = args[i].clone(); - let curlen = cur.len(); - if !is_arg(&cur[..]) { - free.push(cur); - } else if cur == "--" { - let mut j = i + 1; - while j < l { - free.push(args[j].clone()); - j += 1; - } - break; - } else { - let mut names; - let mut i_arg = None; - if cur.as_bytes()[1] == b'-' { - let tail = &cur[2..curlen]; - let tail_eq: Vec<&str> = tail.splitn(2, '=').collect(); - if tail_eq.len() <= 1 { - names = vec![Long(tail.to_owned())]; - } else { - names = vec![Long(tail_eq[0].to_owned())]; - i_arg = Some(tail_eq[1].to_owned()); - } - } else { - let mut j = 1; - names = Vec::new(); - while j < curlen { - let ch = cur[j..].chars().next().unwrap(); - let opt = Short(ch); - - // In a series of potential options (eg. -aheJ), if we - // see one which takes an argument, we assume all - // subsequent characters make up the argument. This - // allows options such as -L/usr/local/lib/foo to be - // interpreted correctly - - let opt_id = match find_opt(&opts, opt.clone()) { - Some(id) => id, - None => return Err(UnrecognizedOption(opt.to_string())), - }; - - names.push(opt); - - let arg_follows = match opts[opt_id].hasarg { - Yes | Maybe => true, - No => false, - }; - - let next = j + ch.len_utf8(); - if arg_follows && next < curlen { - i_arg = Some((&cur[next..curlen]).to_owned()); - break; - } - - j = next; - } - } - let mut name_pos = 0; - for nm in &names { - name_pos += 1; - let optid = match find_opt(&opts, (*nm).clone()) { - Some(id) => id, - None => return Err(UnrecognizedOption(nm.to_string())), - }; - match opts[optid].hasarg { - No => { - if name_pos == names.len() && !i_arg.is_none() { - return Err(UnexpectedArgument(nm.to_string())); - } - let v = &mut vals[optid]; - v.push(Given); - } - Maybe => { - if !i_arg.is_none() { - let v = &mut vals[optid]; - v.push(Val((i_arg.clone()).unwrap())); - } else if name_pos < names.len() || i + 1 == l || is_arg(&args[i + 1][..]) { - let v = &mut vals[optid]; - v.push(Given); - } else { - i += 1; - let v = &mut vals[optid]; - v.push(Val(args[i].clone())); - } - } - Yes => { - if !i_arg.is_none() { - let v = &mut vals[optid]; - v.push(Val(i_arg.clone().unwrap())); - } else if i + 1 == l { - return Err(ArgumentMissing(nm.to_string())); - } else { - i += 1; - let v = &mut vals[optid]; - v.push(Val(args[i].clone())); - } - } - } - } - } - i += 1; - } - for i in 0..n_opts { - let n = vals[i].len(); - let occ = opts[i].occur; - if occ == Req && n == 0 { - return Err(OptionMissing(opts[i].name.to_string())); - } - if occ != Multi && n > 1 { - return Err(OptionDuplicated(opts[i].name.to_string())); - } - } - Ok(Matches { - opts, - vals, - free, - }) -} - -/// Derive a usage message from a set of long options. -pub fn usage(brief: &str, opts: &[OptGroup]) -> String { - - let desc_sep = format!("\n{}", repeat(" ").take(24).collect::()); - - let rows = opts.iter().map(|optref| { - let OptGroup{short_name, - long_name, - hint, - desc, - hasarg, - ..} = (*optref).clone(); - - let mut row = repeat(" ").take(4).collect::(); - - // short option - match short_name.len() { - 0 => {} - 1 => { - row.push('-'); - row.push_str(&short_name[..]); - row.push(' '); - } - _ => panic!("the short name should only be 1 ascii char long"), - } - - // long option - match long_name.len() { - 0 => {} - _ => { - row.push_str("--"); - row.push_str(&long_name[..]); - row.push(' '); - } - } - - // arg - match hasarg { - No => {} - Yes => row.push_str(&hint[..]), - Maybe => { - row.push('['); - row.push_str(&hint[..]); - row.push(']'); - } - } - - // FIXME(https://github.com/rust-lang-nursery/getopts/issues/7) - // should be graphemes not codepoints - // - // here we just need to indent the start of the description - let rowlen = row.chars().count(); - if rowlen < 24 { - for _ in 0..24 - rowlen { - row.push(' '); - } - } else { - row.push_str(&desc_sep[..]); - } - - // Normalize desc to contain words separated by one space character - let mut desc_normalized_whitespace = String::new(); - for word in desc.split_whitespace() { - desc_normalized_whitespace.push_str(word); - desc_normalized_whitespace.push(' '); - } - - // FIXME(https://github.com/rust-lang-nursery/getopts/issues/7) - // should be graphemes not codepoints - let mut desc_rows = Vec::new(); - each_split_within(&desc_normalized_whitespace[..], 54, |substr| { - desc_rows.push(substr.to_owned()); - true - }); - - // FIXME(https://github.com/rust-lang-nursery/getopts/issues/7) - // should be graphemes not codepoints - // - // wrapped description - row.push_str(&desc_rows.join(&desc_sep[..])); - - row - }); - - format!("{}\n\nOptions:\n{}\n", - brief, - rows.collect::>().join("\n")) -} - -fn format_option(opt: &OptGroup) -> String { - let mut line = String::new(); - - if opt.occur != Req { - line.push('['); - } - - // Use short_name is possible, but fallback to long_name. - if !opt.short_name.is_empty() { - line.push('-'); - line.push_str(&opt.short_name[..]); - } else { - line.push_str("--"); - line.push_str(&opt.long_name[..]); - } - - if opt.hasarg != No { - line.push(' '); - if opt.hasarg == Maybe { - line.push('['); - } - line.push_str(&opt.hint[..]); - if opt.hasarg == Maybe { - line.push(']'); - } - } - - if opt.occur != Req { - line.push(']'); - } - if opt.occur == Multi { - line.push_str(".."); - } - - line -} - -/// Derive a short one-line usage summary from a set of long options. -pub fn short_usage(program_name: &str, opts: &[OptGroup]) -> String { - let mut line = format!("Usage: {} ", program_name); - line.push_str(&opts.iter() - .map(format_option) - .collect::>() - .join(" ")[..]); - line -} - -#[derive(Copy, Clone)] -enum SplitWithinState { - A, // leading whitespace, initial state - B, // words - C, // internal and trailing whitespace -} -#[derive(Copy, Clone)] -enum Whitespace { - Ws, // current char is whitespace - Cr, // current char is not whitespace -} -#[derive(Copy, Clone)] -enum LengthLimit { - UnderLim, // current char makes current substring still fit in limit - OverLim, // current char makes current substring no longer fit in limit -} - - -/// Splits a string into substrings with possibly internal whitespace, -/// each of them at most `lim` bytes long. The substrings have leading and trailing -/// whitespace removed, and are only cut at whitespace boundaries. -/// -/// Note: Function was moved here from `std::str` because this module is the only place that -/// uses it, and because it was too specific for a general string function. -/// -/// # Panics -/// -/// Panics during iteration if the string contains a non-whitespace -/// sequence longer than the limit. -fn each_split_within(ss: &str, lim: usize, mut it: F) -> bool - where F: FnMut(&str) -> bool -{ - // Just for fun, let's write this as a state machine: - - let mut slice_start = 0; - let mut last_start = 0; - let mut last_end = 0; - let mut state = A; - let mut fake_i = ss.len(); - let mut lim = lim; - - let mut cont = true; - - // if the limit is larger than the string, lower it to save cycles - if lim >= fake_i { - lim = fake_i; - } - - let mut machine = |cont: &mut bool, (i, c): (usize, char)| -> bool { - let whitespace = if c.is_whitespace() { - Ws - } else { - Cr - }; - let limit = if (i - slice_start + 1) <= lim { - UnderLim - } else { - OverLim - }; - - state = match (state, whitespace, limit) { - (A, Ws, _) => A, - (A, Cr, _) => { - slice_start = i; - last_start = i; - B - } - - (B, Cr, UnderLim) => B, - (B, Cr, OverLim) if (i - last_start + 1) > lim => { - panic!("word starting with {} longer than limit!", - &ss[last_start..i + 1]) - } - (B, Cr, OverLim) => { - *cont = it(&ss[slice_start..last_end]); - slice_start = last_start; - B - } - (B, Ws, UnderLim) => { - last_end = i; - C - } - (B, Ws, OverLim) => { - last_end = i; - *cont = it(&ss[slice_start..last_end]); - A - } - - (C, Cr, UnderLim) => { - last_start = i; - B - } - (C, Cr, OverLim) => { - *cont = it(&ss[slice_start..last_end]); - slice_start = i; - last_start = i; - last_end = i; - B - } - (C, Ws, OverLim) => { - *cont = it(&ss[slice_start..last_end]); - A - } - (C, Ws, UnderLim) => C, - }; - - *cont - }; - - ss.char_indices().all(|x| machine(&mut cont, x)); - - // Let the automaton 'run out' by supplying trailing whitespace - while cont && - match state { - B | C => true, - A => false, - } { - machine(&mut cont, (fake_i, ' ')); - fake_i += 1; - } - cont -} - -#[test] -fn test_split_within() { - fn t(s: &str, i: usize, u: &[String]) { - let mut v = Vec::new(); - each_split_within(s, i, |s| { - v.push(s.to_string()); - true - }); - assert!(v.iter().zip(u).all(|(a, b)| a == b)); - } - t("", 0, &[]); - t("", 15, &[]); - t("hello", 15, &["hello".to_string()]); - t("\nMary had a little lamb\nLittle lamb\n", - 15, - &["Mary had a".to_string(), "little lamb".to_string(), "Little lamb".to_string()]); - t("\nMary had a little lamb\nLittle lamb\n", - ::std::usize::MAX, - &["Mary had a little lamb\nLittle lamb".to_string()]); -} - -#[cfg(test)] -mod tests { - use super::*; - - use std::result::Result::{Err, Ok}; - use std::result; - - // Tests for reqopt - #[test] - fn test_reqopt() { - let long_args = vec!["--test=20".to_string()]; - let opts = vec![reqopt("t", "test", "testing", "TEST")]; - let rs = getopts(&long_args, &opts); - match rs { - Ok(ref m) => { - assert!(m.opt_present("test")); - assert_eq!(m.opt_str("test").unwrap(), "20"); - assert!(m.opt_present("t")); - assert_eq!(m.opt_str("t").unwrap(), "20"); - } - _ => { - panic!("test_reqopt failed (long arg)"); - } - } - let short_args = vec!["-t".to_string(), "20".to_string()]; - match getopts(&short_args, &opts) { - Ok(ref m) => { - assert!((m.opt_present("test"))); - assert_eq!(m.opt_str("test").unwrap(), "20"); - assert!((m.opt_present("t"))); - assert_eq!(m.opt_str("t").unwrap(), "20"); - } - _ => { - panic!("test_reqopt failed (short arg)"); - } - } - } - - #[test] - fn test_reqopt_missing() { - let args = vec!["blah".to_string()]; - let opts = vec![reqopt("t", "test", "testing", "TEST")]; - let rs = getopts(&args, &opts); - match rs { - Err(OptionMissing(_)) => {} - _ => panic!(), - } - } - - #[test] - fn test_reqopt_no_arg() { - let long_args = vec!["--test".to_string()]; - let opts = vec![reqopt("t", "test", "testing", "TEST")]; - let rs = getopts(&long_args, &opts); - match rs { - Err(ArgumentMissing(_)) => {} - _ => panic!(), - } - let short_args = vec!["-t".to_string()]; - match getopts(&short_args, &opts) { - Err(ArgumentMissing(_)) => {} - _ => panic!(), - } - } - - #[test] - fn test_reqopt_multi() { - let args = vec!["--test=20".to_string(), "-t".to_string(), "30".to_string()]; - let opts = vec![reqopt("t", "test", "testing", "TEST")]; - let rs = getopts(&args, &opts); - match rs { - Err(OptionDuplicated(_)) => {} - _ => panic!(), - } - } - - // Tests for optopt - #[test] - fn test_optopt() { - let long_args = vec!["--test=20".to_string()]; - let opts = vec![optopt("t", "test", "testing", "TEST")]; - let rs = getopts(&long_args, &opts); - match rs { - Ok(ref m) => { - assert!(m.opt_present("test")); - assert_eq!(m.opt_str("test").unwrap(), "20"); - assert!((m.opt_present("t"))); - assert_eq!(m.opt_str("t").unwrap(), "20"); - } - _ => panic!(), - } - let short_args = vec!["-t".to_string(), "20".to_string()]; - match getopts(&short_args, &opts) { - Ok(ref m) => { - assert!((m.opt_present("test"))); - assert_eq!(m.opt_str("test").unwrap(), "20"); - assert!((m.opt_present("t"))); - assert_eq!(m.opt_str("t").unwrap(), "20"); - } - _ => panic!(), - } - } - - #[test] - fn test_optopt_missing() { - let args = vec!["blah".to_string()]; - let opts = vec![optopt("t", "test", "testing", "TEST")]; - let rs = getopts(&args, &opts); - match rs { - Ok(ref m) => { - assert!(!m.opt_present("test")); - assert!(!m.opt_present("t")); - } - _ => panic!(), - } - } - - #[test] - fn test_optopt_no_arg() { - let long_args = vec!["--test".to_string()]; - let opts = vec![optopt("t", "test", "testing", "TEST")]; - let rs = getopts(&long_args, &opts); - match rs { - Err(ArgumentMissing(_)) => {} - _ => panic!(), - } - let short_args = vec!["-t".to_string()]; - match getopts(&short_args, &opts) { - Err(ArgumentMissing(_)) => {} - _ => panic!(), - } - } - - #[test] - fn test_optopt_multi() { - let args = vec!["--test=20".to_string(), "-t".to_string(), "30".to_string()]; - let opts = vec![optopt("t", "test", "testing", "TEST")]; - let rs = getopts(&args, &opts); - match rs { - Err(OptionDuplicated(_)) => {} - _ => panic!(), - } - } - - // Tests for optflag - #[test] - fn test_optflag() { - let long_args = vec!["--test".to_string()]; - let opts = vec![optflag("t", "test", "testing")]; - let rs = getopts(&long_args, &opts); - match rs { - Ok(ref m) => { - assert!(m.opt_present("test")); - assert!(m.opt_present("t")); - } - _ => panic!(), - } - let short_args = vec!["-t".to_string()]; - match getopts(&short_args, &opts) { - Ok(ref m) => { - assert!(m.opt_present("test")); - assert!(m.opt_present("t")); - } - _ => panic!(), - } - } - - #[test] - fn test_optflag_missing() { - let args = vec!["blah".to_string()]; - let opts = vec![optflag("t", "test", "testing")]; - let rs = getopts(&args, &opts); - match rs { - Ok(ref m) => { - assert!(!m.opt_present("test")); - assert!(!m.opt_present("t")); - } - _ => panic!(), - } - } - - #[test] - fn test_optflag_long_arg() { - let args = vec!["--test=20".to_string()]; - let opts = vec![optflag("t", "test", "testing")]; - let rs = getopts(&args, &opts); - match rs { - Err(UnexpectedArgument(_)) => {} - _ => panic!(), - } - } - - #[test] - fn test_optflag_multi() { - let args = vec!["--test".to_string(), "-t".to_string()]; - let opts = vec![optflag("t", "test", "testing")]; - let rs = getopts(&args, &opts); - match rs { - Err(OptionDuplicated(_)) => {} - _ => panic!(), - } - } - - #[test] - fn test_optflag_short_arg() { - let args = vec!["-t".to_string(), "20".to_string()]; - let opts = vec![optflag("t", "test", "testing")]; - let rs = getopts(&args, &opts); - match rs { - Ok(ref m) => { - // The next variable after the flag is just a free argument - - assert!(m.free[0] == "20"); - } - _ => panic!(), - } - } - - // Tests for optflagmulti - #[test] - fn test_optflagmulti_short1() { - let args = vec!["-v".to_string()]; - let opts = vec![optflagmulti("v", "verbose", "verbosity")]; - let rs = getopts(&args, &opts); - match rs { - Ok(ref m) => { - assert_eq!(m.opt_count("v"), 1); - } - _ => panic!(), - } - } - - #[test] - fn test_optflagmulti_short2a() { - let args = vec!["-v".to_string(), "-v".to_string()]; - let opts = vec![optflagmulti("v", "verbose", "verbosity")]; - let rs = getopts(&args, &opts); - match rs { - Ok(ref m) => { - assert_eq!(m.opt_count("v"), 2); - } - _ => panic!(), - } - } - - #[test] - fn test_optflagmulti_short2b() { - let args = vec!["-vv".to_string()]; - let opts = vec![optflagmulti("v", "verbose", "verbosity")]; - let rs = getopts(&args, &opts); - match rs { - Ok(ref m) => { - assert_eq!(m.opt_count("v"), 2); - } - _ => panic!(), - } - } - - #[test] - fn test_optflagmulti_long1() { - let args = vec!["--verbose".to_string()]; - let opts = vec![optflagmulti("v", "verbose", "verbosity")]; - let rs = getopts(&args, &opts); - match rs { - Ok(ref m) => { - assert_eq!(m.opt_count("verbose"), 1); - } - _ => panic!(), - } - } - - #[test] - fn test_optflagmulti_long2() { - let args = vec!["--verbose".to_string(), "--verbose".to_string()]; - let opts = vec![optflagmulti("v", "verbose", "verbosity")]; - let rs = getopts(&args, &opts); - match rs { - Ok(ref m) => { - assert_eq!(m.opt_count("verbose"), 2); - } - _ => panic!(), - } - } - - #[test] - fn test_optflagmulti_mix() { - let args = vec!["--verbose".to_string(), - "-v".to_string(), - "-vv".to_string(), - "verbose".to_string()]; - let opts = vec![optflagmulti("v", "verbose", "verbosity")]; - let rs = getopts(&args, &opts); - match rs { - Ok(ref m) => { - assert_eq!(m.opt_count("verbose"), 4); - assert_eq!(m.opt_count("v"), 4); - } - _ => panic!(), - } - } - - // Tests for optmulti - #[test] - fn test_optmulti() { - let long_args = vec!["--test=20".to_string()]; - let opts = vec![optmulti("t", "test", "testing", "TEST")]; - let rs = getopts(&long_args, &opts); - match rs { - Ok(ref m) => { - assert!((m.opt_present("test"))); - assert_eq!(m.opt_str("test").unwrap(), "20"); - assert!((m.opt_present("t"))); - assert_eq!(m.opt_str("t").unwrap(), "20"); - } - _ => panic!(), - } - let short_args = vec!["-t".to_string(), "20".to_string()]; - match getopts(&short_args, &opts) { - Ok(ref m) => { - assert!((m.opt_present("test"))); - assert_eq!(m.opt_str("test").unwrap(), "20"); - assert!((m.opt_present("t"))); - assert_eq!(m.opt_str("t").unwrap(), "20"); - } - _ => panic!(), - } - } - - #[test] - fn test_optmulti_missing() { - let args = vec!["blah".to_string()]; - let opts = vec![optmulti("t", "test", "testing", "TEST")]; - let rs = getopts(&args, &opts); - match rs { - Ok(ref m) => { - assert!(!m.opt_present("test")); - assert!(!m.opt_present("t")); - } - _ => panic!(), - } - } - - #[test] - fn test_optmulti_no_arg() { - let long_args = vec!["--test".to_string()]; - let opts = vec![optmulti("t", "test", "testing", "TEST")]; - let rs = getopts(&long_args, &opts); - match rs { - Err(ArgumentMissing(_)) => {} - _ => panic!(), - } - let short_args = vec!["-t".to_string()]; - match getopts(&short_args, &opts) { - Err(ArgumentMissing(_)) => {} - _ => panic!(), - } - } - - #[test] - fn test_optmulti_multi() { - let args = vec!["--test=20".to_string(), "-t".to_string(), "30".to_string()]; - let opts = vec![optmulti("t", "test", "testing", "TEST")]; - let rs = getopts(&args, &opts); - match rs { - Ok(ref m) => { - assert!(m.opt_present("test")); - assert_eq!(m.opt_str("test").unwrap(), "20"); - assert!(m.opt_present("t")); - assert_eq!(m.opt_str("t").unwrap(), "20"); - let pair = m.opt_strs("test"); - assert!(pair[0] == "20"); - assert!(pair[1] == "30"); - } - _ => panic!(), - } - } - - #[test] - fn test_unrecognized_option() { - let long_args = vec!["--untest".to_string()]; - let opts = vec![optmulti("t", "test", "testing", "TEST")]; - let rs = getopts(&long_args, &opts); - match rs { - Err(UnrecognizedOption(_)) => {} - _ => panic!(), - } - let short_args = vec!["-u".to_string()]; - match getopts(&short_args, &opts) { - Err(UnrecognizedOption(_)) => {} - _ => panic!(), - } - } - - #[test] - fn test_combined() { - let args = vec!["prog".to_string(), - "free1".to_string(), - "-s".to_string(), - "20".to_string(), - "free2".to_string(), - "--flag".to_string(), - "--long=30".to_string(), - "-f".to_string(), - "-m".to_string(), - "40".to_string(), - "-m".to_string(), - "50".to_string(), - "-n".to_string(), - "-A B".to_string(), - "-n".to_string(), - "-60 70".to_string()]; - let opts = vec![optopt("s", "something", "something", "SOMETHING"), - optflag("", "flag", "a flag"), - reqopt("", "long", "hi", "LONG"), - optflag("f", "", "another flag"), - optmulti("m", "", "mmmmmm", "YUM"), - optmulti("n", "", "nothing", "NOTHING"), - optopt("", "notpresent", "nothing to see here", "NOPE")]; - let rs = getopts(&args, &opts); - match rs { - Ok(ref m) => { - assert!(m.free[0] == "prog"); - assert!(m.free[1] == "free1"); - assert_eq!(m.opt_str("s").unwrap(), "20"); - assert!(m.free[2] == "free2"); - assert!((m.opt_present("flag"))); - assert_eq!(m.opt_str("long").unwrap(), "30"); - assert!((m.opt_present("f"))); - let pair = m.opt_strs("m"); - assert!(pair[0] == "40"); - assert!(pair[1] == "50"); - let pair = m.opt_strs("n"); - assert!(pair[0] == "-A B"); - assert!(pair[1] == "-60 70"); - assert!((!m.opt_present("notpresent"))); - } - _ => panic!(), - } - } - - #[test] - fn test_multi() { - let opts = vec![optopt("e", "", "encrypt", "ENCRYPT"), - optopt("", "encrypt", "encrypt", "ENCRYPT"), - optopt("f", "", "flag", "FLAG")]; - - let args_single = vec!["-e".to_string(), "foo".to_string()]; - let matches_single = &match getopts(&args_single, &opts) { - result::Result::Ok(m) => m, - result::Result::Err(_) => panic!(), - }; - assert!(matches_single.opts_present(&["e".to_string()])); - assert!(matches_single.opts_present(&["encrypt".to_string(), "e".to_string()])); - assert!(matches_single.opts_present(&["e".to_string(), "encrypt".to_string()])); - assert!(!matches_single.opts_present(&["encrypt".to_string()])); - assert!(!matches_single.opts_present(&["thing".to_string()])); - assert!(!matches_single.opts_present(&[])); - - assert_eq!(matches_single.opts_str(&["e".to_string()]).unwrap(), "foo"); - assert_eq!(matches_single.opts_str(&["e".to_string(), "encrypt".to_string()]).unwrap(), - "foo"); - assert_eq!(matches_single.opts_str(&["encrypt".to_string(), "e".to_string()]).unwrap(), - "foo"); - - let args_both = vec!["-e".to_string(), - "foo".to_string(), - "--encrypt".to_string(), - "foo".to_string()]; - let matches_both = &match getopts(&args_both, &opts) { - result::Result::Ok(m) => m, - result::Result::Err(_) => panic!(), - }; - assert!(matches_both.opts_present(&["e".to_string()])); - assert!(matches_both.opts_present(&["encrypt".to_string()])); - assert!(matches_both.opts_present(&["encrypt".to_string(), "e".to_string()])); - assert!(matches_both.opts_present(&["e".to_string(), "encrypt".to_string()])); - assert!(!matches_both.opts_present(&["f".to_string()])); - assert!(!matches_both.opts_present(&["thing".to_string()])); - assert!(!matches_both.opts_present(&[])); - - assert_eq!(matches_both.opts_str(&["e".to_string()]).unwrap(), "foo"); - assert_eq!(matches_both.opts_str(&["encrypt".to_string()]).unwrap(), - "foo"); - assert_eq!(matches_both.opts_str(&["e".to_string(), "encrypt".to_string()]).unwrap(), - "foo"); - assert_eq!(matches_both.opts_str(&["encrypt".to_string(), "e".to_string()]).unwrap(), - "foo"); - } - - #[test] - fn test_nospace() { - let args = vec!["-Lfoo".to_string(), "-M.".to_string()]; - let opts = vec![optmulti("L", "", "library directory", "LIB"), - optmulti("M", "", "something", "MMMM")]; - let matches = &match getopts(&args, &opts) { - result::Result::Ok(m) => m, - result::Result::Err(_) => panic!(), - }; - assert!(matches.opts_present(&["L".to_string()])); - assert_eq!(matches.opts_str(&["L".to_string()]).unwrap(), "foo"); - assert!(matches.opts_present(&["M".to_string()])); - assert_eq!(matches.opts_str(&["M".to_string()]).unwrap(), "."); - - } - - #[test] - fn test_nospace_conflict() { - let args = vec!["-vvLverbose".to_string(), "-v".to_string()]; - let opts = vec![optmulti("L", "", "library directory", "LIB"), - optflagmulti("v", "verbose", "Verbose")]; - let matches = &match getopts(&args, &opts) { - result::Result::Ok(m) => m, - result::Result::Err(e) => panic!("{}", e), - }; - assert!(matches.opts_present(&["L".to_string()])); - assert_eq!(matches.opts_str(&["L".to_string()]).unwrap(), "verbose"); - assert!(matches.opts_present(&["v".to_string()])); - assert_eq!(3, matches.opt_count("v")); - } - - #[test] - fn test_long_to_short() { - let mut short = Opt { - name: Name::Long("banana".to_string()), - hasarg: HasArg::Yes, - occur: Occur::Req, - aliases: Vec::new(), - }; - short.aliases = vec![Opt { - name: Name::Short('b'), - hasarg: HasArg::Yes, - occur: Occur::Req, - aliases: Vec::new(), - }]; - let verbose = reqopt("b", "banana", "some bananas", "VAL"); - - assert!(verbose.long_to_short() == short); - } - - #[test] - fn test_aliases_long_and_short() { - let opts = vec![optflagmulti("a", "apple", "Desc")]; - - let args = vec!["-a".to_string(), "--apple".to_string(), "-a".to_string()]; - - let matches = getopts(&args, &opts).unwrap(); - assert_eq!(3, matches.opt_count("a")); - assert_eq!(3, matches.opt_count("apple")); - } - - #[test] - fn test_usage() { - let optgroups = vec![reqopt("b", "banana", "Desc", "VAL"), - optopt("a", "012345678901234567890123456789", "Desc", "VAL"), - optflag("k", "kiwi", "Desc"), - optflagopt("p", "", "Desc", "VAL"), - optmulti("l", "", "Desc", "VAL")]; - - let expected = -"Usage: fruits - -Options: - -b --banana VAL Desc - -a --012345678901234567890123456789 VAL - Desc - -k --kiwi Desc - -p [VAL] Desc - -l VAL Desc -"; - - let generated_usage = usage("Usage: fruits", &optgroups); - - assert_eq!(generated_usage, expected); - } - - #[test] - fn test_usage_description_wrapping() { - // indentation should be 24 spaces - // lines wrap after 78: or rather descriptions wrap after 54 - - let optgroups = vec![optflag("k", - "kiwi", - // 54 - "This is a long description which won't be wrapped..+.."), - optflag("a", - "apple", - "This is a long description which _will_ be wrapped..+..")]; - - let expected = -"Usage: fruits - -Options: - -k --kiwi This is a long description which won't be wrapped..+.. - -a --apple This is a long description which _will_ be - wrapped..+.. -"; - - let usage = usage("Usage: fruits", &optgroups); - - assert!(usage == expected) - } - - #[test] - fn test_usage_description_multibyte_handling() { - let optgroups = vec![optflag("k", - "k\u{2013}w\u{2013}", - "The word kiwi is normally spelled with two i's"), - optflag("a", - "apple", - "This \u{201C}description\u{201D} has some characters that \ - could confuse the line wrapping; an apple costs 0.51€ in \ - some parts of Europe.")]; - - let expected = -"Usage: fruits - -Options: - -k --k–w– The word kiwi is normally spelled with two i's - -a --apple This “description” has some characters that could - confuse the line wrapping; an apple costs 0.51€ in - some parts of Europe. -"; - - let usage = usage("Usage: fruits", &optgroups); - - assert!(usage == expected) - } - - #[test] - fn test_short_usage() { - let optgroups = vec![reqopt("b", "banana", "Desc", "VAL"), - optopt("a", "012345678901234567890123456789", "Desc", "VAL"), - optflag("k", "kiwi", "Desc"), - optflagopt("p", "", "Desc", "VAL"), - optmulti("l", "", "Desc", "VAL")]; - - let expected = "Usage: fruits -b VAL [-a VAL] [-k] [-p [VAL]] [-l VAL]..".to_string(); - let generated_usage = short_usage("fruits", &optgroups); - - assert_eq!(generated_usage, expected); - } - - #[test] - fn test_args_with_equals() { - let args = vec!["--one".to_string(), "A=B".to_string(), - "--two=C=D".to_string()]; - let opts = vec![optopt("o", "one", "One", "INFO"), - optopt("t", "two", "Two", "INFO")]; - let matches = &match getopts(&args, &opts) { - result::Result::Ok(m) => m, - result::Result::Err(e) => panic!("{}", e) - }; - assert_eq!(matches.opts_str(&["o".to_string()]).unwrap(), "A=B"); - assert_eq!(matches.opts_str(&["t".to_string()]).unwrap(), "C=D"); - } -} diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 8bcec79d99f17..42cda6a05a1a7 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -617,8 +617,6 @@ define_dep_nodes!( <'tcx> [input] MissingExternCrateItem(CrateNum), [input] UsedCrateSource(CrateNum), [input] PostorderCnums, - [] HasCloneClosures(CrateNum), - [] HasCopyClosures(CrateNum), // This query is not expected to have inputs -- as a result, it's // not a good candidate for "replay" because it's essentially a diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 2fd875c344767..e22e2b5570394 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -1764,12 +1764,12 @@ The `main` function was incorrectly declared. Erroneous code example: ```compile_fail,E0580 -fn main() -> i32 { // error: main function has wrong type - 0 +fn main(x: i32) { // error: main function has wrong type + println!("{}", x); } ``` -The `main` function prototype should never take arguments or return type. +The `main` function prototype should never take arguments. Example: ``` diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 22b07c8cc044f..a759ce59cb644 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -45,7 +45,7 @@ #![feature(box_syntax)] #![feature(conservative_impl_trait)] #![feature(const_fn)] -#![feature(copy_closures, clone_closures)] +#![cfg_attr(stage0, feature(copy_closures, clone_closures))] #![feature(core_intrinsics)] #![feature(drain_filter)] #![feature(dyn_trait)] diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index d24da1ff7c8e5..f41765b642d96 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1208,6 +1208,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "set the MIR optimization level (0-3, default: 1)"), mutable_noalias: bool = (false, parse_bool, [UNTRACKED], "emit noalias metadata for mutable references"), + arg_align_attributes: bool = (false, parse_bool, [UNTRACKED], + "emit align metadata for reference arguments"), dump_mir: Option = (None, parse_opt_string, [UNTRACKED], "dump MIR state at various points in translation"), dump_mir_dir: String = (String::from("mir_dump"), parse_string, [UNTRACKED], diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 79d5cf7935941..e640cc315c44d 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -595,20 +595,23 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { trait_ref.to_predicate(), post_message) })); + let explanation = + if obligation.cause.code == ObligationCauseCode::MainFunctionType { + "consider using `()`, or a `Result`".to_owned() + } else { + format!("{}the trait `{}` is not implemented for `{}`", + pre_message, + trait_ref, + trait_ref.self_ty()) + }; + if let Some(ref s) = label { // If it has a custom "#[rustc_on_unimplemented]" // error message, let's display it as the label! err.span_label(span, s.as_str()); - err.help(&format!("{}the trait `{}` is not implemented for `{}`", - pre_message, - trait_ref, - trait_ref.self_ty())); + err.help(&explanation); } else { - err.span_label(span, - &*format!("{}the trait `{}` is not implemented for `{}`", - pre_message, - trait_ref, - trait_ref.self_ty())); + err.span_label(span, explanation); } if let Some(ref s) = note { // If it has a custom "#[rustc_on_unimplemented]" note, let's display it diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 4db81cf1dec1d..11daa96134c59 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -2086,14 +2086,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ty::TyClosure(def_id, substs) => { let trait_id = obligation.predicate.def_id(); - let copy_closures = - Some(trait_id) == self.tcx().lang_items().copy_trait() && - self.tcx().has_copy_closures(def_id.krate); - let clone_closures = - Some(trait_id) == self.tcx().lang_items().clone_trait() && - self.tcx().has_clone_closures(def_id.krate); - - if copy_closures || clone_closures { + 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())) } else { Never diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 460593d9cb4fa..fdda2286da03b 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2562,14 +2562,6 @@ pub fn provide(providers: &mut ty::maps::Providers) { assert_eq!(cnum, LOCAL_CRATE); tcx.output_filenames.clone() }; - providers.has_copy_closures = |tcx, cnum| { - assert_eq!(cnum, LOCAL_CRATE); - tcx.features().copy_closures - }; - providers.has_clone_closures = |tcx, cnum| { - assert_eq!(cnum, LOCAL_CRATE); - tcx.features().clone_closures - }; providers.features_query = |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); Lrc::new(tcx.sess.features_untracked().clone()) diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs index 7565e90df986f..bb9467305e335 100644 --- a/src/librustc/ty/maps/config.rs +++ b/src/librustc/ty/maps/config.rs @@ -610,24 +610,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::output_filenames<'tcx> { } } -impl<'tcx> QueryDescription<'tcx> for queries::has_clone_closures<'tcx> { - fn describe(_tcx: TyCtxt, _: CrateNum) -> String { - format!("seeing if the crate has enabled `Clone` closures") - } -} - impl<'tcx> QueryDescription<'tcx> for queries::vtable_methods<'tcx> { fn describe(tcx: TyCtxt, key: ty::PolyTraitRef<'tcx> ) -> String { format!("finding all methods for trait {}", tcx.item_path_str(key.def_id())) } } -impl<'tcx> QueryDescription<'tcx> for queries::has_copy_closures<'tcx> { - fn describe(_tcx: TyCtxt, _: CrateNum) -> String { - format!("seeing if the crate has enabled `Copy` closures") - } -} - impl<'tcx> QueryDescription<'tcx> for queries::features_query<'tcx> { fn describe(_tcx: TyCtxt, _: CrateNum) -> String { format!("looking up enabled feature gates") diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index c16ad0d8ca140..2bfb687032923 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -387,9 +387,6 @@ define_maps! { <'tcx> [] fn output_filenames: output_filenames_node(CrateNum) -> Arc, - [] fn has_copy_closures: HasCopyClosures(CrateNum) -> bool, - [] fn has_clone_closures: HasCloneClosures(CrateNum) -> bool, - // Erases regions from `ty` to yield a new type. // Normally you would just use `tcx.erase_regions(&value)`, // however, which uses this query as a kind of cache. diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 46106d8ec0e91..50a19526ba8c4 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -920,8 +920,6 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, } DepKind::UsedCrateSource => { force!(used_crate_source, krate!()); } DepKind::PostorderCnums => { force!(postorder_cnums, LOCAL_CRATE); } - DepKind::HasCloneClosures => { force!(has_clone_closures, krate!()); } - DepKind::HasCopyClosures => { force!(has_copy_closures, krate!()); } DepKind::Freevars => { force!(freevars, def_id!()); } DepKind::MaybeUnusedTraitImport => { diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index f1f3a0519bbcb..b9bcbccb30ef3 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -63,6 +63,7 @@ use rustc_resolve as resolve; use rustc_save_analysis as save; use rustc_save_analysis::DumpHandler; use rustc_data_structures::sync::Lrc; +use rustc_data_structures::OnDrop; use rustc::session::{self, config, Session, build_session, CompileResult}; use rustc::session::CompileIncomplete; use rustc::session::config::{Input, PrintRequest, ErrorOutputType}; @@ -515,30 +516,35 @@ fn run_compiler_impl<'a>(args: &[String], target_features::add_configuration(&mut cfg, &sess, &*trans); sess.parse_sess.config = cfg; - let plugins = sess.opts.debugging_opts.extra_plugins.clone(); - - let cstore = CStore::new(trans.metadata_loader()); - - do_or_return!(callbacks.late_callback(&*trans, - &matches, - &sess, - &cstore, - &input, - &odir, - &ofile), Some(sess)); - - let control = callbacks.build_controller(&sess, &matches); - - (driver::compile_input(trans, - &sess, - &cstore, - &input_file_path, - &input, - &odir, - &ofile, - Some(plugins), - &control), - Some(sess)) + let result = { + let plugins = sess.opts.debugging_opts.extra_plugins.clone(); + + let cstore = CStore::new(trans.metadata_loader()); + + do_or_return!(callbacks.late_callback(&*trans, + &matches, + &sess, + &cstore, + &input, + &odir, + &ofile), Some(sess)); + + let _sess_abort_error = OnDrop(|| sess.diagnostic().print_error_count()); + + let control = callbacks.build_controller(&sess, &matches); + + driver::compile_input(trans, + &sess, + &cstore, + &input_file_path, + &input, + &odir, + &ofile, + Some(plugins), + &control) + }; + + (result, Some(sess)) } // Extract output directory and file from matches. diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index a25c3668bb13b..dcbea793ba6a3 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -558,21 +558,15 @@ impl Handler { pub fn has_errors(&self) -> bool { self.err_count() > 0 } - pub fn abort_if_errors(&self) { - let s; - match self.err_count() { - 0 => { - if let Some(bug) = self.delayed_span_bug.borrow_mut().take() { - DiagnosticBuilder::new_diagnostic(self, bug).emit(); - } - return; - } - 1 => s = "aborting due to previous error".to_string(), - _ => { - s = format!("aborting due to {} previous errors", self.err_count()); - } - } - let err = self.fatal(&s); + + pub fn print_error_count(&self) { + let s = match self.err_count() { + 0 => return, + 1 => "aborting due to previous error".to_string(), + _ => format!("aborting due to {} previous errors", self.err_count()) + }; + + let _ = self.fatal(&s); let can_show_explain = self.emitter.borrow().should_show_explain(); let are_there_diagnostics = !self.tracked_diagnostic_codes.borrow().is_empty(); @@ -603,8 +597,16 @@ impl Handler { } } } + } - err.raise(); + pub fn abort_if_errors(&self) { + if self.err_count() == 0 { + if let Some(bug) = self.delayed_span_bug.borrow_mut().take() { + DiagnosticBuilder::new_diagnostic(self, bug).emit(); + } + return; + } + FatalError.raise(); } pub fn emit(&self, msp: &MultiSpan, msg: &str, lvl: Level) { if lvl == Warning && !self.flags.can_emit_warnings { diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 53986f0741005..8765d9d8c2bed 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -226,16 +226,6 @@ impl CrateMetadata { attr::contains_name(&attrs, "no_builtins") } - pub fn has_copy_closures(&self, sess: &Session) -> bool { - let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess); - attr::contains_feature_attr(&attrs, "copy_closures") - } - - pub fn has_clone_closures(&self, sess: &Session) -> bool { - let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess); - attr::contains_feature_attr(&attrs, "clone_closures") - } - pub fn panic_strategy(&self) -> PanicStrategy { self.root.panic_strategy.clone() } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index e911a03bbe2b5..5fd8ebaa9b4a6 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -255,9 +255,6 @@ provide! { <'tcx> tcx, def_id, other, cdata, used_crate_source => { Lrc::new(cdata.source.clone()) } - has_copy_closures => { cdata.has_copy_closures(tcx.sess) } - has_clone_closures => { cdata.has_clone_closures(tcx.sess) } - exported_symbols => { let cnum = cdata.cnum; assert!(cnum != LOCAL_CRATE); diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index e72f9ddd82abe..e938d5c1a97fe 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -14,7 +14,8 @@ use cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary, ForeignModule}; use schema::*; use rustc_data_structures::sync::{Lrc, ReadGuard}; -use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash}; +use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash, + DisambiguatedDefPathData}; use rustc::hir; use rustc::middle::cstore::{LinkagePreference, ExternConstBody, ExternBodyNestedBodies}; @@ -1125,7 +1126,23 @@ impl<'a, 'tcx> CrateMetadata { #[inline] pub fn def_key(&self, index: DefIndex) -> DefKey { - self.def_path_table.def_key(index) + if !self.is_proc_macro(index) { + self.def_path_table.def_key(index) + } else { + // FIXME(#49271) - It would be better if the DefIds were consistent + // with the DefPathTable, but for proc-macro crates + // they aren't. + let name = self.proc_macros + .as_ref() + .unwrap()[index.to_proc_macro_index()].0; + DefKey { + parent: Some(CRATE_DEF_INDEX), + disambiguated_data: DisambiguatedDefPathData { + data: DefPathData::MacroDef(name.as_str()), + disambiguator: 0, + } + } + } } // Returns the path leading to the thing with this `id`. diff --git a/src/librustc_mir/diagnostics.rs b/src/librustc_mir/diagnostics.rs index 2000ebea25d7e..4f36c3888b961 100644 --- a/src/librustc_mir/diagnostics.rs +++ b/src/librustc_mir/diagnostics.rs @@ -2247,7 +2247,7 @@ let mut b = || { yield (); // ...is still in scope here, when the yield occurs. println!("{}", a); }; -b.resume(); +unsafe { b.resume() }; ``` At present, it is not permitted to have a yield that occurs while a @@ -2265,7 +2265,7 @@ let mut b = || { yield (); println!("{}", a); }; -b.resume(); +unsafe { b.resume() }; ``` This is a very simple case, of course. In more complex cases, we may @@ -2283,7 +2283,7 @@ let mut b = || { yield x; // ...when this yield occurs. } }; -b.resume(); +unsafe { b.resume() }; ``` Such cases can sometimes be resolved by iterating "by value" (or using @@ -2298,7 +2298,7 @@ let mut b = || { yield x; // <-- Now yield is OK. } }; -b.resume(); +unsafe { b.resume() }; ``` If taking ownership is not an option, using indices can work too: @@ -2314,7 +2314,7 @@ let mut b = || { yield x; // <-- Now yield is OK. } }; -b.resume(); +unsafe { b.resume() }; // (*) -- Unfortunately, these temporaries are currently required. // See . diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index c236ce2abc5f0..b8bfcd756cd23 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -1,7 +1,7 @@ -use std::collections::HashSet; use std::fmt::Write; use rustc::hir::def_id::DefId; +use rustc::hir::def::Def; use rustc::hir::map::definitions::DefPathData; use rustc::middle::const_val::{ConstVal, ErrKind}; use rustc::mir; @@ -9,7 +9,7 @@ use rustc::ty::layout::{self, Size, Align, HasDataLayout, LayoutOf, TyLayout}; use rustc::ty::subst::{Subst, Substs}; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::maps::TyCtxtAt; -use rustc_data_structures::indexed_vec::Idx; +use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use rustc::middle::const_val::FrameInfo; use syntax::codemap::{self, Span}; use syntax::ast::Mutability; @@ -17,6 +17,7 @@ use rustc::mir::interpret::{ GlobalId, Value, Pointer, PrimVal, PrimValKind, EvalError, EvalResult, EvalErrorKind, MemoryPointer, }; +use std::mem; use super::{Place, PlaceExtra, Memory, HasMemory, MemoryKind, @@ -71,12 +72,12 @@ pub struct Frame<'mir, 'tcx: 'mir> { pub return_place: Place, /// The list of locals for this stack frame, stored in order as - /// `[arguments..., variables..., temporaries...]`. The locals are stored as `Option`s. + /// `[return_ptr, arguments..., variables..., temporaries...]`. The locals are stored as `Option`s. /// `None` represents a local that is currently dead, while a live local /// can either directly contain `PrimVal` or refer to some part of an `Allocation`. /// /// Before being initialized, arguments are `Value::ByVal(PrimVal::Undef)` and other locals are `None`. - pub locals: Vec>, + pub locals: IndexVec>, //////////////////////////////////////////////////////////////////////////////// // Current position within the function @@ -383,39 +384,29 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M ) -> EvalResult<'tcx> { ::log_settings::settings().indentation += 1; - /// Return the set of locals that have a storage annotation anywhere - fn collect_storage_annotations<'mir, 'tcx>(mir: &'mir mir::Mir<'tcx>) -> HashSet { - use rustc::mir::StatementKind::*; - - let mut set = HashSet::new(); - for block in mir.basic_blocks() { - for stmt in block.statements.iter() { - match stmt.kind { - StorageLive(local) | - StorageDead(local) => { - set.insert(local); + let locals = if mir.local_decls.len() > 1 { + let mut locals = IndexVec::from_elem(Some(Value::ByVal(PrimVal::Undef)), &mir.local_decls); + match self.tcx.describe_def(instance.def_id()) { + // statics and constants don't have `Storage*` statements, no need to look for them + Some(Def::Static(..)) | Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) => {}, + _ => { + trace!("push_stack_frame: {:?}: num_bbs: {}", span, mir.basic_blocks().len()); + for block in mir.basic_blocks() { + for stmt in block.statements.iter() { + use rustc::mir::StatementKind::{StorageDead, StorageLive}; + match stmt.kind { + StorageLive(local) | + StorageDead(local) => locals[local] = None, + _ => {} + } } - _ => {} } - } - } - set - } - - // Subtract 1 because `local_decls` includes the ReturnMemoryPointer, but we don't store a local - // `Value` for that. - let num_locals = mir.local_decls.len() - 1; - - let locals = { - let annotated_locals = collect_storage_annotations(mir); - let mut locals = vec![None; num_locals]; - for i in 0..num_locals { - let local = mir::Local::new(i + 1); - if !annotated_locals.contains(&local) { - locals[i] = Some(Value::ByVal(PrimVal::Undef)); - } + }, } locals + } else { + // don't allocate at all for trivial constants + IndexVec::new() }; self.stack.push(Frame { @@ -973,8 +964,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M pub fn force_allocation(&mut self, place: Place) -> EvalResult<'tcx, Place> { let new_place = match place { Place::Local { frame, local } => { - // -1 since we don't store the return value - match self.stack[frame].locals[local.index() - 1] { + match self.stack[frame].locals[local] { None => return err!(DeadLocal), Some(Value::ByRef(ptr, align)) => { Place::Ptr { @@ -988,7 +978,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M let ty = self.monomorphize(ty, self.stack[frame].instance.substs); let layout = self.layout_of(ty)?; let ptr = self.alloc_ptr(ty)?; - self.stack[frame].locals[local.index() - 1] = + self.stack[frame].locals[local] = Some(Value::ByRef(ptr.into(), layout.align)); // it stays live let place = Place::from_ptr(ptr, layout.align); self.write_value(ValTy { value: val, ty }, place)?; @@ -1702,13 +1692,11 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M impl<'mir, 'tcx> Frame<'mir, 'tcx> { pub fn get_local(&self, local: mir::Local) -> EvalResult<'tcx, Value> { - // Subtract 1 because we don't store a value for the ReturnPointer, the local with index 0. - self.locals[local.index() - 1].ok_or(EvalErrorKind::DeadLocal.into()) + self.locals[local].ok_or(EvalErrorKind::DeadLocal.into()) } fn set_local(&mut self, local: mir::Local, value: Value) -> EvalResult<'tcx> { - // Subtract 1 because we don't store a value for the ReturnPointer, the local with index 0. - match self.locals[local.index() - 1] { + match self.locals[local] { None => err!(DeadLocal), Some(ref mut local) => { *local = value; @@ -1717,20 +1705,17 @@ impl<'mir, 'tcx> Frame<'mir, 'tcx> { } } - pub fn storage_live(&mut self, local: mir::Local) -> EvalResult<'tcx, Option> { + pub fn storage_live(&mut self, local: mir::Local) -> Option { trace!("{:?} is now live", local); - let old = self.locals[local.index() - 1]; - self.locals[local.index() - 1] = Some(Value::ByVal(PrimVal::Undef)); // StorageLive *always* kills the value that's currently stored - return Ok(old); + // StorageLive *always* kills the value that's currently stored + mem::replace(&mut self.locals[local], Some(Value::ByVal(PrimVal::Undef))) } /// Returns the old value of the local - pub fn storage_dead(&mut self, local: mir::Local) -> EvalResult<'tcx, Option> { + pub fn storage_dead(&mut self, local: mir::Local) -> Option { trace!("{:?} is now dead", local); - let old = self.locals[local.index() - 1]; - self.locals[local.index() - 1] = None; - return Ok(old); + self.locals[local].take() } } diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index b369f80e849b0..4026f52e9620d 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -1,5 +1,5 @@ use byteorder::{ReadBytesExt, WriteBytesExt, LittleEndian, BigEndian}; -use std::collections::{btree_map, BTreeMap, HashMap, HashSet, VecDeque}; +use std::collections::{btree_map, BTreeMap, VecDeque}; use std::{ptr, io}; use rustc::ty::Instance; @@ -7,6 +7,7 @@ use rustc::ty::maps::TyCtxtAt; use rustc::ty::layout::{self, Align, TargetDataLayout}; use syntax::ast::Mutability; +use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use rustc::mir::interpret::{MemoryPointer, AllocId, Allocation, AccessKind, UndefMask, Value, Pointer, EvalResult, PrimVal, EvalErrorKind}; @@ -33,15 +34,15 @@ pub struct Memory<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> { pub data: M::MemoryData, /// Helps guarantee that stack allocations aren't deallocated via `rust_deallocate` - alloc_kind: HashMap>, + alloc_kind: FxHashMap>, /// Actual memory allocations (arbitrary bytes, may contain pointers into other allocations). - alloc_map: HashMap, + alloc_map: FxHashMap, /// Actual memory allocations (arbitrary bytes, may contain pointers into other allocations). /// /// Stores statics while they are being processed, before they are interned and thus frozen - uninitialized_statics: HashMap, + uninitialized_statics: FxHashMap, /// The current stack frame. Used to check accesses against locks. pub cur_frame: usize, @@ -53,9 +54,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn new(tcx: TyCtxtAt<'a, 'tcx, 'tcx>, data: M::MemoryData) -> Self { Memory { data, - alloc_kind: HashMap::new(), - alloc_map: HashMap::new(), - uninitialized_statics: HashMap::new(), + alloc_kind: FxHashMap::default(), + alloc_map: FxHashMap::default(), + uninitialized_statics: FxHashMap::default(), tcx, cur_frame: usize::max_value(), } @@ -338,7 +339,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { allocs.sort(); allocs.dedup(); let mut allocs_to_print = VecDeque::from(allocs); - let mut allocs_seen = HashSet::new(); + let mut allocs_seen = FxHashSet::default(); while let Some(id) = allocs_to_print.pop_front() { let mut msg = format!("Alloc {:<5} ", format!("{}:", id)); diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index f1d58ff5e884e..a22572ec687c3 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -69,13 +69,13 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { // Mark locals as alive StorageLive(local) => { - let old_val = self.frame_mut().storage_live(local)?; + let old_val = self.frame_mut().storage_live(local); self.deallocate_local(old_val)?; } // Mark locals as dead StorageDead(local) => { - let old_val = self.frame_mut().storage_dead(local)?; + let old_val = self.frame_mut().storage_dead(local); self.deallocate_local(old_val)?; } diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 02c703996643a..31af7c2185794 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -126,21 +126,13 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { &AggregateKind::Array(..) | &AggregateKind::Tuple | &AggregateKind::Adt(..) => {} - &AggregateKind::Closure(def_id, _) => { + &AggregateKind::Closure(def_id, _) | + &AggregateKind::Generator(def_id, _, _) => { let UnsafetyCheckResult { violations, unsafe_blocks } = self.tcx.unsafety_check_result(def_id); self.register_violations(&violations, &unsafe_blocks); } - &AggregateKind::Generator(def_id, _, interior) => { - let UnsafetyCheckResult { - violations, unsafe_blocks - } = self.tcx.unsafety_check_result(def_id); - self.register_violations(&violations, &unsafe_blocks); - if !interior.movable { - self.require_unsafe("construction of immovable generator") - } - } } } self.super_rvalue(rvalue, location); diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs index 44c18c371a40f..203e273c98eaa 100644 --- a/src/librustc_trans/abi.rs +++ b/src/librustc_trans/abi.rs @@ -779,7 +779,7 @@ impl<'a, 'tcx> FnType<'tcx> { // HACK(eddyb) LLVM inserts `llvm.assume` calls when inlining functions // with align attributes, and those calls later block optimizations. - if !is_return { + if !is_return && !cx.tcx.sess.opts.debugging_opts.arg_align_attributes { attrs.pointee_align = None; } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 385154152b373..0e93277983f8d 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -27,6 +27,7 @@ use std::slice; use require_c_abi_if_variadic; use util::common::ErrorReported; use util::nodemap::FxHashSet; +use errors::FatalError; use std::iter; use syntax::{abi, ast}; @@ -337,7 +338,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { Def::Trait(trait_def_id) => trait_def_id, Def::TraitAlias(alias_def_id) => alias_def_id, Def::Err => { - self.tcx().sess.fatal("cannot continue compilation due to previous error"); + FatalError.raise(); } _ => unreachable!(), } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 9afa2d42fa44d..f820b0ba16b30 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1130,25 +1130,23 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, } fcx.demand_suptype(span, ret_ty, actual_return_ty); - if fcx.tcx.features().termination_trait { - // If the termination trait language item is activated, check that the main return type - // implements the termination trait. - if let Some(term_id) = fcx.tcx.lang_items().termination() { - if let Some((id, _)) = *fcx.tcx.sess.entry_fn.borrow() { - if id == fn_id { - match fcx.sess().entry_type.get() { - Some(config::EntryMain) => { - let substs = fcx.tcx.mk_substs(iter::once(Kind::from(ret_ty))); - let trait_ref = ty::TraitRef::new(term_id, substs); - let cause = traits::ObligationCause::new( - span, fn_id, ObligationCauseCode::MainFunctionType); - - inherited.register_predicate( - traits::Obligation::new( - cause, param_env, trait_ref.to_predicate())); - }, - _ => {}, - } + // Check that the main return type implements the termination trait. + if let Some(term_id) = fcx.tcx.lang_items().termination() { + if let Some((id, _)) = *fcx.tcx.sess.entry_fn.borrow() { + if id == fn_id { + match fcx.sess().entry_type.get() { + Some(config::EntryMain) => { + let substs = fcx.tcx.mk_substs(iter::once(Kind::from(ret_ty))); + let trait_ref = ty::TraitRef::new(term_id, substs); + let return_ty_span = decl.output.span(); + let cause = traits::ObligationCause::new( + return_ty_span, fn_id, ObligationCauseCode::MainFunctionType); + + inherited.register_predicate( + traits::Obligation::new( + cause, param_env, trait_ref.to_predicate())); + }, + _ => {}, } } } diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 9f98932f24b52..5a7de6b56b500 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -76,7 +76,7 @@ This API is completely unstable and subject to change. #![feature(box_patterns)] #![feature(box_syntax)] #![feature(conservative_impl_trait)] -#![feature(copy_closures, clone_closures)] +#![cfg_attr(stage0, feature(copy_closures, clone_closures))] #![feature(crate_visibility_modifier)] #![feature(from_ref)] #![feature(match_default_bindings)] @@ -208,8 +208,7 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } let actual = tcx.fn_sig(main_def_id); - let expected_return_type = if tcx.lang_items().termination().is_some() - && tcx.features().termination_trait { + let expected_return_type = if tcx.lang_items().termination().is_some() { // we take the return type of the given main function, the real check is done // in `check_fn` actual.output().skip_binder() diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 21c1d9d670d65..6c6c067f95189 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -49,6 +49,13 @@ var themesWidth = null; + if (!String.prototype.startsWith) { + String.prototype.startsWith = function(searchString, position) { + position = position || 0; + return this.indexOf(searchString, position) === position; + }; + } + function hasClass(elem, className) { if (elem && className && elem.className) { var elemClass = elem.className; diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index a760922115aef..ceb019bc95b4c 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -780,7 +780,7 @@ impl f32 { unsafe { cmath::atanf(self) } } - /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`). + /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians. /// /// * `x = 0`, `y = 0`: `0` /// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]` @@ -791,12 +791,13 @@ impl f32 { /// use std::f32; /// /// let pi = f32::consts::PI; - /// // All angles from horizontal right (+x) - /// // 45 deg counter-clockwise + /// // Positive angles measured counter-clockwise + /// // from positive x axis + /// // -pi/4 radians (45 deg clockwise) /// let x1 = 3.0f32; /// let y1 = -3.0f32; /// - /// // 135 deg clockwise + /// // 3pi/4 radians (135 deg counter-clockwise) /// let x2 = -3.0f32; /// let y2 = 3.0f32; /// diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index 6f34f176a9711..97adf108b73b0 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -716,7 +716,7 @@ impl f64 { unsafe { cmath::atan(self) } } - /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`). + /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians. /// /// * `x = 0`, `y = 0`: `0` /// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]` @@ -727,12 +727,13 @@ impl f64 { /// use std::f64; /// /// let pi = f64::consts::PI; - /// // All angles from horizontal right (+x) - /// // 45 deg counter-clockwise + /// // Positive angles measured counter-clockwise + /// // from positive x axis + /// // -pi/4 radians (45 deg clockwise) /// let x1 = 3.0_f64; /// let y1 = -3.0_f64; /// - /// // 135 deg clockwise + /// // 3pi/4 radians (135 deg counter-clockwise) /// let x2 = -3.0_f64; /// let y2 = 3.0_f64; /// diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index db52ed67d3a85..5caa703ee97e3 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -906,7 +906,13 @@ impl Metadata { FileType(self.0.file_type()) } - /// Returns whether this metadata is for a directory. + /// Returns whether this metadata is for a directory. The + /// result is mutually exclusive to the result of + /// [`is_file`], and will be false for symlink metadata + /// obtained from [`symlink_metadata`]. + /// + /// [`is_file`]: struct.Metadata.html#method.is_file + /// [`symlink_metadata`]: fn.symlink_metadata.html /// /// # Examples /// @@ -923,7 +929,13 @@ impl Metadata { #[stable(feature = "rust1", since = "1.0.0")] pub fn is_dir(&self) -> bool { self.file_type().is_dir() } - /// Returns whether this metadata is for a regular file. + /// Returns whether this metadata is for a regular file. The + /// result is mutually exclusive to the result of + /// [`is_dir`], and will be false for symlink metadata + /// obtained from [`symlink_metadata`]. + /// + /// [`is_dir`]: struct.Metadata.html#method.is_dir + /// [`symlink_metadata`]: fn.symlink_metadata.html /// /// # Examples /// @@ -1148,7 +1160,13 @@ impl Permissions { } impl FileType { - /// Test whether this file type represents a directory. + /// Test whether this file type represents a directory. The + /// result is mutually exclusive to the results of + /// [`is_file`] and [`is_symlink`]; only zero or one of these + /// tests may pass. + /// + /// [`is_file`]: struct.FileType.html#method.is_file + /// [`is_symlink`]: struct.FileType.html#method.is_symlink /// /// # Examples /// @@ -1167,6 +1185,12 @@ impl FileType { pub fn is_dir(&self) -> bool { self.0.is_dir() } /// Test whether this file type represents a regular file. + /// The result is mutually exclusive to the results of + /// [`is_dir`] and [`is_symlink`]; only zero or one of these + /// tests may pass. + /// + /// [`is_dir`]: struct.FileType.html#method.is_dir + /// [`is_symlink`]: struct.FileType.html#method.is_symlink /// /// # Examples /// @@ -1185,6 +1209,9 @@ impl FileType { pub fn is_file(&self) -> bool { self.0.is_file() } /// Test whether this file type represents a symbolic link. + /// The result is mutually exclusive to the results of + /// [`is_dir`] and [`is_file`]; only zero or one of these + /// tests may pass. /// /// The underlying [`Metadata`] struct needs to be retrieved /// with the [`fs::symlink_metadata`] function and not the @@ -1195,6 +1222,8 @@ impl FileType { /// [`Metadata`]: struct.Metadata.html /// [`fs::metadata`]: fn.metadata.html /// [`fs::symlink_metadata`]: fn.symlink_metadata.html + /// [`is_dir`]: struct.FileType.html#method.is_dir + /// [`is_file`]: struct.FileType.html#method.is_file /// [`is_symlink`]: struct.FileType.html#method.is_symlink /// /// # Examples diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 36eb729182210..0b06c5d4d656e 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -308,7 +308,6 @@ #![feature(str_char)] #![feature(str_internals)] #![feature(str_utf16)] -#![feature(termination_trait)] #![feature(test, rustc_private)] #![feature(thread_local)] #![feature(toowned_clone_into)] @@ -325,6 +324,7 @@ #![cfg_attr(test, feature(update_panic_count))] #![cfg_attr(windows, feature(used))] #![cfg_attr(stage0, feature(never_type))] +#![cfg_attr(stage0, feature(termination_trait))] #![default_lib_allocator] diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 000f971361530..47609f17221ef 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -335,6 +335,18 @@ pub mod builtin { /// proxied through this one. `format_args!`, unlike its derived macros, avoids /// heap allocations. /// + /// You can use the [`fmt::Arguments`] value that `format_args!` returns + /// in `Debug` and `Display` contexts as seen below. The example also shows + /// that `Debug` and `Display` format to the same thing: the interpolated + /// format string in `format_args!`. + /// + /// ```rust + /// let display = format!("{:?}", format_args!("{} foo {:?}", 1, 2)); + /// let debug = format!("{}", format_args!("{} foo {:?}", 1, 2)); + /// assert_eq!("1 foo 2", display); + /// assert_eq!(display, debug); + /// ``` + /// /// For more information, see the documentation in [`std::fmt`]. /// /// [`Display`]: ../std/fmt/trait.Display.html diff --git a/src/libstd/process.rs b/src/libstd/process.rs index d5ac2d19e831f..c877bf6aa35cd 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -1442,8 +1442,9 @@ pub fn id() -> u32 { /// a successful execution. In case of a failure, `libc::EXIT_FAILURE` is returned. #[cfg_attr(not(test), lang = "termination")] #[unstable(feature = "termination_trait_lib", issue = "43301")] -#[rustc_on_unimplemented = - "`main` can only return types that implement {Termination}, not `{Self}`"] +#[rustc_on_unimplemented( + message="`main` has invalid return type `{Self}`", + label="`main` can only return types that implement {Termination}")] pub trait Termination { /// Is called to get the representation of the value as status code. /// This status code is returned to the operating system. diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 69612054ae3da..e69dace0c7051 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -391,10 +391,6 @@ declare_features! ( // Future-proofing enums/structs with #[non_exhaustive] attribute (RFC 2008) (active, non_exhaustive, "1.22.0", Some(44109), None), - // Copy/Clone closures (RFC 2132) - (active, clone_closures, "1.22.0", Some(44490), None), - (active, copy_closures, "1.22.0", Some(44490), None), - // allow `'_` placeholder lifetimes (active, underscore_lifetimes, "1.22.0", Some(44524), None), @@ -428,8 +424,8 @@ declare_features! ( // `foo.rs` as an alternative to `foo/mod.rs` (active, non_modrs_mods, "1.24.0", Some(44660), None), - // Termination trait in main (RFC 1937) - (active, termination_trait, "1.24.0", Some(43301), None), + // Termination trait in tests (RFC 1937) + (active, termination_trait_test, "1.24.0", Some(48854), None), // Allows use of the :lifetime macro fragment specifier (active, macro_lifetime_matcher, "1.24.0", Some(46895), None), @@ -565,6 +561,11 @@ declare_features! ( (accepted, inclusive_range_syntax, "1.26.0", Some(28237), None), // allow `..=` in patterns (RFC 1192) (accepted, dotdoteq_in_patterns, "1.26.0", Some(28237), None), + // Termination trait in main (RFC 1937) + (accepted, termination_trait, "1.26.0", Some(43301), None), + // Copy/Clone closures (RFC 2132) + (accepted, clone_closures, "1.26.0", Some(44490), None), + (accepted, copy_closures, "1.26.0", Some(44490), None), ); // If you change this, please modify src/doc/unstable-book as well. You must @@ -1885,8 +1886,6 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], struct FeatureChecker { proc_macro: Option, custom_attribute: Option, - copy_closures: Option, - clone_closures: Option, } impl FeatureChecker { @@ -1902,14 +1901,6 @@ impl FeatureChecker { if features.custom_attribute { self.custom_attribute = self.custom_attribute.or(Some(span)); } - - if features.copy_closures { - self.copy_closures = self.copy_closures.or(Some(span)); - } - - if features.clone_closures { - self.clone_closures = self.clone_closures.or(Some(span)); - } } fn check(self, handler: &Handler) { @@ -1921,15 +1912,6 @@ impl FeatureChecker { FatalError.raise(); } - - if let (Some(span), None) = (self.copy_closures, self.clone_closures) { - handler.struct_span_err(span, "`#![feature(copy_closures)]` can only be used with \ - `#![feature(clone_closures)]`") - .span_note(span, "`#![feature(copy_closures)]` declared here") - .emit(); - - FatalError.raise(); - } } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a07279acae2d3..98e2528d30f24 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -3675,7 +3675,13 @@ impl<'a> Parser<'a> { if self.token != token::CloseDelim(token::Brace) { let token_str = self.this_token_to_string(); let mut err = self.fatal(&format!("expected `{}`, found `{}`", "}", token_str)); - err.span_label(self.span, "expected `}`"); + if self.token == token::Comma { // Issue #49257 + err.span_label(self.span, + "`..` must be in the last position, \ + and cannot have a trailing comma"); + } else { + err.span_label(self.span, "expected `}`"); + } return Err(err); } etc = true; diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 5264b627e9613..6c01171d1003e 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -332,7 +332,7 @@ fn is_test_fn(cx: &TestCtxt, i: &ast::Item) -> bool { 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 { + let output_matches = if cx.features.termination_trait_test { true } else { let no_output = match decl.output { @@ -359,7 +359,7 @@ fn is_test_fn(cx: &TestCtxt, i: &ast::Item) -> bool { match has_test_signature(cx, i) { Yes => true, No => { - if cx.features.termination_trait { + 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() -> ()"); @@ -388,7 +388,7 @@ fn is_bench_fn(cx: &TestCtxt, i: &ast::Item) -> bool { // 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 { + let output_matches = if cx.features.termination_trait_test { true } else { let no_output = match decl.output { @@ -416,7 +416,7 @@ fn is_bench_fn(cx: &TestCtxt, i: &ast::Item) -> bool { if has_bench_attr && !has_bench_signature { let diag = cx.span_diagnostic; - if cx.features.termination_trait { + if cx.features.termination_trait_test { diag.span_err(i.span, "functions used as benches must have signature \ `fn(&mut Bencher) -> impl Termination`"); } else { diff --git a/src/libtest/formatters/json.rs b/src/libtest/formatters/json.rs index d323d50f702ba..89235d897bde6 100644 --- a/src/libtest/formatters/json.rs +++ b/src/libtest/formatters/json.rs @@ -36,17 +36,12 @@ impl JsonFormatter { if let Some(extras) = extra { self.write_message(&*format!( r#"{{ "type": "{}", "name": "{}", "event": "{}", {} }}"#, - ty, - name, - evt, - extras + ty, name, evt, extras )) } else { self.write_message(&*format!( r#"{{ "type": "{}", "name": "{}", "event": "{}" }}"#, - ty, - name, - evt + ty, name, evt )) } } @@ -89,14 +84,12 @@ impl OutputFormatter for JsonFormatter { self.write_event("test", desc.name.as_slice(), "failed", extra_data) } - TrFailedMsg(ref m) => { - self.write_event( - "test", - desc.name.as_slice(), - "failed", - Some(format!(r#""message": "{}""#, EscapedString(m))), - ) - } + TrFailedMsg(ref m) => self.write_event( + "test", + desc.name.as_slice(), + "failed", + Some(format!(r#""message": "{}""#, EscapedString(m))), + ), TrIgnored => self.write_event("test", desc.name.as_slice(), "ignored", None), @@ -116,13 +109,10 @@ impl OutputFormatter for JsonFormatter { let line = format!( "{{ \"type\": \"bench\", \ - \"name\": \"{}\", \ - \"median\": {}, \ - \"deviation\": {}{} }}", - desc.name, - median, - deviation, - mbps + \"name\": \"{}\", \ + \"median\": {}, \ + \"deviation\": {}{} }}", + desc.name, median, deviation, mbps ); self.write_message(&*line) @@ -138,16 +128,15 @@ impl OutputFormatter for JsonFormatter { } fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result { - self.write_message(&*format!( "{{ \"type\": \"suite\", \ - \"event\": \"{}\", \ - \"passed\": {}, \ - \"failed\": {}, \ - \"allowed_fail\": {}, \ - \"ignored\": {}, \ - \"measured\": {}, \ - \"filtered_out\": \"{}\" }}", + \"event\": \"{}\", \ + \"passed\": {}, \ + \"failed\": {}, \ + \"allowed_fail\": {}, \ + \"ignored\": {}, \ + \"measured\": {}, \ + \"filtered_out\": \"{}\" }}", if state.failed == 0 { "ok" } else { "failed" }, state.passed, state.failed + state.allowed_fail, diff --git a/src/libtest/formatters/pretty.rs b/src/libtest/formatters/pretty.rs index f2064deefce62..8e5fa00b5f27d 100644 --- a/src/libtest/formatters/pretty.rs +++ b/src/libtest/formatters/pretty.rs @@ -196,8 +196,7 @@ impl OutputFormatter for PrettyFormatter { self.write_plain(&format!( "test {} has been running for over {} seconds\n", - desc.name, - TEST_WARN_TIMEOUT_S + desc.name, TEST_WARN_TIMEOUT_S )) } @@ -232,11 +231,7 @@ impl OutputFormatter for PrettyFormatter { } else { format!( ". {} passed; {} failed; {} ignored; {} measured; {} filtered out\n\n", - state.passed, - state.failed, - state.ignored, - state.measured, - state.filtered_out + state.passed, state.failed, state.ignored, state.measured, state.filtered_out ) }; diff --git a/src/libtest/formatters/terse.rs b/src/libtest/formatters/terse.rs index 88689485144c0..85286027d6921 100644 --- a/src/libtest/formatters/terse.rs +++ b/src/libtest/formatters/terse.rs @@ -195,8 +195,7 @@ impl OutputFormatter for TerseFormatter { fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()> { self.write_plain(&format!( "test {} has been running for over {} seconds\n", - desc.name, - TEST_WARN_TIMEOUT_S + desc.name, TEST_WARN_TIMEOUT_S )) } @@ -231,11 +230,7 @@ impl OutputFormatter for TerseFormatter { } else { format!( ". {} passed; {} failed; {} ignored; {} measured; {} filtered out\n\n", - state.passed, - state.failed, - state.ignored, - state.measured, - state.filtered_out + state.passed, state.failed, state.ignored, state.measured, state.filtered_out ) }; diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 59d701dd0fbc8..b8be1aeff1742 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -30,10 +30,8 @@ #![unstable(feature = "test", issue = "27812")] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", - html_root_url = "https://doc.rust-lang.org/nightly/", - test(attr(deny(warnings))))] + html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))] #![deny(warnings)] - #![feature(asm)] #![feature(fnbox)] #![cfg_attr(any(unix, target_os = "cloudabi"), feature(libc))] @@ -43,10 +41,10 @@ #![feature(termination_trait_lib)] extern crate getopts; -extern crate term; #[cfg(any(unix, target_os = "cloudabi"))] extern crate libc; extern crate panic_unwind; +extern crate term; pub use self::TestFn::*; pub use self::ColorConfig::*; @@ -72,7 +70,7 @@ use std::process::Termination; use std::sync::mpsc::{channel, Sender}; use std::sync::{Arc, Mutex}; use std::thread; -use std::time::{Instant, Duration}; +use std::time::{Duration, Instant}; use std::borrow::Cow; use std::process; @@ -81,16 +79,16 @@ const QUIET_MODE_MAX_COLUMN: usize = 100; // insert a '\n' after 100 tests in qu // to be used by rustc to compile tests in libtest pub mod test { - pub use {Bencher, TestName, TestResult, TestDesc, TestDescAndFn, TestOpts, TrFailed, - TrFailedMsg, TrIgnored, TrOk, Metric, MetricMap, StaticTestFn, StaticTestName, - DynTestName, DynTestFn, assert_test_result, run_test, test_main, test_main_static, - filter_tests, parse_opts, StaticBenchFn, ShouldPanic, Options}; + pub use {assert_test_result, filter_tests, parse_opts, run_test, test_main, test_main_static, + Bencher, DynTestFn, DynTestName, Metric, MetricMap, Options, ShouldPanic, + StaticBenchFn, StaticTestFn, StaticTestName, TestDesc, TestDescAndFn, TestName, + TestOpts, TestResult, TrFailed, TrFailedMsg, TrIgnored, TrOk}; } pub mod stats; mod formatters; -use formatters::{OutputFormatter, PrettyFormatter, TerseFormatter, JsonFormatter}; +use formatters::{JsonFormatter, OutputFormatter, PrettyFormatter, TerseFormatter}; // The name of a test. By convention this follows the rules for rust // paths; i.e. it should be a series of identifiers separated by double @@ -255,7 +253,9 @@ pub struct Options { impl Options { pub fn new() -> Options { - Options { display_output: false } + Options { + display_output: false, + } } pub fn display_output(mut self, display_output: bool) -> Options { @@ -272,7 +272,7 @@ pub fn test_main(args: &[String], tests: Vec, options: Options) { Some(Err(msg)) => { eprintln!("error: {}", msg); process::exit(101); - }, + } None => return, }; @@ -289,7 +289,7 @@ pub fn test_main(args: &[String], tests: Vec, options: Options) { Err(e) => { eprintln!("error: io error when listing tests: {:?}", e); process::exit(101); - }, + } } } } @@ -306,18 +306,14 @@ pub fn test_main_static(tests: &[TestDescAndFn]) { let owned_tests = tests .iter() .map(|t| match t.testfn { - StaticTestFn(f) => { - TestDescAndFn { - testfn: StaticTestFn(f), - desc: t.desc.clone(), - } - } - StaticBenchFn(f) => { - TestDescAndFn { - testfn: StaticBenchFn(f), - desc: t.desc.clone(), - } - } + StaticTestFn(f) => TestDescAndFn { + testfn: StaticTestFn(f), + desc: t.desc.clone(), + }, + StaticBenchFn(f) => TestDescAndFn { + testfn: StaticBenchFn(f), + desc: t.desc.clone(), + }, _ => panic!("non-static tests passed to test::test_main_static"), }) .collect(); @@ -397,34 +393,34 @@ fn optgroups() -> getopts::Options { "", "logfile", "Write logs to the specified file instead \ - of stdout", + of stdout", "PATH", ) .optflag( "", "nocapture", "don't capture stdout/stderr of each \ - task, allow printing directly", + task, allow printing directly", ) .optopt( "", "test-threads", "Number of threads used for running tests \ - in parallel", + in parallel", "n_threads", ) .optmulti( "", "skip", "Skip tests whose names contain FILTER (this flag can \ - be used multiple times)", + be used multiple times)", "FILTER", ) .optflag( "q", "quiet", "Display one character per test instead of one line. \ - Alias to --format=terse", + Alias to --format=terse", ) .optflag( "", @@ -516,8 +512,7 @@ pub fn parse_opts(args: &[String]) -> Option { if let Some(opt) = matches.opt_str("Z") { if !is_nightly() { return Some(Err( - "the option `Z` is only accepted on the nightly compiler" - .into(), + "the option `Z` is only accepted on the nightly compiler".into(), )); } @@ -562,19 +557,17 @@ pub fn parse_opts(args: &[String]) -> Option { } let test_threads = match matches.opt_str("test-threads") { - Some(n_str) => { - match n_str.parse::() { - Ok(0) => return Some(Err(format!("argument for --test-threads must not be 0"))), - Ok(n) => Some(n), - Err(e) => { - return Some(Err(format!( - "argument for --test-threads must be a number > 0 \ - (error: {})", - e - ))) - } + Some(n_str) => match n_str.parse::() { + Ok(0) => return Some(Err(format!("argument for --test-threads must not be 0"))), + Ok(n) => Some(n), + Err(e) => { + return Some(Err(format!( + "argument for --test-threads must be a number > 0 \ + (error: {})", + e + ))) } - } + }, None => None, }; @@ -586,7 +579,7 @@ pub fn parse_opts(args: &[String]) -> Option { Some(v) => { return Some(Err(format!( "argument for --color must be auto, always, or never (was \ - {})", + {})", v ))) } @@ -599,8 +592,7 @@ pub fn parse_opts(args: &[String]) -> Option { Some("json") => { if !allow_unstable { return Some(Err( - "The \"json\" format is only accepted on the nightly compiler" - .into(), + "The \"json\" format is only accepted on the nightly compiler".into(), )); } OutputFormat::Json @@ -609,7 +601,7 @@ pub fn parse_opts(args: &[String]) -> Option { Some(v) => { return Some(Err(format!( "argument for --format must be pretty, terse, or json (was \ - {})", + {})", v ))) } @@ -811,8 +803,7 @@ pub fn list_tests_console(opts: &TestOpts, tests: Vec) -> io::Res ntest += 1; "test" } - StaticBenchFn(..) | - DynBenchFn(..) => { + StaticBenchFn(..) | DynBenchFn(..) => { nbench += 1; "benchmark" } @@ -834,7 +825,8 @@ pub fn list_tests_console(opts: &TestOpts, tests: Vec) -> io::Res writeln!(output, "")?; } - writeln!(output, + writeln!( + output, "{}, {}", plural(ntest, "test"), plural(nbench, "benchmark") @@ -851,7 +843,6 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec) -> io::Resu st: &mut ConsoleTestState, out: &mut OutputFormatter, ) -> io::Result<()> { - match (*event).clone() { TeFiltered(ref filtered_tests) => { st.total = filtered_tests.len(); @@ -989,8 +980,7 @@ fn use_color(opts: &TestOpts) -> bool { } } -#[cfg(any(target_os = "cloudabi", - target_os = "redox", +#[cfg(any(target_os = "cloudabi", target_os = "redox", all(target_arch = "wasm32", not(target_os = "emscripten"))))] fn stdout_isatty() -> bool { // FIXME: Implement isatty on Redox @@ -1089,10 +1079,12 @@ where let now = Instant::now(); let timed_out = running_tests .iter() - .filter_map(|(desc, timeout)| if &now >= timeout { - Some(desc.clone()) - } else { - None + .filter_map(|(desc, timeout)| { + if &now >= timeout { + Some(desc.clone()) + } else { + None + } }) .collect(); for test in &timed_out { @@ -1174,12 +1166,10 @@ fn get_concurrency() -> usize { let opt_n: Option = s.parse().ok(); match opt_n { Some(n) if n > 0 => n, - _ => { - panic!( - "RUST_TEST_THREADS is `{}`, should be a positive integer.", - s - ) - } + _ => panic!( + "RUST_TEST_THREADS is `{}`, should be a positive integer.", + s + ), } } Err(..) => num_cpus(), @@ -1223,20 +1213,15 @@ fn get_concurrency() -> usize { 1 } - #[cfg(any(target_os = "android", - target_os = "cloudabi", - target_os = "emscripten", - target_os = "fuchsia", - target_os = "ios", - target_os = "linux", - target_os = "macos", - target_os = "solaris"))] + #[cfg(any(target_os = "android", target_os = "cloudabi", target_os = "emscripten", + target_os = "fuchsia", target_os = "ios", target_os = "linux", + target_os = "macos", target_os = "solaris"))] fn num_cpus() -> usize { unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as usize } } #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "bitrig", - target_os = "netbsd"))] + target_os = "netbsd"))] fn num_cpus() -> usize { use std::ptr; @@ -1308,26 +1293,28 @@ pub fn filter_tests(opts: &TestOpts, tests: Vec) -> Vec filtered, - Some(ref filter) => { - filtered - .into_iter() - .filter(|test| if opts.filter_exact { + Some(ref filter) => filtered + .into_iter() + .filter(|test| { + if opts.filter_exact { test.desc.name.as_slice() == &filter[..] } else { test.desc.name.as_slice().contains(&filter[..]) - }) - .collect() - } + } + }) + .collect(), }; // Skip tests that match any of the skip filters filtered = filtered .into_iter() .filter(|t| { - !opts.skip.iter().any(|sf| if opts.filter_exact { - t.desc.name.as_slice() == &sf[..] - } else { - t.desc.name.as_slice().contains(&sf[..]) + !opts.skip.iter().any(|sf| { + if opts.filter_exact { + t.desc.name.as_slice() == &sf[..] + } else { + t.desc.name.as_slice().contains(&sf[..]) + } }) }) .collect(); @@ -1354,31 +1341,23 @@ pub fn filter_tests(opts: &TestOpts, tests: Vec) -> Vec) -> Vec { // convert benchmarks to tests, if we're not benchmarking them - tests.into_iter().map(|x| { - let testfn = match x.testfn { - DynBenchFn(bench) => { - DynTestFn(Box::new(move || { - bench::run_once(|b| { - __rust_begin_short_backtrace(|| bench.run(b)) - }) - })) - } - StaticBenchFn(benchfn) => { - DynTestFn(Box::new(move || { - bench::run_once(|b| { - __rust_begin_short_backtrace(|| benchfn(b)) - }) - })) - } + tests + .into_iter() + .map(|x| { + let testfn = match x.testfn { + DynBenchFn(bench) => DynTestFn(Box::new(move || { + bench::run_once(|b| __rust_begin_short_backtrace(|| bench.run(b))) + })), + StaticBenchFn(benchfn) => DynTestFn(Box::new(move || { + bench::run_once(|b| __rust_begin_short_backtrace(|| benchfn(b))) + })), f => f, }; TestDescAndFn { @@ -1395,22 +1374,22 @@ pub fn run_test( test: TestDescAndFn, monitor_ch: Sender, ) { - let TestDescAndFn { desc, testfn } = test; - let ignore_because_panic_abort = cfg!(target_arch = "wasm32") && - !cfg!(target_os = "emscripten") && - desc.should_panic != ShouldPanic::No; + let ignore_because_panic_abort = cfg!(target_arch = "wasm32") && !cfg!(target_os = "emscripten") + && desc.should_panic != ShouldPanic::No; if force_ignore || desc.ignore || ignore_because_panic_abort { monitor_ch.send((desc, TrIgnored, Vec::new())).unwrap(); return; } - fn run_test_inner(desc: TestDesc, - monitor_ch: Sender, - nocapture: bool, - testfn: Box) { + fn run_test_inner( + desc: TestDesc, + monitor_ch: Sender, + nocapture: bool, + testfn: Box, + ) { // Buffer for capturing standard I/O let data = Arc::new(Mutex::new(Vec::new())); let data2 = data.clone(); @@ -1440,7 +1419,6 @@ pub fn run_test( .unwrap(); }; - // If the platform is single-threaded we're just going to run // the test synchronously, regardless of the concurrency // level. @@ -1455,27 +1433,25 @@ pub fn run_test( match testfn { DynBenchFn(bencher) => { - ::bench::benchmark(desc, - monitor_ch, - opts.nocapture, - |harness| bencher.run(harness)); + ::bench::benchmark(desc, monitor_ch, opts.nocapture, |harness| { + bencher.run(harness) + }); } StaticBenchFn(benchfn) => { - ::bench::benchmark(desc, - monitor_ch, - opts.nocapture, - |harness| (benchfn.clone())(harness)); + ::bench::benchmark(desc, monitor_ch, opts.nocapture, |harness| { + (benchfn.clone())(harness) + }); } DynTestFn(f) => { - let cb = move || { - __rust_begin_short_backtrace(f) - }; + let cb = move || __rust_begin_short_backtrace(f); run_test_inner(desc, monitor_ch, opts.nocapture, Box::new(cb)) } - StaticTestFn(f) => { - run_test_inner(desc, monitor_ch, opts.nocapture, - Box::new(move || __rust_begin_short_backtrace(f))) - } + StaticTestFn(f) => run_test_inner( + desc, + monitor_ch, + opts.nocapture, + Box::new(move || __rust_begin_short_backtrace(f)), + ), } } @@ -1487,8 +1463,7 @@ fn __rust_begin_short_backtrace(f: F) { fn calc_result(desc: &TestDesc, task_result: Result<(), Box>) -> TestResult { match (&desc.should_panic, task_result) { - (&ShouldPanic::No, Ok(())) | - (&ShouldPanic::Yes, Err(_)) => TrOk, + (&ShouldPanic::No, Ok(())) | (&ShouldPanic::Yes, Err(_)) => TrOk, (&ShouldPanic::YesWithMessage(msg), Err(ref err)) => { if err.downcast_ref::() .map(|e| &**e) @@ -1545,7 +1520,6 @@ impl MetricMap { } } - // Benchmarking /// A function that is opaque to the optimizer, to allow benchmarks to @@ -1566,7 +1540,6 @@ pub fn black_box(dummy: T) -> T { dummy } - impl Bencher { /// Callback for benchmark functions to run in their body. pub fn iter(&mut self, mut inner: F) @@ -1605,7 +1578,6 @@ where return ns_from_dur(start.elapsed()); } - pub fn iter(inner: &mut F) -> stats::Summary where F: FnMut() -> T, @@ -1649,8 +1621,8 @@ where // If we've run for 100ms and seem to have converged to a // stable median. - if loop_run > Duration::from_millis(100) && summ.median_abs_dev_pct < 1.0 && - summ.median - summ5.median < summ5.median_abs_dev + if loop_run > Duration::from_millis(100) && summ.median_abs_dev_pct < 1.0 + && summ.median - summ5.median < summ5.median_abs_dev { return summ5; } @@ -1680,7 +1652,7 @@ pub mod bench { use std::io; use std::sync::{Arc, Mutex}; use stats; - use super::{Bencher, BenchSamples, BenchMode, Sink, MonitorMsg, TestDesc, Sender, TestResult}; + use super::{BenchMode, BenchSamples, Bencher, MonitorMsg, Sender, Sink, TestDesc, TestResult}; pub fn benchmark(desc: TestDesc, monitor_ch: Sender, nocapture: bool, f: F) where @@ -1711,7 +1683,8 @@ pub mod bench { io::set_panic(panicio); }; - let test_result = match result { //bs.bench(f) { + let test_result = match result { + //bs.bench(f) { Ok(Some(ns_iter_summ)) => { let ns_iter = cmp::max(ns_iter_summ.median as u64, 1); let mb_s = bs.bytes * 1000 / ns_iter; @@ -1732,9 +1705,7 @@ pub mod bench { }; TestResult::TrBench(bs) } - Err(_) => { - TestResult::TrFailed - } + Err(_) => TestResult::TrFailed, }; let stdout = data.lock().unwrap().to_vec(); @@ -1756,9 +1727,9 @@ pub mod bench { #[cfg(test)] mod tests { - use test::{TrFailed, TrFailedMsg, TrIgnored, TrOk, filter_tests, parse_opts, TestDesc, - TestDescAndFn, TestOpts, run_test, MetricMap, StaticTestName, DynTestName, - DynTestFn, ShouldPanic}; + use test::{filter_tests, parse_opts, run_test, DynTestFn, DynTestName, MetricMap, ShouldPanic, + StaticTestName, TestDesc, TestDescAndFn, TestOpts, TrFailed, TrFailedMsg, + TrIgnored, TrOk}; use std::sync::mpsc::channel; use bench; use Bencher; @@ -1904,25 +1875,26 @@ mod tests { opts.run_tests = true; opts.run_ignored = true; - let tests = - vec![TestDescAndFn { - desc: TestDesc { - name: StaticTestName("1"), - ignore: true, - should_panic: ShouldPanic::No, - allow_fail: false, - }, - testfn: DynTestFn(Box::new(move || {})), - }, - TestDescAndFn { - desc: TestDesc { - name: StaticTestName("2"), - ignore: false, - should_panic: ShouldPanic::No, - allow_fail: false, - }, - testfn: DynTestFn(Box::new(move || {})), - }]; + let tests = vec![ + TestDescAndFn { + desc: TestDesc { + name: StaticTestName("1"), + ignore: true, + should_panic: ShouldPanic::No, + allow_fail: false, + }, + testfn: DynTestFn(Box::new(move || {})), + }, + TestDescAndFn { + desc: TestDesc { + name: StaticTestName("2"), + ignore: false, + should_panic: ShouldPanic::No, + allow_fail: false, + }, + testfn: DynTestFn(Box::new(move || {})), + }, + ]; let filtered = filter_tests(&opts, tests); assert_eq!(filtered.len(), 1); @@ -1935,17 +1907,16 @@ mod tests { fn tests() -> Vec { vec!["base", "base::test", "base::test1", "base::test2"] .into_iter() - .map(|name| { - TestDescAndFn { - desc: TestDesc { - name: StaticTestName(name), - ignore: false, - should_panic: ShouldPanic::No, - allow_fail: false, - }, - testfn: DynTestFn(Box::new(move || {})) - } - }).collect() + .map(|name| TestDescAndFn { + desc: TestDesc { + name: StaticTestName(name), + ignore: false, + should_panic: ShouldPanic::No, + allow_fail: false, + }, + testfn: DynTestFn(Box::new(move || {})), + }) + .collect() } let substr = filter_tests( @@ -2127,10 +2098,7 @@ mod tests { allow_fail: false, }; - ::bench::benchmark(desc, - tx, - true, - f); + ::bench::benchmark(desc, tx, true, f); rx.recv().unwrap(); } @@ -2149,10 +2117,7 @@ mod tests { allow_fail: false, }; - ::bench::benchmark(desc, - tx, - true, - f); + ::bench::benchmark(desc, tx, true, f); rx.recv().unwrap(); } } diff --git a/src/libtest/stats.rs b/src/libtest/stats.rs index e22fdf77fc171..ddb5dcf2a1cd3 100644 --- a/src/libtest/stats.rs +++ b/src/libtest/stats.rs @@ -279,7 +279,6 @@ impl Stats for [f64] { } } - // Helper function: extract a value representing the `pct` percentile of a sorted sample-set, using // linear interpolation. If samples are not sorted, return nonsensical value. fn percentile_of_sorted(sorted_samples: &[f64], pct: f64) -> f64 { @@ -304,7 +303,6 @@ fn percentile_of_sorted(sorted_samples: &[f64], pct: f64) -> f64 { lo + (hi - lo) * d } - /// Winsorize a set of samples, replacing values above the `100-pct` percentile /// and below the `pct` percentile with those percentiles themselves. This is a /// way of minimizing the effect of outliers, at the cost of biasing the sample. @@ -338,15 +336,18 @@ mod tests { use std::io; macro_rules! assert_approx_eq { - ($a:expr, $b:expr) => ({ + ($a: expr, $b: expr) => {{ let (a, b) = (&$a, &$b); - assert!((*a - *b).abs() < 1.0e-6, - "{} is not approximately equal to {}", *a, *b); - }) + assert!( + (*a - *b).abs() < 1.0e-6, + "{} is not approximately equal to {}", + *a, + *b + ); + }}; } fn check(samples: &[f64], summ: &Summary) { - let summ2 = Summary::new(samples); let mut w = io::sink(); @@ -911,14 +912,18 @@ mod bench { #[bench] pub fn sum_three_items(b: &mut Bencher) { - b.iter(|| { [1e20f64, 1.5f64, -1e20f64].sum(); }) + b.iter(|| { + [1e20f64, 1.5f64, -1e20f64].sum(); + }) } #[bench] pub fn sum_many_f64(b: &mut Bencher) { let nums = [-1e30f64, 1e60, 1e30, 1.0, -1e60]; let v = (0..500).map(|i| nums[i % 5]).collect::>(); - b.iter(|| { v.sum(); }) + b.iter(|| { + v.sum(); + }) } #[bench] diff --git a/src/test/ui/feature-gate-copy-closures.rs b/src/test/compile-fail/feature-gate-termination_trait_test.rs similarity index 69% rename from src/test/ui/feature-gate-copy-closures.rs rename to src/test/compile-fail/feature-gate-termination_trait_test.rs index b11b09eb9fd9b..4af7e94671627 100644 --- a/src/test/ui/feature-gate-copy-closures.rs +++ b/src/test/compile-fail/feature-gate-termination_trait_test.rs @@ -8,12 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn main() { - let a = 5; - let hello = || { - println!("Hello {}", a); - }; +// compile-flags: --test - let b = hello; - let c = hello; //~ ERROR use of moved value: `hello` [E0382] +fn main() {} + +#[cfg(test)] +mod tests { + #[test] + fn it_works() -> Result<(), ()> { + //~^ ERROR functions used as tests must have signature fn() -> () + Ok(()) + } } diff --git a/src/test/compile-fail/not-clone-closure.rs b/src/test/compile-fail/not-clone-closure.rs index 2a30dc4fdd49c..967cb3610ca5f 100644 --- a/src/test/compile-fail/not-clone-closure.rs +++ b/src/test/compile-fail/not-clone-closure.rs @@ -10,8 +10,6 @@ // Check that closures do not implement `Clone` if their environment is not `Clone`. -#![feature(clone_closures)] - struct S(i32); fn main() { diff --git a/src/test/compile-fail/not-copy-closure.rs b/src/test/compile-fail/not-copy-closure.rs index 271e6d5fc90fc..10567c5c961a2 100644 --- a/src/test/compile-fail/not-copy-closure.rs +++ b/src/test/compile-fail/not-copy-closure.rs @@ -10,9 +10,6 @@ // Check that closures do not implement `Copy` if their environment is not `Copy`. -#![feature(copy_closures)] -#![feature(clone_closures)] - fn main() { let mut a = 5; let hello = || { diff --git a/src/test/compile-fail/feature-gate-termination_trait.rs b/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-i32.rs similarity index 71% rename from src/test/compile-fail/feature-gate-termination_trait.rs rename to src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-i32.rs index 5a56445b64e57..0e6ddf7c92f1a 100644 --- a/src/test/compile-fail/feature-gate-termination_trait.rs +++ b/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-i32.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn main() -> i32 { //~ ERROR main function has wrong type [E0580] +fn main() -> i32 { +//~^ ERROR `main` has invalid return type `i32` +//~| NOTE `main` can only return types that implement std::process::Termination +//~| HELP consider using `()`, or a `Result` 0 } diff --git a/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-not-satisfied.rs b/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-not-satisfied.rs index e87e0ceebf1b1..b5f5472b49290 100644 --- a/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-not-satisfied.rs +++ b/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-not-satisfied.rs @@ -8,10 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(termination_trait)] - struct ReturnType {} -fn main() -> ReturnType { //~ ERROR `ReturnType: std::process::Termination` is not satisfied +fn main() -> ReturnType { //~ ERROR `main` has invalid return type `ReturnType` ReturnType {} } diff --git a/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-never.rs b/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-never.rs index c1dd44a91765e..863de85af88fb 100644 --- a/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-never.rs +++ b/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-never.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(termination_trait)] - // error-pattern:oh, dear fn main() -> ! { diff --git a/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-result-box-error_err.rs b/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-result-box-error_err.rs index 8ce27c0a06250..0c6cb4de9567d 100644 --- a/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-result-box-error_err.rs +++ b/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-result-box-error_err.rs @@ -11,8 +11,6 @@ // must-compile-successfully // failure-status: 1 -#![feature(termination_trait)] - use std::io::{Error, ErrorKind}; fn main() -> Result<(), Box> { diff --git a/src/test/run-pass/clone-closure.rs b/src/test/run-pass/clone-closure.rs index 7f554c77fc4f8..0fe3711d8d32e 100644 --- a/src/test/run-pass/clone-closure.rs +++ b/src/test/run-pass/clone-closure.rs @@ -10,8 +10,6 @@ // Check that closures implement `Clone`. -#![feature(clone_closures)] - #[derive(Clone)] struct S(i32); diff --git a/src/test/run-pass/copy-closure.rs b/src/test/run-pass/copy-closure.rs index 309c83ebd99ac..a211d6fc3a385 100644 --- a/src/test/run-pass/copy-closure.rs +++ b/src/test/run-pass/copy-closure.rs @@ -10,9 +10,6 @@ // Check that closures implement `Copy`. -#![feature(copy_closures)] -#![feature(clone_closures)] - fn call T>(f: F) -> T { f() } fn main() { diff --git a/src/test/run-pass/dynamic-drop.rs b/src/test/run-pass/dynamic-drop.rs index 1f543f7be0e8f..765fb06e5f3a4 100644 --- a/src/test/run-pass/dynamic-drop.rs +++ b/src/test/run-pass/dynamic-drop.rs @@ -179,7 +179,7 @@ fn generator(a: &Allocator, run_count: usize) { ); }; for _ in 0..run_count { - gen.resume(); + unsafe { gen.resume(); } } } diff --git a/src/test/run-pass/generator/conditional-drop.rs b/src/test/run-pass/generator/conditional-drop.rs index 8329684e1a39b..3d39c46186be3 100644 --- a/src/test/run-pass/generator/conditional-drop.rs +++ b/src/test/run-pass/generator/conditional-drop.rs @@ -42,9 +42,9 @@ fn t1() { }; let n = A.load(Ordering::SeqCst); - a.resume(); + unsafe { a.resume() }; assert_eq!(A.load(Ordering::SeqCst), n + 1); - a.resume(); + unsafe { a.resume() }; assert_eq!(A.load(Ordering::SeqCst), n + 1); } @@ -58,8 +58,8 @@ fn t2() { }; let n = A.load(Ordering::SeqCst); - a.resume(); + unsafe { a.resume() }; assert_eq!(A.load(Ordering::SeqCst), n); - a.resume(); + unsafe { a.resume() }; assert_eq!(A.load(Ordering::SeqCst), n + 1); } diff --git a/src/test/run-pass/generator/control-flow.rs b/src/test/run-pass/generator/control-flow.rs index 60a00b4e46756..09971410e556d 100644 --- a/src/test/run-pass/generator/control-flow.rs +++ b/src/test/run-pass/generator/control-flow.rs @@ -16,7 +16,7 @@ fn finish(mut amt: usize, mut t: T) -> T::Return where T: Generator { loop { - match t.resume() { + match unsafe { t.resume() } { GeneratorState::Yielded(()) => amt = amt.checked_sub(1).unwrap(), GeneratorState::Complete(ret) => { assert_eq!(amt, 0); diff --git a/src/test/run-pass/generator/drop-env.rs b/src/test/run-pass/generator/drop-env.rs index ac42a25899dbb..ef4dc24472e61 100644 --- a/src/test/run-pass/generator/drop-env.rs +++ b/src/test/run-pass/generator/drop-env.rs @@ -37,7 +37,7 @@ fn t1() { }; let n = A.load(Ordering::SeqCst); - drop(foo.resume()); + drop(unsafe { foo.resume() }); assert_eq!(A.load(Ordering::SeqCst), n); drop(foo); assert_eq!(A.load(Ordering::SeqCst), n + 1); @@ -50,7 +50,7 @@ fn t2() { }; let n = A.load(Ordering::SeqCst); - drop(foo.resume()); + drop(unsafe { foo.resume() }); assert_eq!(A.load(Ordering::SeqCst), n + 1); drop(foo); assert_eq!(A.load(Ordering::SeqCst), n + 1); diff --git a/src/test/run-pass/generator/issue-44197.rs b/src/test/run-pass/generator/issue-44197.rs index 7cb80ea8b21b7..8ce4fc6affab3 100644 --- a/src/test/run-pass/generator/issue-44197.rs +++ b/src/test/run-pass/generator/issue-44197.rs @@ -35,6 +35,8 @@ fn bar2(baz: String) -> impl Generator { } fn main() { - assert_eq!(bar(String::new()).resume(), GeneratorState::Yielded(String::new())); - assert_eq!(bar2(String::new()).resume(), GeneratorState::Complete(())); + unsafe { + assert_eq!(bar(String::new()).resume(), GeneratorState::Yielded(String::new())); + assert_eq!(bar2(String::new()).resume(), GeneratorState::Complete(())); + } } diff --git a/src/test/run-pass/generator/iterator-count.rs b/src/test/run-pass/generator/iterator-count.rs index 9afe95f9e865c..654b18928c077 100644 --- a/src/test/run-pass/generator/iterator-count.rs +++ b/src/test/run-pass/generator/iterator-count.rs @@ -14,11 +14,13 @@ use std::ops::{GeneratorState, Generator}; struct W(T); +// This impl isn't safe in general, but the generator used in this test is movable +// so it won't cause problems. impl> Iterator for W { type Item = T::Yield; fn next(&mut self) -> Option { - match self.0.resume() { + match unsafe { self.0.resume() } { GeneratorState::Complete(..) => None, GeneratorState::Yielded(v) => Some(v), } diff --git a/src/test/run-pass/generator/live-upvar-across-yield.rs b/src/test/run-pass/generator/live-upvar-across-yield.rs index e34b0b3100c32..28e7da232ce09 100644 --- a/src/test/run-pass/generator/live-upvar-across-yield.rs +++ b/src/test/run-pass/generator/live-upvar-across-yield.rs @@ -17,5 +17,5 @@ fn main() { let mut a = || { b(yield); }; - a.resume(); + unsafe { a.resume() }; } diff --git a/src/test/run-pass/generator/nested_generators.rs b/src/test/run-pass/generator/nested_generators.rs index f70d4144a3c9e..29808da85a7a9 100644 --- a/src/test/run-pass/generator/nested_generators.rs +++ b/src/test/run-pass/generator/nested_generators.rs @@ -20,7 +20,7 @@ fn main() { yield 2; }; - match sub_generator.resume() { + match unsafe { sub_generator.resume() } { GeneratorState::Yielded(x) => { yield x; } diff --git a/src/test/run-pass/generator/panic-drops.rs b/src/test/run-pass/generator/panic-drops.rs index 36e401a54bcdd..3d7b60ab6b901 100644 --- a/src/test/run-pass/generator/panic-drops.rs +++ b/src/test/run-pass/generator/panic-drops.rs @@ -42,7 +42,7 @@ fn main() { assert_eq!(A.load(Ordering::SeqCst), 0); let res = panic::catch_unwind(panic::AssertUnwindSafe(|| { - foo.resume() + unsafe { foo.resume() } })); assert!(res.is_err()); assert_eq!(A.load(Ordering::SeqCst), 1); @@ -57,7 +57,7 @@ fn main() { assert_eq!(A.load(Ordering::SeqCst), 1); let res = panic::catch_unwind(panic::AssertUnwindSafe(|| { - foo.resume() + unsafe { foo.resume() } })); assert!(res.is_err()); assert_eq!(A.load(Ordering::SeqCst), 1); diff --git a/src/test/run-pass/generator/panic-safe.rs b/src/test/run-pass/generator/panic-safe.rs index 0d5bae7876bd3..ace5cdde51d85 100644 --- a/src/test/run-pass/generator/panic-safe.rs +++ b/src/test/run-pass/generator/panic-safe.rs @@ -24,13 +24,13 @@ fn main() { }; let res = panic::catch_unwind(panic::AssertUnwindSafe(|| { - foo.resume() + unsafe { foo.resume() } })); assert!(res.is_err()); for _ in 0..10 { let res = panic::catch_unwind(panic::AssertUnwindSafe(|| { - foo.resume() + unsafe { foo.resume() } })); assert!(res.is_err()); } diff --git a/src/test/run-pass/generator/resume-after-return.rs b/src/test/run-pass/generator/resume-after-return.rs index 56511dcd53a6a..06e7615d26191 100644 --- a/src/test/run-pass/generator/resume-after-return.rs +++ b/src/test/run-pass/generator/resume-after-return.rs @@ -23,12 +23,12 @@ fn main() { yield; }; - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Complete(()) => {} s => panic!("bad state: {:?}", s), } - match panic::catch_unwind(move || foo.resume()) { + match panic::catch_unwind(move || unsafe { foo.resume() }) { Ok(_) => panic!("generator successfully resumed"), Err(_) => {} } diff --git a/src/test/run-pass/generator/smoke.rs b/src/test/run-pass/generator/smoke.rs index 8693964665d34..7395c8484c169 100644 --- a/src/test/run-pass/generator/smoke.rs +++ b/src/test/run-pass/generator/smoke.rs @@ -24,7 +24,7 @@ fn simple() { } }; - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Complete(()) => {} s => panic!("bad state: {:?}", s), } @@ -40,7 +40,7 @@ fn return_capture() { a }; - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Complete(ref s) if *s == "foo" => {} s => panic!("bad state: {:?}", s), } @@ -52,11 +52,11 @@ fn simple_yield() { yield; }; - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Yielded(()) => {} s => panic!("bad state: {:?}", s), } - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Complete(()) => {} s => panic!("bad state: {:?}", s), } @@ -69,11 +69,11 @@ fn yield_capture() { yield b; }; - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Yielded(ref s) if *s == "foo" => {} s => panic!("bad state: {:?}", s), } - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Complete(()) => {} s => panic!("bad state: {:?}", s), } @@ -86,11 +86,11 @@ fn simple_yield_value() { return String::from("foo") }; - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Yielded(ref s) if *s == "bar" => {} s => panic!("bad state: {:?}", s), } - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Complete(ref s) if *s == "foo" => {} s => panic!("bad state: {:?}", s), } @@ -104,11 +104,11 @@ fn return_after_yield() { return a }; - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Yielded(()) => {} s => panic!("bad state: {:?}", s), } - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Complete(ref s) if *s == "foo" => {} s => panic!("bad state: {:?}", s), } @@ -156,11 +156,11 @@ fn send_and_sync() { fn send_over_threads() { let mut foo = || { yield }; thread::spawn(move || { - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Yielded(()) => {} s => panic!("bad state: {:?}", s), } - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Complete(()) => {} s => panic!("bad state: {:?}", s), } @@ -169,11 +169,11 @@ fn send_over_threads() { let a = String::from("a"); let mut foo = || { yield a }; thread::spawn(move || { - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Yielded(ref s) if *s == "a" => {} s => panic!("bad state: {:?}", s), } - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Complete(()) => {} s => panic!("bad state: {:?}", s), } diff --git a/src/test/run-pass/generator/static-generators.rs b/src/test/run-pass/generator/static-generators.rs index 9504414d8b6f5..ebc070eee09c1 100644 --- a/src/test/run-pass/generator/static-generators.rs +++ b/src/test/run-pass/generator/static-generators.rs @@ -13,14 +13,14 @@ use std::ops::{Generator, GeneratorState}; fn main() { - let mut generator = unsafe { - static || { - let a = true; - let b = &a; - yield; - assert_eq!(b as *const _, &a as *const _); - } + let mut generator = static || { + let a = true; + let b = &a; + yield; + assert_eq!(b as *const _, &a as *const _); }; - assert_eq!(generator.resume(), GeneratorState::Yielded(())); - assert_eq!(generator.resume(), GeneratorState::Complete(())); + unsafe { + assert_eq!(generator.resume(), GeneratorState::Yielded(())); + assert_eq!(generator.resume(), GeneratorState::Complete(())); + } } diff --git a/src/test/run-pass/generator/xcrate-reachable.rs b/src/test/run-pass/generator/xcrate-reachable.rs index dff5e08b9c20e..8eeb013314499 100644 --- a/src/test/run-pass/generator/xcrate-reachable.rs +++ b/src/test/run-pass/generator/xcrate-reachable.rs @@ -17,5 +17,5 @@ extern crate xcrate_reachable as foo; use std::ops::Generator; fn main() { - foo::foo().resume(); + unsafe { foo::foo().resume(); } } diff --git a/src/test/run-pass/generator/xcrate.rs b/src/test/run-pass/generator/xcrate.rs index dc7a6fdef9c7e..04791d5135677 100644 --- a/src/test/run-pass/generator/xcrate.rs +++ b/src/test/run-pass/generator/xcrate.rs @@ -19,18 +19,18 @@ use std::ops::{GeneratorState, Generator}; fn main() { let mut foo = xcrate::foo(); - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Complete(()) => {} s => panic!("bad state: {:?}", s), } let mut foo = xcrate::bar(3); - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Yielded(3) => {} s => panic!("bad state: {:?}", s), } - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Complete(()) => {} s => panic!("bad state: {:?}", s), } diff --git a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-empty.rs b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-empty.rs index 5e534da012875..046d27a9f0fe5 100644 --- a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-empty.rs +++ b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-empty.rs @@ -8,6 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(termination_trait)] - fn main() {} diff --git a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-exitcode.rs b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-exitcode.rs index 80fa4d17b6116..4aa7d8c3a77d2 100644 --- a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-exitcode.rs +++ b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-exitcode.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(termination_trait)] #![feature(process_exitcode_placeholder)] use std::process::ExitCode; diff --git a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-result-box-error_ok.rs b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-result-box-error_ok.rs index 269ac451cf4d8..33686ed0b8fa2 100644 --- a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-result-box-error_ok.rs +++ b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-result-box-error_ok.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(termination_trait)] - use std::io::Error; fn main() -> Result<(), Box> { diff --git a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-result.rs b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-result.rs index 751db0fb50082..1c87e31e763e9 100644 --- a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-result.rs +++ b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-result.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(termination_trait)] - use std::io::Error; fn main() -> Result<(), Error> { diff --git a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-in-test.rs b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-in-test.rs index 494500d522abe..11997eb691728 100644 --- a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-in-test.rs +++ b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-in-test.rs @@ -10,7 +10,7 @@ // compile-flags: --test -#![feature(termination_trait)] +#![feature(termination_trait_test)] #![feature(test)] extern crate test; diff --git a/src/test/ui-fulldeps/custom-derive/issue-36935.stderr b/src/test/ui-fulldeps/custom-derive/issue-36935.stderr index b082999a8978d..0278256994120 100644 --- a/src/test/ui-fulldeps/custom-derive/issue-36935.stderr +++ b/src/test/ui-fulldeps/custom-derive/issue-36935.stderr @@ -6,3 +6,5 @@ LL | #[derive(Foo, Bar)] //~ ERROR proc-macro derive panicked | = help: message: lolnope +error: aborting due to previous error + diff --git a/src/test/ui-fulldeps/proc-macro/load-panic.stderr b/src/test/ui-fulldeps/proc-macro/load-panic.stderr index edfd134469cda..30ad53f9041f0 100644 --- a/src/test/ui-fulldeps/proc-macro/load-panic.stderr +++ b/src/test/ui-fulldeps/proc-macro/load-panic.stderr @@ -6,3 +6,5 @@ LL | #[derive(A)] | = help: message: nope! +error: aborting due to previous error + diff --git a/src/test/ui/codemap_tests/two_files.stderr b/src/test/ui/codemap_tests/two_files.stderr index 614531c982128..e247e86fbcb22 100644 --- a/src/test/ui/codemap_tests/two_files.stderr +++ b/src/test/ui/codemap_tests/two_files.stderr @@ -4,5 +4,6 @@ error[E0404]: expected trait, found type alias `Bar` LL | impl Bar for Baz { } //~ ERROR expected trait, found type alias | ^^^ type aliases cannot be used for traits -error: cannot continue compilation due to previous error +error: aborting due to previous error +For more information about this error, try `rustc --explain E0404`. diff --git a/src/test/ui/cross-file-errors/main.stderr b/src/test/ui/cross-file-errors/main.stderr index 41a2172d29580..a64595fbb4020 100644 --- a/src/test/ui/cross-file-errors/main.stderr +++ b/src/test/ui/cross-file-errors/main.stderr @@ -9,3 +9,5 @@ LL | _ LL | underscore!(); | -------------- in this macro invocation +error: aborting due to previous error + diff --git a/src/test/ui/did_you_mean/recursion_limit_macro.stderr b/src/test/ui/did_you_mean/recursion_limit_macro.stderr index f6bce55528c7d..265a688df9910 100644 --- a/src/test/ui/did_you_mean/recursion_limit_macro.stderr +++ b/src/test/ui/did_you_mean/recursion_limit_macro.stderr @@ -9,3 +9,5 @@ LL | recurse!(0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9); | = help: consider adding a `#![recursion_limit="20"]` attribute to your crate +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0404.stderr b/src/test/ui/error-codes/E0404.stderr index 9f705da586167..afb748bedbe0f 100644 --- a/src/test/ui/error-codes/E0404.stderr +++ b/src/test/ui/error-codes/E0404.stderr @@ -10,5 +10,6 @@ error[E0404]: expected trait, found struct `Foo` LL | fn baz(_: T) {} //~ ERROR E0404 | ^^^ not a trait -error: cannot continue compilation due to previous error +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0404`. diff --git a/src/test/ui/error-codes/E0405.stderr b/src/test/ui/error-codes/E0405.stderr index b5901dd9c848b..27190af1c6c11 100644 --- a/src/test/ui/error-codes/E0405.stderr +++ b/src/test/ui/error-codes/E0405.stderr @@ -4,5 +4,6 @@ error[E0405]: cannot find trait `SomeTrait` in this scope LL | impl SomeTrait for Foo {} //~ ERROR E0405 | ^^^^^^^^^ not found in this scope -error: cannot continue compilation due to previous error +error: aborting due to previous error +For more information about this error, try `rustc --explain E0405`. diff --git a/src/test/ui/feature-gate-clone-closures.rs b/src/test/ui/feature-gate-clone-closures.rs deleted file mode 100644 index a15153ea7bf0a..0000000000000 --- a/src/test/ui/feature-gate-clone-closures.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[derive(Clone)] -struct S(i32); - -fn main() { - let a = S(5); - let hello = move || { - println!("Hello {}", a.0); - }; - - let hello = hello.clone(); //~ ERROR no method named `clone` found for type -} diff --git a/src/test/ui/feature-gate-clone-closures.stderr b/src/test/ui/feature-gate-clone-closures.stderr deleted file mode 100644 index 7038a76380d6b..0000000000000 --- a/src/test/ui/feature-gate-clone-closures.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0599]: no method named `clone` found for type `[closure@$DIR/feature-gate-clone-closures.rs:16:17: 18:6 a:_]` in the current scope - --> $DIR/feature-gate-clone-closures.rs:20:23 - | -LL | let hello = hello.clone(); //~ ERROR no method named `clone` found for type - | ^^^^^ - | - = note: hello is a function, perhaps you wish to call it - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/feature-gate-copy-closures.stderr b/src/test/ui/feature-gate-copy-closures.stderr deleted file mode 100644 index e72680b69eaea..0000000000000 --- a/src/test/ui/feature-gate-copy-closures.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0382]: use of moved value: `hello` - --> $DIR/feature-gate-copy-closures.rs:18:9 - | -LL | let b = hello; - | - value moved here -LL | let c = hello; //~ ERROR use of moved value: `hello` [E0382] - | ^ value used here after move - | - = note: move occurs because `hello` has type `[closure@$DIR/feature-gate-copy-closures.rs:13:17: 15:6 a:&i32]`, which does not implement the `Copy` trait - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/feature-gate-fn_must_use-cap-lints-allow.stderr b/src/test/ui/feature-gate-fn_must_use-cap-lints-allow.stderr index a9952ff4fac13..a2c1dedff385a 100644 --- a/src/test/ui/feature-gate-fn_must_use-cap-lints-allow.stderr +++ b/src/test/ui/feature-gate-fn_must_use-cap-lints-allow.stderr @@ -4,3 +4,5 @@ error: compilation successful LL | fn main() {} //~ ERROR compilation successful | ^^^^^^^^^^^^ +error: aborting due to previous error + diff --git a/src/test/ui/feature-gate-fn_must_use.stderr b/src/test/ui/feature-gate-fn_must_use.stderr index 4772cf28f6c12..431c57abd2653 100644 --- a/src/test/ui/feature-gate-fn_must_use.stderr +++ b/src/test/ui/feature-gate-fn_must_use.stderr @@ -20,3 +20,5 @@ error: compilation successful LL | fn main() {} //~ ERROR compilation successful | ^^^^^^^^^^^^ +error: aborting due to previous error + diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr index 9c4fb79f6f1aa..0beed62798710 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr +++ b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr @@ -1316,3 +1316,5 @@ LL | | println!("Hello World"); LL | | } | |_^ +error: aborting due to previous error + diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-deprecated.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-deprecated.stderr index 83f6e016370bb..802c5d9384d75 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-deprecated.stderr +++ b/src/test/ui/feature-gate/issue-43106-gating-of-deprecated.stderr @@ -6,3 +6,5 @@ LL | | println!("Hello World"); LL | | } | |_^ +error: aborting due to previous error + diff --git a/src/test/ui/generator/borrowing.rs b/src/test/ui/generator/borrowing.rs index de10bdef4aee0..e56927d818231 100644 --- a/src/test/ui/generator/borrowing.rs +++ b/src/test/ui/generator/borrowing.rs @@ -15,7 +15,7 @@ use std::ops::Generator; fn main() { let _b = { let a = 3; - (|| yield &a).resume() + unsafe { (|| yield &a).resume() } //~^ ERROR: `a` does not live long enough }; diff --git a/src/test/ui/generator/borrowing.stderr b/src/test/ui/generator/borrowing.stderr index 2a5de3790ada9..45d950b5aef64 100644 --- a/src/test/ui/generator/borrowing.stderr +++ b/src/test/ui/generator/borrowing.stderr @@ -1,10 +1,10 @@ error[E0597]: `a` does not live long enough - --> $DIR/borrowing.rs:18:20 + --> $DIR/borrowing.rs:18:29 | -LL | (|| yield &a).resume() - | -- ^ borrowed value does not live long enough - | | - | capture occurs here +LL | unsafe { (|| yield &a).resume() } + | -- ^ borrowed value does not live long enough + | | + | capture occurs here LL | //~^ ERROR: `a` does not live long enough LL | }; | - borrowed value only lives until here diff --git a/src/test/ui/generator/dropck.rs b/src/test/ui/generator/dropck.rs index 0b143d7f5143e..b2240fb225f58 100644 --- a/src/test/ui/generator/dropck.rs +++ b/src/test/ui/generator/dropck.rs @@ -23,6 +23,6 @@ fn main() { let _d = ref_.take(); //~ ERROR `ref_` does not live long enough yield; }; - gen.resume(); + unsafe { gen.resume(); } // drops the RefCell and then the Ref, leading to use-after-free } diff --git a/src/test/ui/generator/sized-yield.rs b/src/test/ui/generator/sized-yield.rs index f38ebf8b94636..a1c8ca77e41e8 100644 --- a/src/test/ui/generator/sized-yield.rs +++ b/src/test/ui/generator/sized-yield.rs @@ -17,5 +17,5 @@ fn main() { let mut gen = move || { //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied yield s[..]; }; - gen.resume(); //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied + unsafe { gen.resume(); } //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied } diff --git a/src/test/ui/generator/sized-yield.stderr b/src/test/ui/generator/sized-yield.stderr index fc99c7e3bd747..957fac172c258 100644 --- a/src/test/ui/generator/sized-yield.stderr +++ b/src/test/ui/generator/sized-yield.stderr @@ -11,10 +11,10 @@ LL | | }; = note: the yield type of a generator must have a statically known size error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied - --> $DIR/sized-yield.rs:20:8 + --> $DIR/sized-yield.rs:20:17 | -LL | gen.resume(); //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied - | ^^^^^^ `str` does not have a constant size known at compile-time +LL | unsafe { gen.resume(); } //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied + | ^^^^^^ `str` does not have a constant size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `str` diff --git a/src/test/ui/generator/unsafe-immovable.rs b/src/test/ui/generator/unsafe-immovable.rs deleted file mode 100644 index 45acbf50931bc..0000000000000 --- a/src/test/ui/generator/unsafe-immovable.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![feature(generators)] - -fn main() { - static || { //~ ERROR: construction of immovable generator requires unsafe - yield; - }; -} diff --git a/src/test/ui/generator/unsafe-immovable.stderr b/src/test/ui/generator/unsafe-immovable.stderr deleted file mode 100644 index b2add55613d54..0000000000000 --- a/src/test/ui/generator/unsafe-immovable.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0133]: construction of immovable generator requires unsafe function or block - --> $DIR/unsafe-immovable.rs:14:5 - | -LL | / static || { //~ ERROR: construction of immovable generator requires unsafe -LL | | yield; -LL | | }; - | |_____^ construction of immovable generator - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/generator/yield-while-iterating.rs b/src/test/ui/generator/yield-while-iterating.rs index bc53448cb08e6..b8a67a0e7b65d 100644 --- a/src/test/ui/generator/yield-while-iterating.rs +++ b/src/test/ui/generator/yield-while-iterating.rs @@ -43,7 +43,7 @@ fn yield_during_iter_borrowed_slice_2() { println!("{:?}", x); } -fn yield_during_iter_borrowed_slice_3() { +unsafe fn yield_during_iter_borrowed_slice_3() { // OK to take a mutable ref to `x` and yield // up pointers from it: let mut x = vec![22_i32]; @@ -55,7 +55,7 @@ fn yield_during_iter_borrowed_slice_3() { b.resume(); } -fn yield_during_iter_borrowed_slice_4() { +unsafe fn yield_during_iter_borrowed_slice_4() { // ...but not OK to do that while reading // from `x` too let mut x = vec![22_i32]; @@ -68,7 +68,7 @@ fn yield_during_iter_borrowed_slice_4() { b.resume(); } -fn yield_during_range_iter() { +unsafe fn yield_during_range_iter() { // Should be OK. let mut b = || { let v = vec![1,2,3]; diff --git a/src/test/ui/generator/yield-while-local-borrowed.rs b/src/test/ui/generator/yield-while-local-borrowed.rs index 11bd4ed05caca..3dc2650a2ecbf 100644 --- a/src/test/ui/generator/yield-while-local-borrowed.rs +++ b/src/test/ui/generator/yield-while-local-borrowed.rs @@ -15,7 +15,7 @@ use std::ops::{GeneratorState, Generator}; use std::cell::Cell; -fn borrow_local_inline() { +unsafe fn borrow_local_inline() { // Not OK to yield with a borrow of a temporary. // // (This error occurs because the region shows up in the type of @@ -30,7 +30,7 @@ fn borrow_local_inline() { b.resume(); } -fn borrow_local_inline_done() { +unsafe fn borrow_local_inline_done() { // No error here -- `a` is not in scope at the point of `yield`. let mut b = move || { { @@ -41,7 +41,7 @@ fn borrow_local_inline_done() { b.resume(); } -fn borrow_local() { +unsafe fn borrow_local() { // Not OK to yield with a borrow of a temporary. // // (This error occurs because the region shows up in the type of diff --git a/src/test/ui/generator/yield-while-ref-reborrowed.rs b/src/test/ui/generator/yield-while-ref-reborrowed.rs index b9c963ae74077..573dd4377bb2c 100644 --- a/src/test/ui/generator/yield-while-ref-reborrowed.rs +++ b/src/test/ui/generator/yield-while-ref-reborrowed.rs @@ -13,7 +13,7 @@ use std::ops::{GeneratorState, Generator}; use std::cell::Cell; -fn reborrow_shared_ref(x: &i32) { +unsafe fn reborrow_shared_ref(x: &i32) { // This is OK -- we have a borrow live over the yield, but it's of // data that outlives the generator. let mut b = move || { @@ -24,7 +24,7 @@ fn reborrow_shared_ref(x: &i32) { b.resume(); } -fn reborrow_mutable_ref(x: &mut i32) { +unsafe fn reborrow_mutable_ref(x: &mut i32) { // This is OK -- we have a borrow live over the yield, but it's of // data that outlives the generator. let mut b = move || { @@ -35,7 +35,7 @@ fn reborrow_mutable_ref(x: &mut i32) { b.resume(); } -fn reborrow_mutable_ref_2(x: &mut i32) { +unsafe fn reborrow_mutable_ref_2(x: &mut i32) { // ...but not OK to go on using `x`. let mut b = || { let a = &mut *x; diff --git a/src/test/ui/impl-trait/universal_wrong_bounds.stderr b/src/test/ui/impl-trait/universal_wrong_bounds.stderr index a02fc1f748faa..3cc0bebe81655 100644 --- a/src/test/ui/impl-trait/universal_wrong_bounds.stderr +++ b/src/test/ui/impl-trait/universal_wrong_bounds.stderr @@ -24,5 +24,7 @@ help: possible candidate is found in another module, you can import it into scop LL | use std::fmt::Debug; | -error: cannot continue compilation due to previous error +error: aborting due to 3 previous errors +Some errors occurred: E0405, E0425. +For more information about an error, try `rustc --explain E0405`. diff --git a/src/test/ui/issue-22644.stderr b/src/test/ui/issue-22644.stderr index 257b9bd235d76..aeb465b2ab233 100644 --- a/src/test/ui/issue-22644.stderr +++ b/src/test/ui/issue-22644.stderr @@ -89,3 +89,5 @@ error: expected type, found `4` LL | println!("{}", a: &mut 4); //~ ERROR expected type, found `4` | ^ expecting a type here because of type ascription +error: aborting due to 9 previous errors + diff --git a/src/test/ui/issue-44406.stderr b/src/test/ui/issue-44406.stderr index 443b28cf09968..de7c11732e4a3 100644 --- a/src/test/ui/issue-44406.stderr +++ b/src/test/ui/issue-44406.stderr @@ -13,3 +13,5 @@ LL | bar(baz: $rest) LL | foo!(true); //~ ERROR expected type, found keyword | ^^^^ expecting a type here because of type ascription +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/unboxed-closer-non-implicit-copyable.rs b/src/test/ui/issue-49257.rs similarity index 53% rename from src/test/compile-fail/unboxed-closer-non-implicit-copyable.rs rename to src/test/ui/issue-49257.rs index 2d55979491981..a319849223740 100644 --- a/src/test/compile-fail/unboxed-closer-non-implicit-copyable.rs +++ b/src/test/ui/issue-49257.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,12 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(unboxed_closures)] +// Test for #49257: +// emits good diagnostics for `..` pattern fragments not in the last position. -fn to_fn_once>(f: F) -> F { f } +#![allow(unused)] + +struct Point { x: u8, y: u8 } fn main() { - let f = to_fn_once(move|| ()); - f(); - f(); //~ ERROR use of moved value + let p = Point { x: 0, y: 0 }; + let Point { .., y } = p; //~ ERROR expected `}`, found `,` + //~| ERROR pattern does not mention fields `x`, `y` } diff --git a/src/test/ui/issue-49257.stderr b/src/test/ui/issue-49257.stderr new file mode 100644 index 0000000000000..fec990764bb14 --- /dev/null +++ b/src/test/ui/issue-49257.stderr @@ -0,0 +1,15 @@ +error: expected `}`, found `,` + --> $DIR/issue-49257.rs:20:19 + | +LL | let Point { .., y } = p; //~ ERROR expected `}`, found `,` + | ^ `..` must be in the last position, and cannot have a trailing comma + +error[E0027]: pattern does not mention fields `x`, `y` + --> $DIR/issue-49257.rs:20:9 + | +LL | let Point { .., y } = p; //~ ERROR expected `}`, found `,` + | ^^^^^^^^^^^^^^^ missing fields `x`, `y` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0027`. diff --git a/src/test/ui/lint-output-format-2.stderr b/src/test/ui/lint-output-format-2.stderr index b2d1e1ac05822..d484061ef9661 100644 --- a/src/test/ui/lint-output-format-2.stderr +++ b/src/test/ui/lint-output-format-2.stderr @@ -22,3 +22,5 @@ LL | | let _y = bar(); LL | | } | |_^ +error: aborting due to previous error + diff --git a/src/test/ui/loops-reject-duplicate-labels-2.stderr b/src/test/ui/loops-reject-duplicate-labels-2.stderr index d35ed4ff88a67..830270a99d112 100644 --- a/src/test/ui/loops-reject-duplicate-labels-2.stderr +++ b/src/test/ui/loops-reject-duplicate-labels-2.stderr @@ -70,3 +70,5 @@ LL | | foo(); LL | | } | |_^ +error: aborting due to previous error + diff --git a/src/test/ui/loops-reject-duplicate-labels.stderr b/src/test/ui/loops-reject-duplicate-labels.stderr index d1b874ea99729..a71f98b812a8c 100644 --- a/src/test/ui/loops-reject-duplicate-labels.stderr +++ b/src/test/ui/loops-reject-duplicate-labels.stderr @@ -73,3 +73,5 @@ LL | | foo(); LL | | } | |_^ +error: aborting due to previous error + diff --git a/src/test/ui/loops-reject-labels-shadowing-lifetimes.stderr b/src/test/ui/loops-reject-labels-shadowing-lifetimes.stderr index 0cdd58fdbd75d..af524d5b01766 100644 --- a/src/test/ui/loops-reject-labels-shadowing-lifetimes.stderr +++ b/src/test/ui/loops-reject-labels-shadowing-lifetimes.stderr @@ -108,3 +108,5 @@ LL | | foo(); LL | | } | |_^ +error: aborting due to previous error + diff --git a/src/test/ui/loops-reject-lifetime-shadowing-label.stderr b/src/test/ui/loops-reject-lifetime-shadowing-label.stderr index a050aec50c72b..999cfb9cc3c6b 100644 --- a/src/test/ui/loops-reject-lifetime-shadowing-label.stderr +++ b/src/test/ui/loops-reject-lifetime-shadowing-label.stderr @@ -14,3 +14,5 @@ LL | | foo(); LL | | } | |_^ +error: aborting due to previous error + diff --git a/src/test/ui/macro-context.stderr b/src/test/ui/macro-context.stderr index 4dc6bbe4d656c..b3e67fb2607cd 100644 --- a/src/test/ui/macro-context.stderr +++ b/src/test/ui/macro-context.stderr @@ -43,3 +43,5 @@ LL | () => ( i ; typeof ); //~ ERROR expected expression, found reserved k LL | m!(); | ----- in this macro invocation +error: aborting due to 4 previous errors + diff --git a/src/test/ui/macros/macro_path_as_generic_bound.stderr b/src/test/ui/macros/macro_path_as_generic_bound.stderr index 06d22714dd8b6..0f9f0607c5bf2 100644 --- a/src/test/ui/macros/macro_path_as_generic_bound.stderr +++ b/src/test/ui/macros/macro_path_as_generic_bound.stderr @@ -4,5 +4,6 @@ error[E0433]: failed to resolve. Use of undeclared type or module `m` LL | foo!(m::m2::A); //~ ERROR failed to resolve | ^ Use of undeclared type or module `m` -error: cannot continue compilation due to previous error +error: aborting due to previous error +For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/ui/macros/trace_faulty_macros.stderr b/src/test/ui/macros/trace_faulty_macros.stderr index 9fb5b17a3114b..a9ffef8ef8090 100644 --- a/src/test/ui/macros/trace_faulty_macros.stderr +++ b/src/test/ui/macros/trace_faulty_macros.stderr @@ -45,3 +45,5 @@ LL | my_recursive_macro!(); = note: expanding `my_recursive_macro! { }` = note: to `my_recursive_macro ! ( ) ;` +error: aborting due to 2 previous errors + diff --git a/src/test/ui/raw_string.stderr b/src/test/ui/raw_string.stderr index b8aa596ef953a..ddf1cfe406f7c 100644 --- a/src/test/ui/raw_string.stderr +++ b/src/test/ui/raw_string.stderr @@ -6,3 +6,5 @@ LL | let x = r##"lol"#; | = note: this raw string should be terminated with `"##` +error: aborting due to previous error + diff --git a/src/test/ui/resolve/issue-21221-1.stderr b/src/test/ui/resolve/issue-21221-1.stderr index a9d2aeee2d151..3edfa33d80a02 100644 --- a/src/test/ui/resolve/issue-21221-1.stderr +++ b/src/test/ui/resolve/issue-21221-1.stderr @@ -45,5 +45,7 @@ help: possible candidate is found in another module, you can import it into scop LL | use std::ops::Div; | -error: cannot continue compilation due to previous error +error: aborting due to 4 previous errors +Some errors occurred: E0405, E0412. +For more information about an error, try `rustc --explain E0405`. diff --git a/src/test/ui/resolve/issue-21221-2.stderr b/src/test/ui/resolve/issue-21221-2.stderr index c61ffe3b33e8a..e11fe9ac4cf11 100644 --- a/src/test/ui/resolve/issue-21221-2.stderr +++ b/src/test/ui/resolve/issue-21221-2.stderr @@ -8,5 +8,6 @@ help: possible candidate is found in another module, you can import it into scop LL | use foo::bar::T; | -error: cannot continue compilation due to previous error +error: aborting due to previous error +For more information about this error, try `rustc --explain E0405`. diff --git a/src/test/ui/resolve/issue-21221-3.stderr b/src/test/ui/resolve/issue-21221-3.stderr index 7725f74cb49fc..f406cd6e35fcf 100644 --- a/src/test/ui/resolve/issue-21221-3.stderr +++ b/src/test/ui/resolve/issue-21221-3.stderr @@ -8,5 +8,6 @@ help: possible candidate is found in another module, you can import it into scop LL | use issue_21221_3::outer::OuterTrait; | -error: cannot continue compilation due to previous error +error: aborting due to previous error +For more information about this error, try `rustc --explain E0405`. diff --git a/src/test/ui/resolve/issue-21221-4.stderr b/src/test/ui/resolve/issue-21221-4.stderr index b0a4d5ba4d898..c0a7f1734f49c 100644 --- a/src/test/ui/resolve/issue-21221-4.stderr +++ b/src/test/ui/resolve/issue-21221-4.stderr @@ -8,5 +8,6 @@ help: possible candidate is found in another module, you can import it into scop LL | use issue_21221_4::T; | -error: cannot continue compilation due to previous error +error: aborting due to previous error +For more information about this error, try `rustc --explain E0405`. diff --git a/src/test/ui/resolve/issue-3907.stderr b/src/test/ui/resolve/issue-3907.stderr index 2b8b2b20685f8..3627c09b28fd9 100644 --- a/src/test/ui/resolve/issue-3907.stderr +++ b/src/test/ui/resolve/issue-3907.stderr @@ -8,5 +8,6 @@ help: possible better candidate is found in another module, you can import it in LL | use issue_3907::Foo; | -error: cannot continue compilation due to previous error +error: aborting due to previous error +For more information about this error, try `rustc --explain E0404`. diff --git a/src/test/ui/resolve/issue-5035.stderr b/src/test/ui/resolve/issue-5035.stderr index 6597f05889af8..353a0b1c3d9d0 100644 --- a/src/test/ui/resolve/issue-5035.stderr +++ b/src/test/ui/resolve/issue-5035.stderr @@ -13,5 +13,7 @@ LL | impl K for isize {} //~ ERROR expected trait, found type alias `K` | did you mean `I`? | type aliases cannot be used for traits -error: cannot continue compilation due to previous error +error: aborting due to 2 previous errors +Some errors occurred: E0404, E0432. +For more information about an error, try `rustc --explain E0404`. diff --git a/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr b/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr index 6e7bd28d16fc3..f32c5e9b2c6bd 100644 --- a/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr +++ b/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr @@ -10,5 +10,7 @@ error[E0404]: expected trait, found type alias `Typedef` LL | fn g isize>(x: F) {} | ^^^^^^^^^^^^^^^^^^^^^^^ type aliases cannot be used for traits -error: cannot continue compilation due to previous error +error: aborting due to 2 previous errors +Some errors occurred: E0404, E0405. +For more information about an error, try `rustc --explain E0404`. diff --git a/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs b/src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs similarity index 78% rename from src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs rename to src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs index 93e2561adf753..425f51ca2fb54 100644 --- a/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs +++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs @@ -7,9 +7,7 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(termination_trait)] -fn main() -> char { -//~^ ERROR: the trait bound `char: std::process::Termination` is not satisfied +fn main() -> char { //~ ERROR ' ' } diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr b/src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr new file mode 100644 index 0000000000000..5109d9275c58b --- /dev/null +++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr @@ -0,0 +1,11 @@ +error[E0277]: `main` has invalid return type `char` + --> $DIR/termination-trait-main-wrong-type.rs:11:14 + | +LL | fn main() -> char { //~ ERROR + | ^^^^ `main` can only return types that implement std::process::Termination + | + = help: consider using `()`, or a `Result` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.stderr b/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.stderr index bb55d86f620b7..e69de29bb2d1d 100644 --- a/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.stderr +++ b/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.stderr @@ -1,2 +0,0 @@ -error: cannot continue compilation due to previous error - diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs index 8e03c303e54d7..e8227971691e9 100644 --- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs +++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs @@ -58,7 +58,10 @@ fn test6() { fn test7() { fn foo(_: F) where F: FnMut(Box, isize) {} - let mut f = |g: Box, b: isize| {}; + let s = String::new(); // Capture to make f !Copy + let mut f = move |g: Box, b: isize| { + let _ = s.len(); + }; f(Box::new(|a| { foo(f); //~^ ERROR cannot move `f` into closure because it is borrowed diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr index 318b77dedcba4..2e7e1e0744141 100644 --- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr +++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr @@ -28,7 +28,7 @@ LL | f.f.call_mut(()) | ^^^ cannot borrow as mutable error[E0504]: cannot move `f` into closure because it is borrowed - --> $DIR/borrowck-call-is-borrow-issue-12224.rs:63:13 + --> $DIR/borrowck-call-is-borrow-issue-12224.rs:66:13 | LL | f(Box::new(|a| { | - borrow of `f` occurs here @@ -36,11 +36,11 @@ LL | foo(f); | ^ move into closure occurs here error[E0507]: cannot move out of captured outer variable in an `FnMut` closure - --> $DIR/borrowck-call-is-borrow-issue-12224.rs:63:13 + --> $DIR/borrowck-call-is-borrow-issue-12224.rs:66:13 | -LL | let mut f = |g: Box, b: isize| {}; +LL | let mut f = move |g: Box, b: isize| { | ----- captured outer variable -LL | f(Box::new(|a| { +... LL | foo(f); | ^ cannot move out of captured outer variable in an `FnMut` closure diff --git a/src/test/ui/span/issue-24690.stderr b/src/test/ui/span/issue-24690.stderr index 6a4ec73b27a66..b496a1a76c017 100644 --- a/src/test/ui/span/issue-24690.stderr +++ b/src/test/ui/span/issue-24690.stderr @@ -36,3 +36,5 @@ LL | | println!("{}", theTwo); LL | | } | |_^ +error: aborting due to previous error + diff --git a/src/test/ui/span/issue-35987.stderr b/src/test/ui/span/issue-35987.stderr index 2d4a7cc72f5f6..1dd45bb1e5efe 100644 --- a/src/test/ui/span/issue-35987.stderr +++ b/src/test/ui/span/issue-35987.stderr @@ -8,5 +8,6 @@ help: possible better candidate is found in another module, you can import it in LL | use std::ops::Add; | -error: cannot continue compilation due to previous error +error: aborting due to previous error +For more information about this error, try `rustc --explain E0404`.