diff --git a/.travis.yml b/.travis.yml index b2aba305aedc4..41ea0c9afa87c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -318,8 +318,6 @@ before_deploy: deploy: - provider: s3 - edge: - branch: s3-eager-autoload bucket: rust-lang-ci2 skip_cleanup: true local_dir: deploy @@ -336,8 +334,6 @@ deploy: # this is the same as the above deployment provider except that it uploads to # a slightly different directory and has a different trigger - provider: s3 - edge: - branch: s3-eager-autoload bucket: rust-lang-ci2 skip_cleanup: true local_dir: deploy @@ -355,8 +351,6 @@ deploy: # try branch. Travis does not appear to provide a way to use "or" in these # conditions. - provider: s3 - edge: - branch: s3-eager-autoload bucket: rust-lang-ci2 skip_cleanup: true local_dir: deploy @@ -371,8 +365,6 @@ deploy: condition: $DEPLOY = 1 - provider: s3 - edge: - branch: s3-eager-autoload bucket: rust-lang-ci2 skip_cleanup: true local_dir: deploy diff --git a/RELEASES.md b/RELEASES.md index 64e2145e0f37b..51c36c99858b8 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,103 @@ +Version 1.25.0 (2018-03-29) +========================== + +Language +-------- +- [Stabilised `#[repr(align(x))]`.][47006] [RFC 1358] +- [You can now use nested groups of imports.][47948] + e.g. `use std::{fs::File, io::Read, path::{Path, PathBuf}};` +- [You can now have `|` at the start of a match arm.][47947] e.g. +```rust +enum Foo { A, B, C } + +fn main() { + let x = Foo::A; + match x { + | Foo::A + | Foo::B => println!("AB"), + | Foo::C => println!("C"), + } +} +``` + +Compiler +-------- +- [Upgraded to LLVM 6.][47828] +- [Added `-C lto=val` option.][47521] +- [Added `i586-unknown-linux-musl` target][47282] + +Libraries +--------- +- [Impl Send for `process::Command` on Unix.][47760] +- [Impl PartialEq and Eq for `ParseCharError`.][47790] +- [`UnsafeCell::into_inner` is now safe.][47204] +- [Implement libstd for CloudABI.][47268] +- [`Float::{from_bits, to_bits}` is now available in libcore.][46931] +- [Implement `AsRef` for Component][46985] +- [Implemented `Write` for `Cursor<&mut Vec>`][46830] +- [Moved `Duration` to libcore.][46666] + +Stabilized APIs +--------------- +- [`Location::column`] +- [`ptr::NonNull`] + +The following functions can now be used in a constant expression. +eg. `static MINUTE: Duration = Duration::from_secs(60);` +- [`Duration::new`][47300] +- [`Duration::from_secs`][47300] +- [`Duration::from_millis`][47300] +- [`Duration::from_micros`][47300] +- [`Duration::from_nanos`][47300] + +Cargo +----- +- [`cargo new` no longer removes `rust` or `rs` prefixs/suffixs.][cargo/5013] +- [`cargo new` now defaults to creating a binary crate, instead of a + library crate.][cargo/5029] + +Misc +---- +- [Rust by example is now shipped with new releases][46196] + +Compatibility Notes +------------------- +- [Deprecated `net::lookup_host`.][47510] +- [`rustdoc` has switched to pulldown as the default markdown renderer.][47398] +- The borrow checker was sometimes incorrectly permitting overlapping borrows + around indexing operations (see [#47349][47349]). This has been fixed (which also + enabled some correct code that used to cause errors (e.g. [#33903][33903] and [#46095][46095]). +- [Removed deprecated unstable attribute `#[simd]`.][47251] + +[33903]: https://github.com/rust-lang/rust/pull/33903 +[47947]: https://github.com/rust-lang/rust/pull/47947 +[47948]: https://github.com/rust-lang/rust/pull/47948 +[47760]: https://github.com/rust-lang/rust/pull/47760 +[47790]: https://github.com/rust-lang/rust/pull/47790 +[47828]: https://github.com/rust-lang/rust/pull/47828 +[47398]: https://github.com/rust-lang/rust/pull/47398 +[47510]: https://github.com/rust-lang/rust/pull/47510 +[47521]: https://github.com/rust-lang/rust/pull/47521 +[47204]: https://github.com/rust-lang/rust/pull/47204 +[47251]: https://github.com/rust-lang/rust/pull/47251 +[47268]: https://github.com/rust-lang/rust/pull/47268 +[47282]: https://github.com/rust-lang/rust/pull/47282 +[47300]: https://github.com/rust-lang/rust/pull/47300 +[47349]: https://github.com/rust-lang/rust/pull/47349 +[46931]: https://github.com/rust-lang/rust/pull/46931 +[46985]: https://github.com/rust-lang/rust/pull/46985 +[47006]: https://github.com/rust-lang/rust/pull/47006 +[46830]: https://github.com/rust-lang/rust/pull/46830 +[46095]: https://github.com/rust-lang/rust/pull/46095 +[46666]: https://github.com/rust-lang/rust/pull/46666 +[46196]: https://github.com/rust-lang/rust/pull/46196 +[cargo/5013]: https://github.com/rust-lang/cargo/pull/5013 +[cargo/5029]: https://github.com/rust-lang/cargo/pull/5029 +[RFC 1358]: https://github.com/rust-lang/rfcs/pull/1358 +[`Location::column`]: https://doc.rust-lang.org/std/panic/struct.Location.html#method.column +[`ptr::NonNull`]: https://doc.rust-lang.org/std/ptr/struct.NonNull.html + + Version 1.24.0 (2018-02-15) ========================== diff --git a/src/Cargo.lock b/src/Cargo.lock index 675457905eade..b452e83870a2c 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)", @@ -567,15 +550,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" @@ -774,14 +748,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]] @@ -1053,14 +1025,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" @@ -1319,13 +1283,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)", @@ -1392,18 +1356,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" @@ -1416,11 +1368,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" @@ -1461,7 +1408,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)", @@ -1525,7 +1472,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)", ] @@ -2094,11 +2041,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" @@ -2416,23 +2358,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" @@ -2583,11 +2508,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" @@ -2680,8 +2600,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" @@ -2720,7 +2638,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" @@ -2741,7 +2658,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" @@ -2767,7 +2684,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" @@ -2796,16 +2712,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" @@ -2825,7 +2739,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" @@ -2854,8 +2767,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" @@ -2873,7 +2784,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 675d3dd437eef..07026cbe2650c 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -308,12 +308,14 @@ impl<'a> Builder<'a> { test::UiFullDeps, test::RunPassFullDeps, test::RunFailFullDeps, test::CompileFailFullDeps, test::IncrementalFullDeps, test::Rustdoc, test::Pretty, test::RunPassPretty, test::RunFailPretty, test::RunPassValgrindPretty, - test::RunPassFullDepsPretty, test::RunFailFullDepsPretty, test::RunMake, + test::RunPassFullDepsPretty, test::RunFailFullDepsPretty, test::Crate, test::CrateLibrustc, test::CrateRustdoc, test::Linkcheck, test::Cargotest, test::Cargo, test::Rls, test::ErrorIndex, test::Distcheck, test::Nomicon, test::Reference, test::RustdocBook, test::RustByExample, test::TheBook, test::UnstableBook, - test::Rustfmt, test::Miri, test::Clippy, test::RustdocJS, test::RustdocTheme), + test::Rustfmt, test::Miri, test::Clippy, test::RustdocJS, test::RustdocTheme, + // Run run-make last, since these won't pass without make on Windows + 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, diff --git a/src/ci/init_repo.sh b/src/ci/init_repo.sh index 8ab4276fa3b05..f2664e6d196c7 100755 --- a/src/ci/init_repo.sh +++ b/src/ci/init_repo.sh @@ -17,6 +17,7 @@ ci_dir=$(cd $(dirname $0) && pwd) . "$ci_dir/shared.sh" travis_fold start init_repo +travis_time_start REPO_DIR="$1" CACHE_DIR="$2" @@ -42,54 +43,39 @@ if grep -q RUST_RELEASE_CHANNEL=beta src/ci/run.sh; then git fetch origin --unshallow beta master fi -travis_fold start update_cache -travis_time_start - -# Update the cache (a pristine copy of the rust source master) -retry sh -c "rm -rf $cache_src_dir && mkdir -p $cache_src_dir && \ - git clone --depth 1 https://github.com/rust-lang/rust.git $cache_src_dir" -if [ -d $cache_src_dir/src/llvm ]; then - (cd $cache_src_dir && git rm src/llvm) -fi -if [ -d $cache_src_dir/src/llvm-emscripten ]; then - (cd $cache_src_dir && git rm src/llvm-emscripten) -fi -retry sh -c "cd $cache_src_dir && \ - git submodule deinit -f . && git submodule sync && git submodule update --init" - -travis_fold end update_cache -travis_time_finish +function fetch_submodule { + local module=$1 + local cached="download-${module//\//-}.tar.gz" + retry sh -c "rm -f $cached && \ + curl -sSL -o $cached $2" + mkdir $module + touch "$module/.git" + tar -C $module --strip-components=1 -xf $cached + rm $cached +} -travis_fold start update_submodules -travis_time_start - -# Update the submodules of the repo we're in, using the pristine repo as -# a cache for any object files -# No, `git submodule foreach` won't work: -# http://stackoverflow.com/questions/12641469/list-submodules-in-a-git-repository +included="src/llvm src/llvm-emscripten src/doc/book src/doc/rust-by-example" modules="$(git config --file .gitmodules --get-regexp '\.path$' | cut -d' ' -f2)" -for module in $modules; do - if [ "$module" = src/llvm ] || [ "$module" = src/llvm-emscripten ]; then +modules=($modules) +use_git="" +urls="$(git config --file .gitmodules --get-regexp '\.url$' | cut -d' ' -f2)" +urls=($urls) +for i in ${!modules[@]}; do + module=${modules[$i]} + if [[ " $included " = *" $module "* ]]; then commit="$(git ls-tree HEAD $module | awk '{print $3}')" git rm $module - retry sh -c "rm -f $commit.tar.gz && \ - curl -sSL -O https://github.com/rust-lang/llvm/archive/$commit.tar.gz" - tar -C src/ -xf "$commit.tar.gz" - rm "$commit.tar.gz" - mv "src/llvm-$commit" $module - continue - fi - if [ ! -e "$cache_src_dir/$module/.git" ]; then - echo "WARNING: $module not found in pristine repo" - retry sh -c "git submodule deinit -f $module && \ - git submodule update --init --recursive $module" + url=${urls[$i]} + url=${url/\.git/} + fetch_submodule $module "$url/archive/$commit.tar.gz" & continue + else + use_git="$use_git $module" fi - retry sh -c "git submodule deinit -f $module && \ - git submodule update --init --recursive --reference $cache_src_dir/$module $module" done - -travis_fold end update_submodules -travis_time_finish - +retry sh -c "git submodule deinit -f $use_git && \ + git submodule sync && \ + git submodule update -j 16 --init --recursive $use_git" +wait travis_fold end init_repo +travis_time_finish diff --git a/src/liballoc/tests/slice.rs b/src/liballoc/tests/slice.rs index d9e9d91cea88a..3f679d81f08de 100644 --- a/src/liballoc/tests/slice.rs +++ b/src/liballoc/tests/slice.rs @@ -1351,7 +1351,7 @@ fn test_copy_from_slice_dst_shorter() { const MAX_LEN: usize = 80; static DROP_COUNTS: [AtomicUsize; MAX_LEN] = [ - // FIXME #5244: AtomicUsize is not Copy. + // FIXME(RFC 1109): AtomicUsize is not Copy. AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index d3a83dc795c85..2206910c93f61 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -382,7 +382,7 @@ impl<'a, T: ?Sized, U: ?Sized> AsRef for &'a mut T where T: AsRef } } -// FIXME (#23442): replace the above impls for &/&mut with the following more general one: +// FIXME (#45742): replace the above impls for &/&mut with the following more general one: // // As lifts over Deref // impl AsRef for D where D::Target: AsRef { // fn as_ref(&self) -> &U { @@ -399,7 +399,7 @@ impl<'a, T: ?Sized, U: ?Sized> AsMut for &'a mut T where T: AsMut } } -// FIXME (#23442): replace the above impl for &mut with the following more general one: +// FIXME (#45742): replace the above impl for &mut with the following more general one: // // AsMut lifts over DerefMut // impl AsMut for D where D::Target: AsMut { // fn as_mut(&mut self) -> &mut U { diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index b1b783b47c72b..1e8476d3880c8 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -1872,7 +1872,7 @@ impl Iterator for Peekable { #[inline] fn nth(&mut self, n: usize) -> Option { - // FIXME(#6393): merge these when borrow-checking gets better. + // FIXME(#43234): merge these when borrow-checking gets better. if n == 0 { match self.peeked.take() { Some(v) => v, diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 25827edee7d93..fe5ed5d494224 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -948,6 +948,7 @@ macro_rules! atomic_int { $stable_from:meta, $stable_nand:meta, $s_int_type:expr, $int_ref:expr, + $extra_feature:expr, $int_type:ident $atomic_type:ident $atomic_init:ident) => { /// An integer type which can be safely shared between threads. /// @@ -959,12 +960,7 @@ macro_rules! atomic_int { /// ). For more about the differences between atomic types and /// non-atomic types, please see the [module-level documentation]. /// - /// Please note that examples are shared between atomic variants of - /// primitive integer types, so it's normal that they are all - /// demonstrating [`AtomicIsize`]. - /// /// [module-level documentation]: index.html - /// [`AtomicIsize`]: struct.AtomicIsize.html #[$stable] pub struct $atomic_type { v: UnsafeCell<$int_type>, @@ -1001,395 +997,426 @@ macro_rules! atomic_int { unsafe impl Sync for $atomic_type {} impl $atomic_type { - /// Creates a new atomic integer. - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::AtomicIsize; - /// - /// let atomic_forty_two = AtomicIsize::new(42); - /// ``` - #[inline] - #[$stable] - pub const fn new(v: $int_type) -> Self { - $atomic_type {v: UnsafeCell::new(v)} + doc_comment! { + concat!("Creates a new atomic integer. + +# Examples + +``` +", $extra_feature, "use std::sync::atomic::", stringify!($atomic_type), "; + +let atomic_forty_two = ", stringify!($atomic_type), "::new(42); +```"), + #[inline] + #[$stable] + pub const fn new(v: $int_type) -> Self { + $atomic_type {v: UnsafeCell::new(v)} + } } - /// Returns a mutable reference to the underlying integer. - /// - /// This is safe because the mutable reference guarantees that no other threads are - /// concurrently accessing the atomic data. - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::{AtomicIsize, Ordering}; - /// - /// let mut some_isize = AtomicIsize::new(10); - /// assert_eq!(*some_isize.get_mut(), 10); - /// *some_isize.get_mut() = 5; - /// assert_eq!(some_isize.load(Ordering::SeqCst), 5); - /// ``` - #[inline] - #[$stable_access] - pub fn get_mut(&mut self) -> &mut $int_type { - unsafe { &mut *self.v.get() } + doc_comment! { + concat!("Returns a mutable reference to the underlying integer. + +This is safe because the mutable reference guarantees that no other threads are +concurrently accessing the atomic data. + +# Examples + +``` +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let mut some_var = ", stringify!($atomic_type), "::new(10); +assert_eq!(*some_var.get_mut(), 10); +*some_var.get_mut() = 5; +assert_eq!(some_var.load(Ordering::SeqCst), 5); +```"), + #[inline] + #[$stable_access] + pub fn get_mut(&mut self) -> &mut $int_type { + unsafe { &mut *self.v.get() } + } } - /// Consumes the atomic and returns the contained value. - /// - /// This is safe because passing `self` by value guarantees that no other threads are - /// concurrently accessing the atomic data. - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::AtomicIsize; - /// - /// let some_isize = AtomicIsize::new(5); - /// assert_eq!(some_isize.into_inner(), 5); - /// ``` - #[inline] - #[$stable_access] - pub fn into_inner(self) -> $int_type { - self.v.into_inner() + doc_comment! { + concat!("Consumes the atomic and returns the contained value. + +This is safe because passing `self` by value guarantees that no other threads are +concurrently accessing the atomic data. + +# Examples + +``` +", $extra_feature, "use std::sync::atomic::", stringify!($atomic_type), "; + +let some_var = ", stringify!($atomic_type), "::new(5); +assert_eq!(some_var.into_inner(), 5); +```"), + #[inline] + #[$stable_access] + pub fn into_inner(self) -> $int_type { + self.v.into_inner() + } } - /// Loads a value from the atomic integer. - /// - /// `load` takes an [`Ordering`] argument which describes the memory ordering of this - /// operation. - /// - /// # Panics - /// - /// Panics if `order` is [`Release`] or [`AcqRel`]. - /// - /// [`Ordering`]: enum.Ordering.html - /// [`Release`]: enum.Ordering.html#variant.Release - /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::{AtomicIsize, Ordering}; - /// - /// let some_isize = AtomicIsize::new(5); - /// - /// assert_eq!(some_isize.load(Ordering::Relaxed), 5); - /// ``` - #[inline] - #[$stable] - pub fn load(&self, order: Ordering) -> $int_type { - unsafe { atomic_load(self.v.get(), order) } + doc_comment! { + concat!("Loads a value from the atomic integer. + +`load` takes an [`Ordering`] argument which describes the memory ordering of this operation. + +# Panics + +Panics if `order` is [`Release`] or [`AcqRel`]. + +[`Ordering`]: enum.Ordering.html +[`Release`]: enum.Ordering.html#variant.Release +[`AcqRel`]: enum.Ordering.html#variant.AcqRel + +# Examples + +``` +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let some_var = ", stringify!($atomic_type), "::new(5); + +assert_eq!(some_var.load(Ordering::Relaxed), 5); +```"), + #[inline] + #[$stable] + pub fn load(&self, order: Ordering) -> $int_type { + unsafe { atomic_load(self.v.get(), order) } + } } - /// Stores a value into the atomic integer. - /// - /// `store` takes an [`Ordering`] argument which describes the memory ordering of this - /// operation. - /// - /// [`Ordering`]: enum.Ordering.html - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::{AtomicIsize, Ordering}; - /// - /// let some_isize = AtomicIsize::new(5); - /// - /// some_isize.store(10, Ordering::Relaxed); - /// assert_eq!(some_isize.load(Ordering::Relaxed), 10); - /// ``` - /// - /// # Panics - /// - /// Panics if `order` is [`Acquire`] or [`AcqRel`]. - /// - /// [`Acquire`]: enum.Ordering.html#variant.Acquire - /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel - #[inline] - #[$stable] - pub fn store(&self, val: $int_type, order: Ordering) { - unsafe { atomic_store(self.v.get(), val, order); } + doc_comment! { + concat!("Stores a value into the atomic integer. + +`store` takes an [`Ordering`] argument which describes the memory ordering of this operation. + +[`Ordering`]: enum.Ordering.html + +# Examples + +``` +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let some_var = ", stringify!($atomic_type), "::new(5); + +some_var.store(10, Ordering::Relaxed); +assert_eq!(some_var.load(Ordering::Relaxed), 10); +``` + +# Panics + +Panics if `order` is [`Acquire`] or [`AcqRel`]. + +[`Acquire`]: enum.Ordering.html#variant.Acquire +[`AcqRel`]: enum.Ordering.html#variant.AcqRel"), + #[inline] + #[$stable] + pub fn store(&self, val: $int_type, order: Ordering) { + unsafe { atomic_store(self.v.get(), val, order); } + } } - /// Stores a value into the atomic integer, returning the previous value. - /// - /// `swap` takes an [`Ordering`] argument which describes the memory ordering of this - /// operation. - /// - /// [`Ordering`]: enum.Ordering.html - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::{AtomicIsize, Ordering}; - /// - /// let some_isize = AtomicIsize::new(5); - /// - /// assert_eq!(some_isize.swap(10, Ordering::Relaxed), 5); - /// ``` - #[inline] - #[$stable] - pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type { - unsafe { atomic_swap(self.v.get(), val, order) } + doc_comment! { + concat!("Stores a value into the atomic integer, returning the previous value. + +`swap` takes an [`Ordering`] argument which describes the memory ordering of this operation. + +[`Ordering`]: enum.Ordering.html + +# Examples + +``` +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let some_var = ", stringify!($atomic_type), "::new(5); + +assert_eq!(some_var.swap(10, Ordering::Relaxed), 5); +```"), + #[inline] + #[$stable] + pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type { + unsafe { atomic_swap(self.v.get(), val, order) } + } } - /// Stores a value into the atomic integer if the current value is the same as the - /// `current` value. - /// - /// The return value is always the previous value. If it is equal to `current`, then the - /// value was updated. - /// - /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory - /// ordering of this operation. - /// - /// [`Ordering`]: enum.Ordering.html - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::{AtomicIsize, Ordering}; - /// - /// let some_isize = AtomicIsize::new(5); - /// - /// assert_eq!(some_isize.compare_and_swap(5, 10, Ordering::Relaxed), 5); - /// assert_eq!(some_isize.load(Ordering::Relaxed), 10); - /// - /// assert_eq!(some_isize.compare_and_swap(6, 12, Ordering::Relaxed), 10); - /// assert_eq!(some_isize.load(Ordering::Relaxed), 10); - /// ``` - #[inline] - #[$stable] - pub fn compare_and_swap(&self, - current: $int_type, - new: $int_type, - order: Ordering) -> $int_type { - match self.compare_exchange(current, - new, - order, - strongest_failure_ordering(order)) { - Ok(x) => x, - Err(x) => x, + doc_comment! { + concat!("Stores a value into the atomic integer if the current value is the same as +the `current` value. + +The return value is always the previous value. If it is equal to `current`, then the +value was updated. + +`compare_and_swap` also takes an [`Ordering`] argument which describes the memory +ordering of this operation. + +[`Ordering`]: enum.Ordering.html + +# Examples + +``` +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let some_var = ", stringify!($atomic_type), "::new(5); + +assert_eq!(some_var.compare_and_swap(5, 10, Ordering::Relaxed), 5); +assert_eq!(some_var.load(Ordering::Relaxed), 10); + +assert_eq!(some_var.compare_and_swap(6, 12, Ordering::Relaxed), 10); +assert_eq!(some_var.load(Ordering::Relaxed), 10); +```"), + #[inline] + #[$stable] + pub fn compare_and_swap(&self, + current: $int_type, + new: $int_type, + order: Ordering) -> $int_type { + match self.compare_exchange(current, + new, + order, + strongest_failure_ordering(order)) { + Ok(x) => x, + Err(x) => x, + } } } - /// Stores a value into the atomic integer if the current value is the same as the - /// `current` value. - /// - /// The return value is a result indicating whether the new value was written and - /// containing the previous value. On success this value is guaranteed to be equal to - /// `current`. - /// - /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory - /// ordering of this operation. The first describes the required ordering if - /// the operation succeeds while the second describes the required ordering when - /// the operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and - /// must be equivalent or weaker than the success ordering. - /// - /// [`Ordering`]: enum.Ordering.html - /// [`Release`]: enum.Ordering.html#variant.Release - /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::{AtomicIsize, Ordering}; - /// - /// let some_isize = AtomicIsize::new(5); - /// - /// assert_eq!(some_isize.compare_exchange(5, 10, - /// Ordering::Acquire, - /// Ordering::Relaxed), - /// Ok(5)); - /// assert_eq!(some_isize.load(Ordering::Relaxed), 10); - /// - /// assert_eq!(some_isize.compare_exchange(6, 12, - /// Ordering::SeqCst, - /// Ordering::Acquire), - /// Err(10)); - /// assert_eq!(some_isize.load(Ordering::Relaxed), 10); - /// ``` - #[inline] - #[$stable_cxchg] - pub fn compare_exchange(&self, - current: $int_type, - new: $int_type, - success: Ordering, - failure: Ordering) -> Result<$int_type, $int_type> { - unsafe { atomic_compare_exchange(self.v.get(), current, new, success, failure) } + doc_comment! { + concat!("Stores a value into the atomic integer if the current value is the same as +the `current` value. + +The return value is a result indicating whether the new value was written and +containing the previous value. On success this value is guaranteed to be equal to +`current`. + +`compare_exchange` takes two [`Ordering`] arguments to describe the memory +ordering of this operation. The first describes the required ordering if +the operation succeeds while the second describes the required ordering when +the operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and +must be equivalent or weaker than the success ordering. + +[`Ordering`]: enum.Ordering.html +[`Release`]: enum.Ordering.html#variant.Release +[`AcqRel`]: enum.Ordering.html#variant.AcqRel + +# Examples + +``` +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let some_var = ", stringify!($atomic_type), "::new(5); + +assert_eq!(some_var.compare_exchange(5, 10, + Ordering::Acquire, + Ordering::Relaxed), + Ok(5)); +assert_eq!(some_var.load(Ordering::Relaxed), 10); + +assert_eq!(some_var.compare_exchange(6, 12, + Ordering::SeqCst, + Ordering::Acquire), + Err(10)); +assert_eq!(some_var.load(Ordering::Relaxed), 10); +```"), + #[inline] + #[$stable_cxchg] + pub fn compare_exchange(&self, + current: $int_type, + new: $int_type, + success: Ordering, + failure: Ordering) -> Result<$int_type, $int_type> { + unsafe { atomic_compare_exchange(self.v.get(), current, new, success, failure) } + } } - /// Stores a value into the atomic integer if the current value is the same as the - /// `current` value. - /// - /// Unlike [`compare_exchange`], this function is allowed to spuriously fail even - /// when the comparison succeeds, which can result in more efficient code on some - /// platforms. The return value is a result indicating whether the new value was - /// written and containing the previous value. - /// - /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory - /// ordering of this operation. The first describes the required ordering if the - /// operation succeeds while the second describes the required ordering when the - /// operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and - /// must be equivalent or weaker than the success ordering. - /// - /// [`compare_exchange`]: #method.compare_exchange - /// [`Ordering`]: enum.Ordering.html - /// [`Release`]: enum.Ordering.html#variant.Release - /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::{AtomicIsize, Ordering}; - /// - /// let val = AtomicIsize::new(4); - /// - /// let mut old = val.load(Ordering::Relaxed); - /// loop { - /// let new = old * 2; - /// match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) { - /// Ok(_) => break, - /// Err(x) => old = x, - /// } - /// } - /// ``` - #[inline] - #[$stable_cxchg] - pub fn compare_exchange_weak(&self, - current: $int_type, - new: $int_type, - success: Ordering, - failure: Ordering) -> Result<$int_type, $int_type> { - unsafe { - atomic_compare_exchange_weak(self.v.get(), current, new, success, failure) + doc_comment! { + concat!("Stores a value into the atomic integer if the current value is the same as +the `current` value. + +Unlike [`compare_exchange`], this function is allowed to spuriously fail even +when the comparison succeeds, which can result in more efficient code on some +platforms. The return value is a result indicating whether the new value was +written and containing the previous value. + +`compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory +ordering of this operation. The first describes the required ordering if the +operation succeeds while the second describes the required ordering when the +operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and +must be equivalent or weaker than the success ordering. + +[`compare_exchange`]: #method.compare_exchange +[`Ordering`]: enum.Ordering.html +[`Release`]: enum.Ordering.html#variant.Release +[`AcqRel`]: enum.Ordering.html#variant.AcqRel + +# Examples + +``` +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let val = ", stringify!($atomic_type), "::new(4); + +let mut old = val.load(Ordering::Relaxed); +loop { + let new = old * 2; + match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) { + Ok(_) => break, + Err(x) => old = x, + } +} +```"), + #[inline] + #[$stable_cxchg] + pub fn compare_exchange_weak(&self, + current: $int_type, + new: $int_type, + success: Ordering, + failure: Ordering) -> Result<$int_type, $int_type> { + unsafe { + atomic_compare_exchange_weak(self.v.get(), current, new, success, failure) + } } } - /// Adds to the current value, returning the previous value. - /// - /// This operation wraps around on overflow. - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::{AtomicIsize, Ordering}; - /// - /// let foo = AtomicIsize::new(0); - /// assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0); - /// assert_eq!(foo.load(Ordering::SeqCst), 10); - /// ``` - #[inline] - #[$stable] - pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type { - unsafe { atomic_add(self.v.get(), val, order) } + doc_comment! { + concat!("Adds to the current value, returning the previous value. + +This operation wraps around on overflow. + +# Examples + +``` +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let foo = ", stringify!($atomic_type), "::new(0); +assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0); +assert_eq!(foo.load(Ordering::SeqCst), 10); +```"), + #[inline] + #[$stable] + pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type { + unsafe { atomic_add(self.v.get(), val, order) } + } } - /// Subtracts from the current value, returning the previous value. - /// - /// This operation wraps around on overflow. - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::{AtomicIsize, Ordering}; - /// - /// let foo = AtomicIsize::new(0); - /// assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 0); - /// assert_eq!(foo.load(Ordering::SeqCst), -10); - /// ``` - #[inline] - #[$stable] - pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type { - unsafe { atomic_sub(self.v.get(), val, order) } + doc_comment! { + concat!("Subtracts from the current value, returning the previous value. + +This operation wraps around on overflow. + +# Examples + +``` +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let foo = ", stringify!($atomic_type), "::new(20); +assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 20); +assert_eq!(foo.load(Ordering::SeqCst), 10); +```"), + #[inline] + #[$stable] + pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type { + unsafe { atomic_sub(self.v.get(), val, order) } + } } - /// Bitwise "and" with the current value. - /// - /// Performs a bitwise "and" operation on the current value and the argument `val`, and - /// sets the new value to the result. - /// - /// Returns the previous value. - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::{AtomicIsize, Ordering}; - /// - /// let foo = AtomicIsize::new(0b101101); - /// assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101); - /// assert_eq!(foo.load(Ordering::SeqCst), 0b100001); - #[inline] - #[$stable] - pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type { - unsafe { atomic_and(self.v.get(), val, order) } + doc_comment! { + concat!("Bitwise \"and\" with the current value. + +Performs a bitwise \"and\" operation on the current value and the argument `val`, and +sets the new value to the result. + +Returns the previous value. + +# Examples + +``` +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let foo = ", stringify!($atomic_type), "::new(0b101101); +assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101); +assert_eq!(foo.load(Ordering::SeqCst), 0b100001); +```"), + #[inline] + #[$stable] + pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type { + unsafe { atomic_and(self.v.get(), val, order) } + } } - /// Bitwise "nand" with the current value. - /// - /// Performs a bitwise "nand" operation on the current value and the argument `val`, and - /// sets the new value to the result. - /// - /// Returns the previous value. - /// - /// # Examples - /// - /// ``` - /// #![feature(atomic_nand)] - /// - /// use std::sync::atomic::{AtomicIsize, Ordering}; - /// - /// let foo = AtomicIsize::new(0xf731); - /// assert_eq!(foo.fetch_nand(0x137f, Ordering::SeqCst), 0xf731); - /// assert_eq!(foo.load(Ordering::SeqCst), !(0xf731 & 0x137f)); - #[inline] - #[$stable_nand] - pub fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type { - unsafe { atomic_nand(self.v.get(), val, order) } + doc_comment! { + concat!("Bitwise \"nand\" with the current value. + +Performs a bitwise \"nand\" operation on the current value and the argument `val`, and +sets the new value to the result. + +Returns the previous value. + +# Examples + +``` +", $extra_feature, "#![feature(atomic_nand)] + +use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let foo = ", stringify!($atomic_type), "::new(0x13); +assert_eq!(foo.fetch_nand(0x31, Ordering::SeqCst), 0x13); +assert_eq!(foo.load(Ordering::SeqCst), !(0x13 & 0x31)); +```"), + #[inline] + #[$stable_nand] + pub fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type { + unsafe { atomic_nand(self.v.get(), val, order) } + } } - /// Bitwise "or" with the current value. - /// - /// Performs a bitwise "or" operation on the current value and the argument `val`, and - /// sets the new value to the result. - /// - /// Returns the previous value. - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::{AtomicIsize, Ordering}; - /// - /// let foo = AtomicIsize::new(0b101101); - /// assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101); - /// assert_eq!(foo.load(Ordering::SeqCst), 0b111111); - #[inline] - #[$stable] - pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type { - unsafe { atomic_or(self.v.get(), val, order) } + doc_comment! { + concat!("Bitwise \"or\" with the current value. + +Performs a bitwise \"or\" operation on the current value and the argument `val`, and +sets the new value to the result. + +Returns the previous value. + +# Examples + +``` +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let foo = ", stringify!($atomic_type), "::new(0b101101); +assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101); +assert_eq!(foo.load(Ordering::SeqCst), 0b111111); +```"), + #[inline] + #[$stable] + pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type { + unsafe { atomic_or(self.v.get(), val, order) } + } } - /// Bitwise "xor" with the current value. - /// - /// Performs a bitwise "xor" operation on the current value and the argument `val`, and - /// sets the new value to the result. - /// - /// Returns the previous value. - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::{AtomicIsize, Ordering}; - /// - /// let foo = AtomicIsize::new(0b101101); - /// assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101); - /// assert_eq!(foo.load(Ordering::SeqCst), 0b011110); - #[inline] - #[$stable] - pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type { - unsafe { atomic_xor(self.v.get(), val, order) } + doc_comment! { + concat!("Bitwise \"xor\" with the current value. + +Performs a bitwise \"xor\" operation on the current value and the argument `val`, and +sets the new value to the result. + +Returns the previous value. + +# Examples + +``` +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let foo = ", stringify!($atomic_type), "::new(0b101101); +assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101); +assert_eq!(foo.load(Ordering::SeqCst), 0b011110); +```"), + #[inline] + #[$stable] + pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type { + unsafe { atomic_xor(self.v.get(), val, order) } + } } } } @@ -1404,6 +1431,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "atomic_nand", issue = "13226"), "i8", "../../../std/primitive.i8.html", + "#![feature(integer_atomics)]\n\n", i8 AtomicI8 ATOMIC_I8_INIT } #[cfg(target_has_atomic = "8")] @@ -1415,6 +1443,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "atomic_nand", issue = "13226"), "u8", "../../../std/primitive.u8.html", + "#![feature(integer_atomics)]\n\n", u8 AtomicU8 ATOMIC_U8_INIT } #[cfg(target_has_atomic = "16")] @@ -1426,6 +1455,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "atomic_nand", issue = "13226"), "i16", "../../../std/primitive.i16.html", + "#![feature(integer_atomics)]\n\n", i16 AtomicI16 ATOMIC_I16_INIT } #[cfg(target_has_atomic = "16")] @@ -1437,6 +1467,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "atomic_nand", issue = "13226"), "u16", "../../../std/primitive.u16.html", + "#![feature(integer_atomics)]\n\n", u16 AtomicU16 ATOMIC_U16_INIT } #[cfg(target_has_atomic = "32")] @@ -1448,6 +1479,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "atomic_nand", issue = "13226"), "i32", "../../../std/primitive.i32.html", + "#![feature(integer_atomics)]\n\n", i32 AtomicI32 ATOMIC_I32_INIT } #[cfg(target_has_atomic = "32")] @@ -1459,6 +1491,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "atomic_nand", issue = "13226"), "u32", "../../../std/primitive.u32.html", + "#![feature(integer_atomics)]\n\n", u32 AtomicU32 ATOMIC_U32_INIT } #[cfg(target_has_atomic = "64")] @@ -1470,6 +1503,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "atomic_nand", issue = "13226"), "i64", "../../../std/primitive.i64.html", + "#![feature(integer_atomics)]\n\n", i64 AtomicI64 ATOMIC_I64_INIT } #[cfg(target_has_atomic = "64")] @@ -1481,6 +1515,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "atomic_nand", issue = "13226"), "u64", "../../../std/primitive.u64.html", + "#![feature(integer_atomics)]\n\n", u64 AtomicU64 ATOMIC_U64_INIT } #[cfg(target_has_atomic = "ptr")] @@ -1492,6 +1527,7 @@ atomic_int!{ stable(feature = "atomic_from", since = "1.23.0"), unstable(feature = "atomic_nand", issue = "13226"), "isize", "../../../std/primitive.isize.html", + "", isize AtomicIsize ATOMIC_ISIZE_INIT } #[cfg(target_has_atomic = "ptr")] @@ -1503,6 +1539,7 @@ atomic_int!{ stable(feature = "atomic_from", since = "1.23.0"), unstable(feature = "atomic_nand", issue = "13226"), "usize", "../../../std/primitive.usize.html", + "", usize AtomicUsize ATOMIC_USIZE_INIT } diff --git a/src/libcore/tests/ascii.rs b/src/libcore/tests/ascii.rs index 4d43067ad2cf3..950222dbcfa3f 100644 --- a/src/libcore/tests/ascii.rs +++ b/src/libcore/tests/ascii.rs @@ -9,7 +9,6 @@ // except according to those terms. use core::char::from_u32; -use std::ascii::AsciiExt; #[test] fn test_is_ascii() { @@ -143,8 +142,6 @@ macro_rules! assert_all { stringify!($what), b); } } - assert!($str.$what()); - assert!($str.as_bytes().$what()); )+ }}; ($what:ident, $($str:tt),+,) => (assert_all!($what,$($str),+)) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 744e3a5eaabcc..1e2e4e5a69fa1 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -579,6 +579,9 @@ define_dep_nodes!( <'tcx> [] GetPanicStrategy(CrateNum), [] IsNoBuiltins(CrateNum), [] ImplDefaultness(DefId), + [] CheckItemWellFormed(DefId), + [] CheckTraitItemWellFormed(DefId), + [] CheckImplItemWellFormed(DefId), [] ReachableNonGenerics(CrateNum), [] NativeLibraries(CrateNum), [] PluginRegistrarFn(CrateNum), diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 0ad79eacd2b03..d60c22064d3a0 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -476,10 +476,8 @@ impl DepGraph { fingerprints.resize(current_dep_graph.nodes.len(), Fingerprint::ZERO); } - let nodes: IndexVec<_, (DepNode, Fingerprint)> = - current_dep_graph.nodes.iter_enumerated().map(|(idx, &dep_node)| { - (dep_node, fingerprints[idx]) - }).collect(); + let fingerprints = fingerprints.clone().convert_index_type(); + let nodes = current_dep_graph.nodes.clone().convert_index_type(); let total_edge_count: usize = current_dep_graph.edges.iter() .map(|v| v.len()) @@ -503,6 +501,7 @@ impl DepGraph { SerializedDepGraph { nodes, + fingerprints, edge_list_indices, edge_list_data, } diff --git a/src/librustc/dep_graph/prev.rs b/src/librustc/dep_graph/prev.rs index 504b60e763e23..669a99019aa60 100644 --- a/src/librustc/dep_graph/prev.rs +++ b/src/librustc/dep_graph/prev.rs @@ -23,7 +23,7 @@ impl PreviousDepGraph { pub fn new(data: SerializedDepGraph) -> PreviousDepGraph { let index: FxHashMap<_, _> = data.nodes .iter_enumerated() - .map(|(idx, &(dep_node, _))| (dep_node, idx)) + .map(|(idx, &dep_node)| (dep_node, idx)) .collect(); PreviousDepGraph { data, index } } @@ -41,7 +41,7 @@ impl PreviousDepGraph { #[inline] pub fn index_to_node(&self, dep_node_index: SerializedDepNodeIndex) -> DepNode { - self.data.nodes[dep_node_index].0 + self.data.nodes[dep_node_index] } #[inline] @@ -58,14 +58,14 @@ impl PreviousDepGraph { pub fn fingerprint_of(&self, dep_node: &DepNode) -> Option { self.index .get(dep_node) - .map(|&node_index| self.data.nodes[node_index].1) + .map(|&node_index| self.data.fingerprints[node_index]) } #[inline] pub fn fingerprint_by_index(&self, dep_node_index: SerializedDepNodeIndex) -> Fingerprint { - self.data.nodes[dep_node_index].1 + self.data.fingerprints[dep_node_index] } pub fn node_count(&self) -> usize { diff --git a/src/librustc/dep_graph/serialized.rs b/src/librustc/dep_graph/serialized.rs index c96040ab9b6e3..60fc813a25d51 100644 --- a/src/librustc/dep_graph/serialized.rs +++ b/src/librustc/dep_graph/serialized.rs @@ -20,7 +20,10 @@ newtype_index!(SerializedDepNodeIndex); #[derive(Debug, RustcEncodable, RustcDecodable)] pub struct SerializedDepGraph { /// The set of all DepNodes in the graph - pub nodes: IndexVec, + pub nodes: IndexVec, + /// The set of all Fingerprints in the graph. Each Fingerprint corresponds to + /// the DepNode at the same index in the nodes vector. + pub fingerprints: IndexVec, /// For each DepNode, stores the list of edges originating from that /// DepNode. Encoded as a [start, end) pair indexing into edge_list_data, /// which holds the actual DepNodeIndices of the target nodes. @@ -35,6 +38,7 @@ impl SerializedDepGraph { pub fn new() -> SerializedDepGraph { SerializedDepGraph { nodes: IndexVec::new(), + fingerprints: IndexVec::new(), edge_list_indices: IndexVec::new(), edge_list_data: Vec::new(), } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 0d91074e946bd..7e5ff632a4a6b 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1064,6 +1064,8 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, 2 = full debug info with variable and type information"), opt_level: Option = (None, parse_opt_string, [TRACKED], "optimize with possible levels 0-3, s, or z"), + force_frame_pointers: Option = (None, parse_opt_bool, [TRACKED], + "force use of the frame pointers"), debug_assertions: Option = (None, parse_opt_bool, [TRACKED], "explicitly enable the cfg(debug_assertions) directive"), inline_threshold: Option = (None, parse_opt_uint, [TRACKED], @@ -2892,6 +2894,10 @@ mod tests { opts.cg.debuginfo = Some(0xba5eba11); assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + opts = reference.clone(); + opts.cg.force_frame_pointers = Some(false); + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + opts = reference.clone(); opts.cg.debug_assertions = Some(true); assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 3f52ecfc0999b..1cfb5700b715d 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -20,7 +20,7 @@ use lint::builtin::BuiltinLintDiagnostics; use middle::allocator::AllocatorKind; use middle::dependency_format; use session::search_paths::PathKind; -use session::config::{DebugInfoLevel, OutputType}; +use session::config::{OutputType}; use ty::tls; use util::nodemap::{FxHashMap, FxHashSet}; use util::common::{duration_to_secs_str, ErrorReported}; @@ -676,8 +676,11 @@ impl Session { } pub fn must_not_eliminate_frame_pointers(&self) -> bool { - self.opts.debuginfo != DebugInfoLevel::NoDebugInfo - || !self.target.target.options.eliminate_frame_pointer + if let Some(x) = self.opts.cg.force_frame_pointers { + x + } else { + !self.target.target.options.eliminate_frame_pointer + } } /// Returns the symbol name for the registrar function, diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index b6b7361bb2f72..6c3b4efb932ad 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -299,6 +299,10 @@ define_maps! { <'tcx> [] fn impl_defaultness: ImplDefaultness(DefId) -> hir::Defaultness, + [] fn check_item_well_formed: CheckItemWellFormed(DefId) -> (), + [] fn check_trait_item_well_formed: CheckTraitItemWellFormed(DefId) -> (), + [] fn check_impl_item_well_formed: CheckImplItemWellFormed(DefId) -> (), + // The DefIds of all non-generic functions and statics in the given crate // that can be reached from outside the crate. // diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index c514679042527..4170fa7679716 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -871,6 +871,9 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::GetPanicStrategy => { force!(panic_strategy, krate!()); } DepKind::IsNoBuiltins => { force!(is_no_builtins, krate!()); } DepKind::ImplDefaultness => { force!(impl_defaultness, def_id!()); } + DepKind::CheckItemWellFormed => { force!(check_item_well_formed, def_id!()); } + DepKind::CheckTraitItemWellFormed => { force!(check_trait_item_well_formed, def_id!()); } + DepKind::CheckImplItemWellFormed => { force!(check_impl_item_well_formed, def_id!()); } DepKind::ReachableNonGenerics => { force!(reachable_non_generics, krate!()); } DepKind::NativeLibraries => { force!(native_libraries, krate!()); } DepKind::PluginRegistrarFn => { force!(plugin_registrar_fn, krate!()); } diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs index a5b1a7e57ab46..cbb3ff5171592 100644 --- a/src/librustc_data_structures/indexed_vec.rs +++ b/src/librustc_data_structures/indexed_vec.rs @@ -503,6 +503,13 @@ impl IndexVec { (c1, c2) } } + + pub fn convert_index_type(self) -> IndexVec { + IndexVec { + raw: self.raw, + _marker: PhantomData, + } + } } impl IndexVec { diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs index ca1e3563089db..a5bc1106ba0b0 100644 --- a/src/librustc_incremental/persist/save.rs +++ b/src/librustc_incremental/persist/save.rs @@ -162,7 +162,7 @@ fn encode_dep_graph(tcx: TyCtxt, let mut counts: FxHashMap<_, Stat> = FxHashMap(); - for (i, &(node, _)) in serialized_graph.nodes.iter_enumerated() { + for (i, &node) in serialized_graph.nodes.iter_enumerated() { let stat = counts.entry(node.kind).or_insert(Stat { kind: node.kind, node_counter: 0, diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs index ef30b1e452230..7281fb5966388 100644 --- a/src/librustc_mir/build/block.rs +++ b/src/librustc_mir/build/block.rs @@ -117,10 +117,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // Evaluate the initializer, if present. if let Some(init) = initializer { unpack!(block = this.in_opt_scope( - opt_destruction_scope.map(|de|(de, source_info)), block, move |this| { + opt_destruction_scope.map(|de|(de, source_info)), block, |this| { let scope = (init_scope, source_info); - this.in_scope(scope, lint_level, block, move |this| { - // FIXME #30046 ^~~~ + this.in_scope(scope, lint_level, block, |this| { this.expr_into_pattern(block, pattern, init) }) })); diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs index 82eb28287b033..47f6f61072e13 100644 --- a/src/librustc_mir/interpret/const_eval.rs +++ b/src/librustc_mir/interpret/const_eval.rs @@ -339,6 +339,14 @@ impl<'mir, 'tcx> super::Machine<'mir, 'tcx> for CompileTimeEvaluator { ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, cid: GlobalId<'tcx>, ) -> EvalResult<'tcx, AllocId> { + let alloc = ecx + .tcx + .interpret_interner + .get_cached(cid.instance.def_id()); + // Don't evaluate when already cached to prevent cycles + if let Some(alloc) = alloc { + return Ok(alloc) + } // ensure the static is computed ecx.const_eval(cid)?; Ok(ecx diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index d27de3ef6bfc4..456f5fd75db09 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -197,29 +197,17 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { }, Static(ref static_) => { - let alloc = self - .tcx - .interpret_interner - .get_cached(static_.def_id); let layout = self.layout_of(self.place_ty(mir_place))?; - if let Some(alloc) = alloc { - Place::Ptr { - ptr: MemoryPointer::new(alloc, 0).into(), - align: layout.align, - extra: PlaceExtra::None, - } - } else { - let instance = ty::Instance::mono(*self.tcx, static_.def_id); - let cid = GlobalId { - instance, - promoted: None - }; - let alloc = Machine::init_static(self, cid)?; - Place::Ptr { - ptr: MemoryPointer::new(alloc, 0).into(), - align: layout.align, - extra: PlaceExtra::None, - } + let instance = ty::Instance::mono(*self.tcx, static_.def_id); + let cid = GlobalId { + instance, + promoted: None + }; + let alloc = Machine::init_static(self, cid)?; + Place::Ptr { + ptr: MemoryPointer::new(alloc, 0).into(), + align: layout.align, + extra: PlaceExtra::None, } } diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index e95126c8a1a0f..19f33ef5d45a8 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -177,7 +177,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> }); } DropStyle::Conditional => { - let unwind = self.unwind; // FIXME(#6393) + let unwind = self.unwind; // FIXME(#43234) let succ = self.succ; let drop_bb = self.complete_drop(Some(DropFlagMode::Deep), succ, unwind); self.elaborator.patch().patch_terminator(bb, TerminatorKind::Goto { @@ -268,7 +268,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> // Clear the "master" drop flag at the end. This is needed // because the "master" drop protects the ADT's discriminant, // which is invalidated after the ADT is dropped. - let (succ, unwind) = (self.succ, self.unwind); // FIXME(#6393) + let (succ, unwind) = (self.succ, self.unwind); // FIXME(#43234) ( self.drop_flag_reset_block(DropFlagMode::Shallow, succ, unwind), unwind.map(|unwind| { @@ -344,7 +344,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> let interior = self.place.clone().deref(); let interior_path = self.elaborator.deref_subpath(self.path); - let succ = self.succ; // FIXME(#6393) + let succ = self.succ; // FIXME(#43234) let unwind = self.unwind; let succ = self.box_free_block(ty, succ, unwind); let unwind_succ = self.unwind.map(|unwind| { @@ -717,7 +717,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> ptr_based) }); - let succ = self.succ; // FIXME(#6393) + let succ = self.succ; // FIXME(#43234) let loop_block = self.drop_loop( succ, cur, @@ -798,7 +798,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> self.open_drop_for_adt(def, substs) } ty::TyDynamic(..) => { - let unwind = self.unwind; // FIXME(#6393) + let unwind = self.unwind; // FIXME(#43234) let succ = self.succ; self.complete_drop(Some(DropFlagMode::Deep), succ, unwind) } @@ -849,7 +849,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> fn elaborated_drop_block<'a>(&mut self) -> BasicBlock { debug!("elaborated_drop_block({:?})", self); - let unwind = self.unwind; // FIXME(#6393) + let unwind = self.unwind; // FIXME(#43234) let succ = self.succ; let blk = self.drop_block(succ, unwind); self.elaborate_drop(blk); @@ -882,7 +882,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> args: vec![Operand::Move(self.place.clone())], destination: Some((unit_temp, target)), cleanup: None - }; // FIXME(#6393) + }; // FIXME(#43234) let free_block = self.new_block(unwind, call); let block_start = Location { block: free_block, statement_index: 0 }; diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 4cbebdc3c1c39..644a2ffe3c379 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -1025,28 +1025,9 @@ fn import_path_to_string(names: &[SpannedIdent], if names.is_empty() { import_directive_subclass_to_string(subclass) } else { - // FIXME: Remove this entire logic after #48116 is fixed. - // - // Note that this code looks a little wonky, it's currently here to - // hopefully help debug #48116, but otherwise isn't intended to - // cause any problems. - let x = format!( - "{}::{}", - names_to_string(names), - import_directive_subclass_to_string(subclass), - ); - if names.is_empty() || x.starts_with("::") { - span_bug!( - span, - "invalid name `{}` at {:?}; global = {}, names = {:?}, subclass = {:?}", - x, - span, - global, - names, - subclass - ); - } - return x + format!("{}::{}", + names_to_string(names), + import_directive_subclass_to_string(subclass)) } } } diff --git a/src/librustc_traits/lowering.rs b/src/librustc_traits/lowering.rs index c9666f55d440e..1092e826a35f9 100644 --- a/src/librustc_traits/lowering.rs +++ b/src/librustc_traits/lowering.rs @@ -12,6 +12,7 @@ use rustc::hir::{self, ImplPolarity}; use rustc::hir::def_id::DefId; use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc::ty::{self, TyCtxt}; +use rustc::ty::subst::Substs; use rustc::traits::{QuantifierKind, Goal, DomainGoal, Clause, WhereClauseAtom}; use syntax::ast; use rustc_data_structures::sync::Lrc; @@ -104,6 +105,7 @@ crate fn program_clauses_for<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefI let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); let item = tcx.hir.expect_item(node_id); match item.node { + hir::ItemTrait(..) => program_clauses_for_trait(tcx, def_id), hir::ItemImpl(..) => program_clauses_for_impl(tcx, def_id), // FIXME: other constructions e.g. traits, associated types... @@ -111,6 +113,36 @@ crate fn program_clauses_for<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefI } } +fn program_clauses_for_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) + -> Lrc>> +{ + // Rule Implemented-From-Env (see rustc guide) + // + // `trait Trait where WC { .. } // P0 == Self` + // + // ``` + // forall { + // Implemented(Self: Trait) :- FromEnv(Self: Trait) + // } + // ``` + + // `Self: Trait` + let trait_pred = ty::TraitPredicate { + trait_ref: ty::TraitRef { + def_id, + substs: Substs::identity_for_item(tcx, def_id) + } + }; + // `FromEnv(Self: Trait)` + let from_env = Goal::DomainGoal(DomainGoal::FromEnv(trait_pred.lower())); + // `Implemented(Self: Trait)` + let impl_trait = DomainGoal::Holds(WhereClauseAtom::Implemented(trait_pred)); + + // `Implemented(Self: Trait) :- FromEnv(Self: Trait)` + let clause = Clause::Implies(vec![from_env], impl_trait); + Lrc::new(vec![clause]) +} + fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Lrc>> { @@ -118,15 +150,24 @@ fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId return Lrc::new(vec![]); } - // Rule Implemented-From-Impl + // Rule Implemented-From-Impl (see rustc guide) + // + // `impl Trait for A0 where WC { .. }` // - // (see rustc guide) + // ``` + // forall { + // Implemented(A0: Trait) :- WC + // } + // ``` let trait_ref = tcx.impl_trait_ref(def_id).unwrap(); - let trait_ref = ty::TraitPredicate { trait_ref }.lower(); + // `Implemented(A0: Trait)` + let trait_pred = ty::TraitPredicate { trait_ref }.lower(); + // `WC` let where_clauses = tcx.predicates_of(def_id).predicates.lower(); - let clause = Clause::Implies(where_clauses, trait_ref); + // `Implemented(A0: Trait) :- WC` + let clause = Clause::Implies(where_clauses, trait_pred); Lrc::new(vec![clause]) } diff --git a/src/librustc_trans/attributes.rs b/src/librustc_trans/attributes.rs index d5ec8d1b55262..d57e5040045cd 100644 --- a/src/librustc_trans/attributes.rs +++ b/src/librustc_trans/attributes.rs @@ -65,8 +65,6 @@ pub fn naked(val: ValueRef, is_naked: bool) { } pub fn set_frame_pointer_elimination(cx: &CodegenCx, llfn: ValueRef) { - // FIXME: #11906: Omitting frame pointers breaks retrieving the value of a - // parameter. if cx.sess().must_not_eliminate_frame_pointers() { llvm::AddFunctionAttrStringValue( llfn, llvm::AttributePlace::Function, diff --git a/src/librustc_trans/builder.rs b/src/librustc_trans/builder.rs index 3f5a9a54ff1ea..91eabb9998f4a 100644 --- a/src/librustc_trans/builder.rs +++ b/src/librustc_trans/builder.rs @@ -1036,7 +1036,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub fn vector_reduce_fmin(&self, src: ValueRef) -> ValueRef { self.count_insn("vector.reduce.fmin"); unsafe { - let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, true); + let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ false); if instr.is_null() { bug!("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0"); } @@ -1046,7 +1046,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub fn vector_reduce_fmax(&self, src: ValueRef) -> ValueRef { self.count_insn("vector.reduce.fmax"); unsafe { - let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, true); + let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ false); if instr.is_null() { bug!("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0"); } @@ -1056,7 +1056,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub fn vector_reduce_fmin_fast(&self, src: ValueRef) -> ValueRef { self.count_insn("vector.reduce.fmin_fast"); unsafe { - let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, false); + let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ true); if instr.is_null() { bug!("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0"); } @@ -1067,7 +1067,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub fn vector_reduce_fmax_fast(&self, src: ValueRef) -> ValueRef { self.count_insn("vector.reduce.fmax_fast"); unsafe { - let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, false); + let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ true); if instr.is_null() { bug!("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0"); } diff --git a/src/librustc_trans_utils/symbol_names_test.rs b/src/librustc_trans_utils/symbol_names_test.rs index 267c8d2bd03c8..47bbd67fb5c70 100644 --- a/src/librustc_trans_utils/symbol_names_test.rs +++ b/src/librustc_trans_utils/symbol_names_test.rs @@ -15,7 +15,6 @@ //! paths etc in all kinds of annoying scenarios. use rustc::hir; -use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::ty::TyCtxt; use syntax::ast; @@ -34,8 +33,7 @@ pub fn report_symbol_names<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { tcx.dep_graph.with_ignore(|| { let mut visitor = SymbolNamesTest { tcx: tcx }; - // FIXME(#37712) could use ItemLikeVisitor if trait items were item-like - tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor()); + tcx.hir.krate().visit_all_item_likes(&mut visitor); }) } @@ -66,23 +64,16 @@ impl<'a, 'tcx> SymbolNamesTest<'a, 'tcx> { } } -impl<'a, 'tcx> Visitor<'tcx> for SymbolNamesTest<'a, 'tcx> { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::None - } - +impl<'a, 'tcx> hir::itemlikevisit::ItemLikeVisitor<'tcx> for SymbolNamesTest<'a, 'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item) { self.process_attrs(item.id); - intravisit::walk_item(self, item); } - fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) { - self.process_attrs(ti.id); - intravisit::walk_trait_item(self, ti) + fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) { + self.process_attrs(trait_item.id); } - fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) { - self.process_attrs(ii.id); - intravisit::walk_impl_item(self, ii) + fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) { + self.process_attrs(impl_item.id); } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 4a685cfddb7a4..69879bbe85d6e 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -718,6 +718,18 @@ fn typeck_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum })?) } +fn check_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { + wfcheck::check_item_well_formed(tcx, def_id); +} + +fn check_trait_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { + wfcheck::check_trait_item(tcx, def_id); +} + +fn check_impl_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { + wfcheck::check_impl_item(tcx, def_id); +} + pub fn provide(providers: &mut Providers) { *providers = Providers { typeck_item_bodies, @@ -725,6 +737,9 @@ pub fn provide(providers: &mut Providers) { has_typeck_tables, adt_destructor, used_trait_imports, + check_item_well_formed, + check_trait_item_well_formed, + check_impl_item_well_formed, ..*providers }; } @@ -2869,7 +2884,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let origin = self.misc(call_span); let ures = self.at(&origin, self.param_env).sup(ret_ty, formal_ret); - // FIXME(#15760) can't use try! here, FromError doesn't default + // FIXME(#27336) can't use ? here, Try::from_error doesn't default // to identity so the resulting type is not constrained. match ures { Ok(ok) => { @@ -2877,19 +2892,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // we can. We don't care if some things turn // out unconstrained or ambiguous, as we're // just trying to get hints here. - let result = self.save_and_restore_in_snapshot_flag(|_| { + self.save_and_restore_in_snapshot_flag(|_| { let mut fulfill = FulfillmentContext::new(); - let ok = ok; // FIXME(#30046) for obligation in ok.obligations { fulfill.register_predicate_obligation(self, obligation); } fulfill.select_where_possible(self) - }); - - match result { - Ok(()) => { } - Err(_) => return Err(()), - } + }).map_err(|_| ())?; } Err(_) => return Err(()), } diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index b94af0a1e0081..406ff9463a03c 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -26,17 +26,11 @@ use errors::{DiagnosticBuilder, DiagnosticId}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir; -pub struct CheckTypeWellFormedVisitor<'a, 'tcx:'a> { - tcx: TyCtxt<'a, 'tcx, 'tcx>, - code: ObligationCauseCode<'tcx>, -} - /// Helper type of a temporary returned by .for_item(...). /// Necessary because we can't write the following bound: /// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(FnCtxt<'b, 'gcx, 'tcx>). struct CheckWfFcxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { inherited: super::InheritedBuilder<'a, 'gcx, 'tcx>, - code: ObligationCauseCode<'gcx>, id: ast::NodeId, span: Span, param_env: ty::ParamEnv<'tcx>, @@ -45,585 +39,597 @@ struct CheckWfFcxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { impl<'a, 'gcx, 'tcx> CheckWfFcxBuilder<'a, 'gcx, 'tcx> { fn with_fcx(&'tcx mut self, f: F) where F: for<'b> FnOnce(&FnCtxt<'b, 'gcx, 'tcx>, - &mut CheckTypeWellFormedVisitor<'b, 'gcx>) -> Vec> + TyCtxt<'b, 'gcx, 'gcx>) -> Vec> { - let code = self.code.clone(); let id = self.id; let span = self.span; let param_env = self.param_env; self.inherited.enter(|inh| { let fcx = FnCtxt::new(&inh, param_env, id); - let wf_tys = f(&fcx, &mut CheckTypeWellFormedVisitor { - tcx: fcx.tcx.global_tcx(), - code, - }); + let wf_tys = f(&fcx, fcx.tcx.global_tcx()); fcx.select_all_obligations_or_error(); fcx.regionck_item(id, span, &wf_tys); }); } } -impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { - pub fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>) - -> CheckTypeWellFormedVisitor<'a, 'gcx> { - CheckTypeWellFormedVisitor { - tcx, - code: ObligationCauseCode::MiscObligation - } - } - - /// Checks that the field types (in a struct def'n) or argument types (in an enum def'n) are - /// well-formed, meaning that they do not require any constraints not declared in the struct - /// definition itself. For example, this definition would be illegal: - /// - /// struct Ref<'a, T> { x: &'a T } - /// - /// because the type did not declare that `T:'a`. - /// - /// We do this check as a pre-pass before checking fn bodies because if these constraints are - /// not included it frequently leads to confusing errors in fn bodies. So it's better to check - /// the types first. - fn check_item_well_formed(&mut self, item: &hir::Item) { - let tcx = self.tcx; - debug!("check_item_well_formed(it.id={}, it.name={})", - item.id, - tcx.item_path_str(tcx.hir.local_def_id(item.id))); - - match item.node { - // Right now we check that every default trait implementation - // has an implementation of itself. Basically, a case like: - // - // `impl Trait for T {}` - // - // has a requirement of `T: Trait` which was required for default - // method implementations. Although this could be improved now that - // there's a better infrastructure in place for this, it's being left - // for a follow-up work. - // - // Since there's such a requirement, we need to check *just* positive - // implementations, otherwise things like: - // - // impl !Send for T {} - // - // won't be allowed unless there's an *explicit* implementation of `Send` - // for `T` - hir::ItemImpl(_, polarity, defaultness, _, ref trait_ref, ref self_ty, _) => { - let is_auto = tcx.impl_trait_ref(tcx.hir.local_def_id(item.id)) - .map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.def_id)); - if let (hir::Defaultness::Default { .. }, true) = (defaultness, is_auto) { - tcx.sess.span_err(item.span, "impls of auto traits cannot be default"); - } - if polarity == hir::ImplPolarity::Positive { - self.check_impl(item, self_ty, trait_ref); - } else { - // FIXME(#27579) what amount of WF checking do we need for neg impls? - if trait_ref.is_some() && !is_auto { - span_err!(tcx.sess, item.span, E0192, - "negative impls are only allowed for \ - auto traits (e.g., `Send` and `Sync`)") - } - } - } - hir::ItemFn(..) => { - self.check_item_fn(item); - } - hir::ItemStatic(..) => { - self.check_item_type(item); +/// Checks that the field types (in a struct def'n) or argument types (in an enum def'n) are +/// well-formed, meaning that they do not require any constraints not declared in the struct +/// definition itself. For example, this definition would be illegal: +/// +/// struct Ref<'a, T> { x: &'a T } +/// +/// because the type did not declare that `T:'a`. +/// +/// We do this check as a pre-pass before checking fn bodies because if these constraints are +/// not included it frequently leads to confusing errors in fn bodies. So it's better to check +/// the types first. +pub fn check_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { + let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); + let item = tcx.hir.expect_item(node_id); + + debug!("check_item_well_formed(it.id={}, it.name={})", + item.id, + tcx.item_path_str(def_id)); + + match item.node { + // Right now we check that every default trait implementation + // has an implementation of itself. Basically, a case like: + // + // `impl Trait for T {}` + // + // has a requirement of `T: Trait` which was required for default + // method implementations. Although this could be improved now that + // there's a better infrastructure in place for this, it's being left + // for a follow-up work. + // + // Since there's such a requirement, we need to check *just* positive + // implementations, otherwise things like: + // + // impl !Send for T {} + // + // won't be allowed unless there's an *explicit* implementation of `Send` + // for `T` + hir::ItemImpl(_, polarity, defaultness, _, ref trait_ref, ref self_ty, _) => { + let is_auto = tcx.impl_trait_ref(tcx.hir.local_def_id(item.id)) + .map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.def_id)); + if let (hir::Defaultness::Default { .. }, true) = (defaultness, is_auto) { + tcx.sess.span_err(item.span, "impls of auto traits cannot be default"); } - hir::ItemConst(..) => { - self.check_item_type(item); + if polarity == hir::ImplPolarity::Positive { + check_impl(tcx, item, self_ty, trait_ref); + } else { + // FIXME(#27579) what amount of WF checking do we need for neg impls? + if trait_ref.is_some() && !is_auto { + span_err!(tcx.sess, item.span, E0192, + "negative impls are only allowed for \ + auto traits (e.g., `Send` and `Sync`)") + } } - hir::ItemStruct(ref struct_def, ref ast_generics) => { - self.check_type_defn(item, false, |fcx| { - vec![fcx.non_enum_variant(struct_def)] - }); + } + hir::ItemFn(..) => { + check_item_fn(tcx, item); + } + hir::ItemStatic(..) => { + check_item_type(tcx, item); + } + hir::ItemConst(..) => { + check_item_type(tcx, item); + } + hir::ItemStruct(ref struct_def, ref ast_generics) => { + check_type_defn(tcx, item, false, |fcx| { + vec![fcx.non_enum_variant(struct_def)] + }); - self.check_variances_for_type_defn(item, ast_generics); - } - hir::ItemUnion(ref struct_def, ref ast_generics) => { - self.check_type_defn(item, true, |fcx| { - vec![fcx.non_enum_variant(struct_def)] - }); + check_variances_for_type_defn(tcx, item, ast_generics); + } + hir::ItemUnion(ref struct_def, ref ast_generics) => { + check_type_defn(tcx, item, true, |fcx| { + vec![fcx.non_enum_variant(struct_def)] + }); - self.check_variances_for_type_defn(item, ast_generics); - } - hir::ItemEnum(ref enum_def, ref ast_generics) => { - self.check_type_defn(item, true, |fcx| { - fcx.enum_variants(enum_def) - }); + check_variances_for_type_defn(tcx, item, ast_generics); + } + hir::ItemEnum(ref enum_def, ref ast_generics) => { + check_type_defn(tcx, item, true, |fcx| { + fcx.enum_variants(enum_def) + }); - self.check_variances_for_type_defn(item, ast_generics); - } - hir::ItemTrait(..) => { - self.check_trait(item); - } - _ => {} + check_variances_for_type_defn(tcx, item, ast_generics); } + hir::ItemTrait(..) => { + check_trait(tcx, item); + } + _ => {} } +} - fn check_associated_item(&mut self, - item_id: ast::NodeId, - span: Span, - sig_if_method: Option<&hir::MethodSig>) { - let code = self.code.clone(); - self.for_id(item_id, span).with_fcx(|fcx, this| { - let item = fcx.tcx.associated_item(fcx.tcx.hir.local_def_id(item_id)); - - let (mut implied_bounds, self_ty) = match item.container { - ty::TraitContainer(_) => (vec![], fcx.tcx.mk_self_type()), - ty::ImplContainer(def_id) => (fcx.impl_implied_bounds(def_id, span), - fcx.tcx.type_of(def_id)) - }; +pub fn check_trait_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { + let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); + let trait_item = tcx.hir.expect_trait_item(node_id); + + let method_sig = match trait_item.node { + hir::TraitItemKind::Method(ref sig, _) => Some(sig), + _ => None + }; + check_associated_item(tcx, trait_item.id, trait_item.span, method_sig); +} + +pub fn check_impl_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { + let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); + let impl_item = tcx.hir.expect_impl_item(node_id); + + let method_sig = match impl_item.node { + hir::ImplItemKind::Method(ref sig, _) => Some(sig), + _ => None + }; + check_associated_item(tcx, impl_item.id, impl_item.span, method_sig); +} + +fn check_associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + item_id: ast::NodeId, + span: Span, + sig_if_method: Option<&hir::MethodSig>) { + let code = ObligationCauseCode::MiscObligation; + for_id(tcx, item_id, span).with_fcx(|fcx, tcx| { + let item = fcx.tcx.associated_item(fcx.tcx.hir.local_def_id(item_id)); + + let (mut implied_bounds, self_ty) = match item.container { + ty::TraitContainer(_) => (vec![], fcx.tcx.mk_self_type()), + ty::ImplContainer(def_id) => (fcx.impl_implied_bounds(def_id, span), + fcx.tcx.type_of(def_id)) + }; - match item.kind { - ty::AssociatedKind::Const => { + match item.kind { + ty::AssociatedKind::Const => { + let ty = fcx.tcx.type_of(item.def_id); + let ty = fcx.normalize_associated_types_in(span, &ty); + fcx.register_wf_obligation(ty, span, code.clone()); + } + ty::AssociatedKind::Method => { + reject_shadowing_type_parameters(fcx.tcx, item.def_id); + let sig = fcx.tcx.fn_sig(item.def_id); + let sig = fcx.normalize_associated_types_in(span, &sig); + check_fn_or_method(tcx, fcx, span, sig, + item.def_id, &mut implied_bounds); + let sig_if_method = sig_if_method.expect("bad signature for method"); + check_method_receiver(fcx, sig_if_method, &item, self_ty); + } + ty::AssociatedKind::Type => { + if item.defaultness.has_value() { let ty = fcx.tcx.type_of(item.def_id); let ty = fcx.normalize_associated_types_in(span, &ty); fcx.register_wf_obligation(ty, span, code.clone()); } - ty::AssociatedKind::Method => { - reject_shadowing_type_parameters(fcx.tcx, item.def_id); - let sig = fcx.tcx.fn_sig(item.def_id); - let sig = fcx.normalize_associated_types_in(span, &sig); - this.check_fn_or_method(fcx, span, sig, - item.def_id, &mut implied_bounds); - let sig_if_method = sig_if_method.expect("bad signature for method"); - this.check_method_receiver(fcx, sig_if_method, &item, self_ty); - } - ty::AssociatedKind::Type => { - if item.defaultness.has_value() { - let ty = fcx.tcx.type_of(item.def_id); - let ty = fcx.normalize_associated_types_in(span, &ty); - fcx.register_wf_obligation(ty, span, code.clone()); - } - } } + } - implied_bounds - }) - } - - fn for_item<'tcx>(&self, item: &hir::Item) - -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> { - self.for_id(item.id, item.span) - } + implied_bounds + }) +} - fn for_id<'tcx>(&self, id: ast::NodeId, span: Span) +fn for_item<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, item: &hir::Item) -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> { - let def_id = self.tcx.hir.local_def_id(id); - CheckWfFcxBuilder { - inherited: Inherited::build(self.tcx, def_id), - code: self.code.clone(), - id, - span, - param_env: self.tcx.param_env(def_id), - } + for_id(tcx, item.id, item.span) +} + +fn for_id<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, id: ast::NodeId, span: Span) + -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> { + let def_id = tcx.hir.local_def_id(id); + CheckWfFcxBuilder { + inherited: Inherited::build(tcx, def_id), + id, + span, + param_env: tcx.param_env(def_id), } +} - /// In a type definition, we check that to ensure that the types of the fields are well-formed. - fn check_type_defn(&mut self, item: &hir::Item, all_sized: bool, mut lookup_fields: F) - where F: for<'fcx, 'tcx> FnMut(&FnCtxt<'fcx, 'gcx, 'tcx>) -> Vec> - { - self.for_item(item).with_fcx(|fcx, this| { - let variants = lookup_fields(fcx); - let def_id = fcx.tcx.hir.local_def_id(item.id); - let packed = fcx.tcx.adt_def(def_id).repr.packed(); - - for variant in &variants { - // For DST, or when drop needs to copy things around, all - // intermediate types must be sized. - let needs_drop_copy = || { - packed && { - let ty = variant.fields.last().unwrap().ty; - let ty = fcx.tcx.erase_regions(&ty).lift_to_tcx(this.tcx) - .unwrap_or_else(|| { - span_bug!(item.span, "inference variables in {:?}", ty) - }); - ty.needs_drop(this.tcx, this.tcx.param_env(def_id)) - } - }; - let unsized_len = if - all_sized || - variant.fields.is_empty() || - needs_drop_copy() - { - 0 - } else { - 1 - }; - for field in &variant.fields[..variant.fields.len() - unsized_len] { - fcx.register_bound( - field.ty, - fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), - traits::ObligationCause::new(field.span, - fcx.body_id, - traits::FieldSized(match item.node.adt_kind() { - Some(i) => i, - None => bug!(), - }))); +/// In a type definition, we check that to ensure that the types of the fields are well-formed. +fn check_type_defn<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + item: &hir::Item, all_sized: bool, mut lookup_fields: F) + where F: for<'fcx, 'gcx, 'tcx2> FnMut(&FnCtxt<'fcx, 'gcx, 'tcx2>) -> Vec> +{ + for_item(tcx, item).with_fcx(|fcx, fcx_tcx| { + let variants = lookup_fields(fcx); + let def_id = fcx.tcx.hir.local_def_id(item.id); + let packed = fcx.tcx.adt_def(def_id).repr.packed(); + + for variant in &variants { + // For DST, or when drop needs to copy things around, all + // intermediate types must be sized. + let needs_drop_copy = || { + packed && { + let ty = variant.fields.last().unwrap().ty; + let ty = fcx.tcx.erase_regions(&ty).lift_to_tcx(fcx_tcx) + .unwrap_or_else(|| { + span_bug!(item.span, "inference variables in {:?}", ty) + }); + ty.needs_drop(fcx_tcx, fcx_tcx.param_env(def_id)) } + }; + let unsized_len = if + all_sized || + variant.fields.is_empty() || + needs_drop_copy() + { + 0 + } else { + 1 + }; + for field in &variant.fields[..variant.fields.len() - unsized_len] { + fcx.register_bound( + field.ty, + fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), + traits::ObligationCause::new(field.span, + fcx.body_id, + traits::FieldSized(match item.node.adt_kind() { + Some(i) => i, + None => bug!(), + }))); + } - // All field types must be well-formed. - for field in &variant.fields { - fcx.register_wf_obligation(field.ty, field.span, this.code.clone()) - } + // All field types must be well-formed. + for field in &variant.fields { + fcx.register_wf_obligation(field.ty, field.span, + ObligationCauseCode::MiscObligation) } + } - self.check_where_clauses(fcx, item.span, def_id); + check_where_clauses(tcx, fcx, item.span, def_id); - vec![] // no implied bounds in a struct def'n - }); - } + vec![] // no implied bounds in a struct def'n + }); +} - fn check_trait(&mut self, item: &hir::Item) { - let trait_def_id = self.tcx.hir.local_def_id(item.id); - self.for_item(item).with_fcx(|fcx, _| { - self.check_where_clauses(fcx, item.span, trait_def_id); - vec![] - }); - } +fn check_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item) { + let trait_def_id = tcx.hir.local_def_id(item.id); + for_item(tcx, item).with_fcx(|fcx, _| { + check_where_clauses(tcx, fcx, item.span, trait_def_id); + vec![] + }); +} - fn check_item_fn(&mut self, item: &hir::Item) { - self.for_item(item).with_fcx(|fcx, this| { - let def_id = fcx.tcx.hir.local_def_id(item.id); - let sig = fcx.tcx.fn_sig(def_id); - let sig = fcx.normalize_associated_types_in(item.span, &sig); - let mut implied_bounds = vec![]; - this.check_fn_or_method(fcx, item.span, sig, - def_id, &mut implied_bounds); - implied_bounds - }) - } +fn check_item_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item) { + for_item(tcx, item).with_fcx(|fcx, tcx| { + let def_id = fcx.tcx.hir.local_def_id(item.id); + let sig = fcx.tcx.fn_sig(def_id); + let sig = fcx.normalize_associated_types_in(item.span, &sig); + let mut implied_bounds = vec![]; + check_fn_or_method(tcx, fcx, item.span, sig, + def_id, &mut implied_bounds); + implied_bounds + }) +} - fn check_item_type(&mut self, - item: &hir::Item) - { - debug!("check_item_type: {:?}", item); +fn check_item_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + item: &hir::Item) +{ + debug!("check_item_type: {:?}", item); - self.for_item(item).with_fcx(|fcx, this| { - let ty = fcx.tcx.type_of(fcx.tcx.hir.local_def_id(item.id)); - let item_ty = fcx.normalize_associated_types_in(item.span, &ty); + for_item(tcx, item).with_fcx(|fcx, _this| { + let ty = fcx.tcx.type_of(fcx.tcx.hir.local_def_id(item.id)); + let item_ty = fcx.normalize_associated_types_in(item.span, &ty); - fcx.register_wf_obligation(item_ty, item.span, this.code.clone()); + fcx.register_wf_obligation(item_ty, item.span, ObligationCauseCode::MiscObligation); - vec![] // no implied bounds in a const etc - }); - } + vec![] // no implied bounds in a const etc + }); +} - fn check_impl(&mut self, - item: &hir::Item, - ast_self_ty: &hir::Ty, - ast_trait_ref: &Option) - { - debug!("check_impl: {:?}", item); - - self.for_item(item).with_fcx(|fcx, this| { - let item_def_id = fcx.tcx.hir.local_def_id(item.id); - - match *ast_trait_ref { - Some(ref ast_trait_ref) => { - let trait_ref = fcx.tcx.impl_trait_ref(item_def_id).unwrap(); - let trait_ref = - fcx.normalize_associated_types_in( - ast_trait_ref.path.span, &trait_ref); - let obligations = - ty::wf::trait_obligations(fcx, - fcx.param_env, - fcx.body_id, - &trait_ref, - ast_trait_ref.path.span); - for obligation in obligations { - fcx.register_predicate(obligation); - } - } - None => { - let self_ty = fcx.tcx.type_of(item_def_id); - let self_ty = fcx.normalize_associated_types_in(item.span, &self_ty); - fcx.register_wf_obligation(self_ty, ast_self_ty.span, this.code.clone()); +fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + item: &hir::Item, + ast_self_ty: &hir::Ty, + ast_trait_ref: &Option) +{ + debug!("check_impl: {:?}", item); + + for_item(tcx, item).with_fcx(|fcx, tcx| { + let item_def_id = fcx.tcx.hir.local_def_id(item.id); + + match *ast_trait_ref { + Some(ref ast_trait_ref) => { + let trait_ref = fcx.tcx.impl_trait_ref(item_def_id).unwrap(); + let trait_ref = + fcx.normalize_associated_types_in( + ast_trait_ref.path.span, &trait_ref); + let obligations = + ty::wf::trait_obligations(fcx, + fcx.param_env, + fcx.body_id, + &trait_ref, + ast_trait_ref.path.span); + for obligation in obligations { + fcx.register_predicate(obligation); } } + None => { + let self_ty = fcx.tcx.type_of(item_def_id); + let self_ty = fcx.normalize_associated_types_in(item.span, &self_ty); + fcx.register_wf_obligation(self_ty, ast_self_ty.span, + ObligationCauseCode::MiscObligation); + } + } - this.check_where_clauses(fcx, item.span, item_def_id); + check_where_clauses(tcx, fcx, item.span, item_def_id); - fcx.impl_implied_bounds(item_def_id, item.span) - }); - } + fcx.impl_implied_bounds(item_def_id, item.span) + }); +} - /// Checks where clauses and inline bounds that are declared on def_id. - fn check_where_clauses<'fcx, 'tcx>(&mut self, - fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, - span: Span, - def_id: DefId) { - use ty::subst::Subst; - use rustc::ty::TypeFoldable; - - let mut predicates = fcx.tcx.predicates_of(def_id); - let mut substituted_predicates = Vec::new(); - - let generics = self.tcx.generics_of(def_id); - let is_our_default = |def: &ty::TypeParameterDef| - def.has_default && def.index >= generics.parent_count() as u32; - - // Check that concrete defaults are well-formed. See test `type-check-defaults.rs`. - // For example this forbids the declaration: - // struct Foo> { .. } - // Here the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold. - for d in generics.types.iter().cloned().filter(is_our_default).map(|p| p.def_id) { - let ty = fcx.tcx.type_of(d); - // ignore dependent defaults -- that is, where the default of one type - // parameter includes another (e.g., ). In those cases, we can't - // be sure if it will error or not as user might always specify the other. - if !ty.needs_subst() { - fcx.register_wf_obligation(ty, fcx.tcx.def_span(d), self.code.clone()); - } +/// Checks where clauses and inline bounds that are declared on def_id. +fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, + fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, + span: Span, + def_id: DefId) { + use ty::subst::Subst; + use rustc::ty::TypeFoldable; + + let mut predicates = fcx.tcx.predicates_of(def_id); + let mut substituted_predicates = Vec::new(); + + let generics = tcx.generics_of(def_id); + let is_our_default = |def: &ty::TypeParameterDef| + def.has_default && def.index >= generics.parent_count() as u32; + + // Check that concrete defaults are well-formed. See test `type-check-defaults.rs`. + // For example this forbids the declaration: + // struct Foo> { .. } + // Here the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold. + for d in generics.types.iter().cloned().filter(is_our_default).map(|p| p.def_id) { + let ty = fcx.tcx.type_of(d); + // ignore dependent defaults -- that is, where the default of one type + // parameter includes another (e.g., ). In those cases, we can't + // be sure if it will error or not as user might always specify the other. + if !ty.needs_subst() { + fcx.register_wf_obligation(ty, fcx.tcx.def_span(d), + ObligationCauseCode::MiscObligation); } + } - // Check that trait predicates are WF when params are substituted by their defaults. - // We don't want to overly constrain the predicates that may be written but we want to - // catch cases where a default my never be applied such as `struct Foo`. - // Therefore we check if a predicate which contains a single type param - // with a concrete default is WF with that default substituted. - // For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`. - // - // First we build the defaulted substitution. - let substs = ty::subst::Substs::for_item(fcx.tcx, def_id, |def, _| { - // All regions are identity. - fcx.tcx.mk_region(ty::ReEarlyBound(def.to_early_bound_region_data())) - }, |def, _| { - // If the param has a default, - if is_our_default(def) { - let default_ty = fcx.tcx.type_of(def.def_id); - // and it's not a dependent default - if !default_ty.needs_subst() { - // then substitute with the default. - return default_ty; - } + // Check that trait predicates are WF when params are substituted by their defaults. + // We don't want to overly constrain the predicates that may be written but we want to + // catch cases where a default my never be applied such as `struct Foo`. + // Therefore we check if a predicate which contains a single type param + // with a concrete default is WF with that default substituted. + // For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`. + // + // First we build the defaulted substitution. + let substs = ty::subst::Substs::for_item(fcx.tcx, def_id, |def, _| { + // All regions are identity. + fcx.tcx.mk_region(ty::ReEarlyBound(def.to_early_bound_region_data())) + }, |def, _| { + // If the param has a default, + if is_our_default(def) { + let default_ty = fcx.tcx.type_of(def.def_id); + // and it's not a dependent default + if !default_ty.needs_subst() { + // then substitute with the default. + return default_ty; } - // Mark unwanted params as err. - fcx.tcx.types.err - }); - // Now we build the substituted predicates. - for &pred in predicates.predicates.iter() { - struct CountParams { params: FxHashSet } - impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams { - fn visit_ty(&mut self, t: Ty<'tcx>) -> bool { - match t.sty { - ty::TyParam(p) => { - self.params.insert(p.idx); - t.super_visit_with(self) - } - _ => t.super_visit_with(self) + } + // Mark unwanted params as err. + fcx.tcx.types.err + }); + // Now we build the substituted predicates. + for &pred in predicates.predicates.iter() { + struct CountParams { params: FxHashSet } + impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams { + fn visit_ty(&mut self, t: Ty<'tcx>) -> bool { + match t.sty { + ty::TyParam(p) => { + self.params.insert(p.idx); + t.super_visit_with(self) } + _ => t.super_visit_with(self) } } - let mut param_count = CountParams { params: FxHashSet() }; - pred.visit_with(&mut param_count); - let substituted_pred = pred.subst(fcx.tcx, substs); - // Don't check non-defaulted params, dependent defaults or preds with multiple params. - if substituted_pred.references_error() || param_count.params.len() > 1 { - continue; - } - // Avoid duplication of predicates that contain no parameters, for example. - if !predicates.predicates.contains(&substituted_pred) { - substituted_predicates.push(substituted_pred); - } } - - predicates.predicates.extend(substituted_predicates); - let predicates = predicates.instantiate_identity(fcx.tcx); - let predicates = fcx.normalize_associated_types_in(span, &predicates); - - let obligations = - predicates.predicates - .iter() - .flat_map(|p| ty::wf::predicate_obligations(fcx, - fcx.param_env, - fcx.body_id, - p, - span)); - - for obligation in obligations { - fcx.register_predicate(obligation); + let mut param_count = CountParams { params: FxHashSet() }; + pred.visit_with(&mut param_count); + let substituted_pred = pred.subst(fcx.tcx, substs); + // Don't check non-defaulted params, dependent defaults or preds with multiple params. + if substituted_pred.references_error() || param_count.params.len() > 1 { + continue; + } + // Avoid duplication of predicates that contain no parameters, for example. + if !predicates.predicates.contains(&substituted_pred) { + substituted_predicates.push(substituted_pred); } } - fn check_fn_or_method<'fcx, 'tcx>(&mut self, - fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, - span: Span, - sig: ty::PolyFnSig<'tcx>, - def_id: DefId, - implied_bounds: &mut Vec>) - { - let sig = fcx.normalize_associated_types_in(span, &sig); - let sig = fcx.tcx.liberate_late_bound_regions(def_id, &sig); - - for input_ty in sig.inputs() { - fcx.register_wf_obligation(&input_ty, span, self.code.clone()); - } - implied_bounds.extend(sig.inputs()); + predicates.predicates.extend(substituted_predicates); + let predicates = predicates.instantiate_identity(fcx.tcx); + let predicates = fcx.normalize_associated_types_in(span, &predicates); + + let obligations = + predicates.predicates + .iter() + .flat_map(|p| ty::wf::predicate_obligations(fcx, + fcx.param_env, + fcx.body_id, + p, + span)); + + for obligation in obligations { + fcx.register_predicate(obligation); + } +} - fcx.register_wf_obligation(sig.output(), span, self.code.clone()); +fn check_fn_or_method<'a, 'fcx, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, + fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, + span: Span, + sig: ty::PolyFnSig<'tcx>, + def_id: DefId, + implied_bounds: &mut Vec>) +{ + let sig = fcx.normalize_associated_types_in(span, &sig); + let sig = fcx.tcx.liberate_late_bound_regions(def_id, &sig); + + for input_ty in sig.inputs() { + fcx.register_wf_obligation(&input_ty, span, ObligationCauseCode::MiscObligation); + } + implied_bounds.extend(sig.inputs()); - // FIXME(#25759) return types should not be implied bounds - implied_bounds.push(sig.output()); + fcx.register_wf_obligation(sig.output(), span, ObligationCauseCode::MiscObligation); - self.check_where_clauses(fcx, span, def_id); - } + // FIXME(#25759) return types should not be implied bounds + implied_bounds.push(sig.output()); - fn check_method_receiver<'fcx, 'tcx>(&mut self, - fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, - method_sig: &hir::MethodSig, - method: &ty::AssociatedItem, - self_ty: Ty<'tcx>) - { - // check that the method has a valid receiver type, given the type `Self` - debug!("check_method_receiver({:?}, self_ty={:?})", - method, self_ty); + check_where_clauses(tcx, fcx, span, def_id); +} - if !method.method_has_self_argument { - return; - } +fn check_method_receiver<'fcx, 'gcx, 'tcx>(fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, + method_sig: &hir::MethodSig, + method: &ty::AssociatedItem, + self_ty: Ty<'tcx>) +{ + // check that the method has a valid receiver type, given the type `Self` + debug!("check_method_receiver({:?}, self_ty={:?})", + method, self_ty); + + if !method.method_has_self_argument { + return; + } - let span = method_sig.decl.inputs[0].span; + let span = method_sig.decl.inputs[0].span; - let sig = fcx.tcx.fn_sig(method.def_id); - let sig = fcx.normalize_associated_types_in(span, &sig); - let sig = fcx.tcx.liberate_late_bound_regions(method.def_id, &sig); + let sig = fcx.tcx.fn_sig(method.def_id); + let sig = fcx.normalize_associated_types_in(span, &sig); + let sig = fcx.tcx.liberate_late_bound_regions(method.def_id, &sig); - debug!("check_method_receiver: sig={:?}", sig); + debug!("check_method_receiver: sig={:?}", sig); - let self_ty = fcx.normalize_associated_types_in(span, &self_ty); - let self_ty = fcx.tcx.liberate_late_bound_regions( - method.def_id, - &ty::Binder(self_ty) - ); + let self_ty = fcx.normalize_associated_types_in(span, &self_ty); + let self_ty = fcx.tcx.liberate_late_bound_regions( + method.def_id, + &ty::Binder(self_ty) + ); - let self_arg_ty = sig.inputs()[0]; + let self_arg_ty = sig.inputs()[0]; - let cause = fcx.cause(span, ObligationCauseCode::MethodReceiver); - let self_arg_ty = fcx.normalize_associated_types_in(span, &self_arg_ty); - let self_arg_ty = fcx.tcx.liberate_late_bound_regions( - method.def_id, - &ty::Binder(self_arg_ty) - ); + let cause = fcx.cause(span, ObligationCauseCode::MethodReceiver); + let self_arg_ty = fcx.normalize_associated_types_in(span, &self_arg_ty); + let self_arg_ty = fcx.tcx.liberate_late_bound_regions( + method.def_id, + &ty::Binder(self_arg_ty) + ); - let mut autoderef = fcx.autoderef(span, self_arg_ty).include_raw_pointers(); + let mut autoderef = fcx.autoderef(span, self_arg_ty).include_raw_pointers(); - loop { - if let Some((potential_self_ty, _)) = autoderef.next() { - debug!("check_method_receiver: potential self type `{:?}` to match `{:?}`", - potential_self_ty, self_ty); + loop { + if let Some((potential_self_ty, _)) = autoderef.next() { + debug!("check_method_receiver: potential self type `{:?}` to match `{:?}`", + potential_self_ty, self_ty); - if fcx.infcx.can_eq(fcx.param_env, self_ty, potential_self_ty).is_ok() { - autoderef.finalize(); - if let Some(mut err) = fcx.demand_eqtype_with_origin( - &cause, self_ty, potential_self_ty) { - err.emit(); - } - break + if fcx.infcx.can_eq(fcx.param_env, self_ty, potential_self_ty).is_ok() { + autoderef.finalize(); + if let Some(mut err) = fcx.demand_eqtype_with_origin( + &cause, self_ty, potential_self_ty) { + err.emit(); } - } else { - fcx.tcx.sess.diagnostic().mut_span_err( - span, &format!("invalid `self` type: {:?}", self_arg_ty)) - .note(&format!("type must be `{:?}` or a type that dereferences to it", self_ty)) - .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box`") - .code(DiagnosticId::Error("E0307".into())) - .emit(); - return + break } + } else { + fcx.tcx.sess.diagnostic().mut_span_err( + span, &format!("invalid `self` type: {:?}", self_arg_ty)) + .note(&format!("type must be `{:?}` or a type that dereferences to it", self_ty)) + .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box`") + .code(DiagnosticId::Error("E0307".into())) + .emit(); + return } + } - let is_self_ty = |ty| fcx.infcx.can_eq(fcx.param_env, self_ty, ty).is_ok(); - let self_kind = ExplicitSelf::determine(self_arg_ty, is_self_ty); - - if !fcx.tcx.features().arbitrary_self_types { - match self_kind { - ExplicitSelf::ByValue | - ExplicitSelf::ByReference(_, _) | - ExplicitSelf::ByBox => (), - - ExplicitSelf::ByRawPointer(_) => { - feature_gate::feature_err( - &fcx.tcx.sess.parse_sess, - "arbitrary_self_types", - span, - GateIssue::Language, - "raw pointer `self` is unstable") - .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box`") - .emit(); - } + let is_self_ty = |ty| fcx.infcx.can_eq(fcx.param_env, self_ty, ty).is_ok(); + let self_kind = ExplicitSelf::determine(self_arg_ty, is_self_ty); + + if !fcx.tcx.features().arbitrary_self_types { + match self_kind { + ExplicitSelf::ByValue | + ExplicitSelf::ByReference(_, _) | + ExplicitSelf::ByBox => (), + + ExplicitSelf::ByRawPointer(_) => { + feature_gate::feature_err( + &fcx.tcx.sess.parse_sess, + "arbitrary_self_types", + span, + GateIssue::Language, + "raw pointer `self` is unstable") + .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box`") + .emit(); + } - ExplicitSelf::Other => { - feature_gate::feature_err( - &fcx.tcx.sess.parse_sess, - "arbitrary_self_types", - span, - GateIssue::Language,"arbitrary `self` types are unstable") - .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box`") - .emit(); - } + ExplicitSelf::Other => { + feature_gate::feature_err( + &fcx.tcx.sess.parse_sess, + "arbitrary_self_types", + span, + GateIssue::Language,"arbitrary `self` types are unstable") + .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box`") + .emit(); } } } +} - fn check_variances_for_type_defn(&self, - item: &hir::Item, - ast_generics: &hir::Generics) - { - let item_def_id = self.tcx.hir.local_def_id(item.id); - let ty = self.tcx.type_of(item_def_id); - if self.tcx.has_error_field(ty) { - return; - } - - let ty_predicates = self.tcx.predicates_of(item_def_id); - assert_eq!(ty_predicates.parent, None); - let variances = self.tcx.variances_of(item_def_id); +fn check_variances_for_type_defn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + item: &hir::Item, + ast_generics: &hir::Generics) +{ + let item_def_id = tcx.hir.local_def_id(item.id); + let ty = tcx.type_of(item_def_id); + if tcx.has_error_field(ty) { + return; + } - let mut constrained_parameters: FxHashSet<_> = - variances.iter().enumerate() - .filter(|&(_, &variance)| variance != ty::Bivariant) - .map(|(index, _)| Parameter(index as u32)) - .collect(); + let ty_predicates = tcx.predicates_of(item_def_id); + assert_eq!(ty_predicates.parent, None); + let variances = tcx.variances_of(item_def_id); - identify_constrained_type_params(self.tcx, - ty_predicates.predicates.as_slice(), - None, - &mut constrained_parameters); + let mut constrained_parameters: FxHashSet<_> = + variances.iter().enumerate() + .filter(|&(_, &variance)| variance != ty::Bivariant) + .map(|(index, _)| Parameter(index as u32)) + .collect(); - for (index, _) in variances.iter().enumerate() { - if constrained_parameters.contains(&Parameter(index as u32)) { - continue; - } + identify_constrained_type_params(tcx, + ty_predicates.predicates.as_slice(), + None, + &mut constrained_parameters); - let (span, name) = match ast_generics.params[index] { - hir::GenericParam::Lifetime(ref ld) => (ld.lifetime.span, ld.lifetime.name.name()), - hir::GenericParam::Type(ref tp) => (tp.span, tp.name), - }; - self.report_bivariance(span, name); + for (index, _) in variances.iter().enumerate() { + if constrained_parameters.contains(&Parameter(index as u32)) { + continue; } + + let (span, name) = match ast_generics.params[index] { + hir::GenericParam::Lifetime(ref ld) => (ld.lifetime.span, ld.lifetime.name.name()), + hir::GenericParam::Type(ref tp) => (tp.span, tp.name), + }; + report_bivariance(tcx, span, name); } +} - fn report_bivariance(&self, - span: Span, - param_name: ast::Name) - { - let mut err = error_392(self.tcx, span, param_name); - - let suggested_marker_id = self.tcx.lang_items().phantom_data(); - match suggested_marker_id { - Some(def_id) => { - err.help( - &format!("consider removing `{}` or using a marker such as `{}`", - param_name, - self.tcx.item_path_str(def_id))); - } - None => { - // no lang items, no help! - } +fn report_bivariance<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + span: Span, + param_name: ast::Name) +{ + let mut err = error_392(tcx, span, param_name); + + let suggested_marker_id = tcx.lang_items().phantom_data(); + match suggested_marker_id { + Some(def_id) => { + err.help( + &format!("consider removing `{}` or using a marker such as `{}`", + param_name, + tcx.item_path_str(def_id))); + } + None => { + // no lang items, no help! } - err.emit(); } + err.emit(); } fn reject_shadowing_type_parameters(tcx: TyCtxt, def_id: DefId) { @@ -648,6 +654,19 @@ fn reject_shadowing_type_parameters(tcx: TyCtxt, def_id: DefId) { } } +pub struct CheckTypeWellFormedVisitor<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, +} + +impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { + pub fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>) + -> CheckTypeWellFormedVisitor<'a, 'gcx> { + CheckTypeWellFormedVisitor { + tcx, + } + } +} + impl<'a, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> { NestedVisitorMap::None @@ -655,27 +674,22 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'a, 'tcx> { fn visit_item(&mut self, i: &hir::Item) { debug!("visit_item: {:?}", i); - self.check_item_well_formed(i); + let def_id = self.tcx.hir.local_def_id(i.id); + ty::maps::queries::check_item_well_formed::ensure(self.tcx, def_id); intravisit::walk_item(self, i); } fn visit_trait_item(&mut self, trait_item: &'v hir::TraitItem) { debug!("visit_trait_item: {:?}", trait_item); - let method_sig = match trait_item.node { - hir::TraitItemKind::Method(ref sig, _) => Some(sig), - _ => None - }; - self.check_associated_item(trait_item.id, trait_item.span, method_sig); + let def_id = self.tcx.hir.local_def_id(trait_item.id); + ty::maps::queries::check_trait_item_well_formed::ensure(self.tcx, def_id); intravisit::walk_trait_item(self, trait_item) } fn visit_impl_item(&mut self, impl_item: &'v hir::ImplItem) { debug!("visit_impl_item: {:?}", impl_item); - let method_sig = match impl_item.node { - hir::ImplItemKind::Method(ref sig, _) => Some(sig), - _ => None - }; - self.check_associated_item(impl_item.id, impl_item.span, method_sig); + let def_id = self.tcx.hir.local_def_id(impl_item.id); + ty::maps::queries::check_impl_item_well_formed::ensure(self.tcx, def_id); intravisit::walk_impl_item(self, impl_item) } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 904c24815cb7f..72e303e198202 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -929,7 +929,7 @@ fn ambiguity_error(cx: &DocContext, attrs: &Attributes, select the {}", disambig1, kind1, disambig2, kind2)) - .emit(); + .emit(); } /// Given an enum variant's def, return the def of its enum and the associated fragment @@ -1074,6 +1074,7 @@ fn macro_resolve(cx: &DocContext, path_str: &str) -> Option { } } +#[derive(Debug)] enum PathKind { /// can be either value or type, not a macro Unknown, @@ -1082,7 +1083,7 @@ enum PathKind { /// values, functions, consts, statics, everything in the value namespace Value, /// types, traits, everything in the type namespace - Type + Type, } impl Clean for [ast::Attribute] { @@ -1091,12 +1092,13 @@ impl Clean for [ast::Attribute] { if UnstableFeatures::from_environment().is_nightly_build() { let dox = attrs.collapsed_doc_value().unwrap_or_else(String::new); - for link in markdown_links(&dox) { + for ori_link in markdown_links(&dox) { // bail early for real links - if link.contains('/') { + if ori_link.contains('/') { continue; } - let (def, fragment) = { + let link = ori_link.replace("`", ""); + let (def, fragment) = { let mut kind = PathKind::Unknown; let path_str = if let Some(prefix) = ["struct@", "enum@", "type@", @@ -1132,7 +1134,6 @@ impl Clean for [ast::Attribute] { continue; } - match kind { PathKind::Value => { if let Ok(def) = resolve(cx, path_str, true) { @@ -1206,9 +1207,8 @@ impl Clean for [ast::Attribute] { } }; - let id = register_def(cx, def); - attrs.links.push((link, id, fragment)); + attrs.links.push((ori_link, id, fragment)); } cx.sess().abort_if_errors(); diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 5e55353a26e6b..c09bd4cc84ae5 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -27,6 +27,7 @@ #![allow(non_camel_case_types)] +use rustc::session; use std::cell::RefCell; use std::collections::{HashMap, VecDeque}; use std::default::Default; @@ -232,14 +233,14 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'a, I> { /// Make headings links with anchor ids and build up TOC. struct LinkReplacer<'a, 'b, I: Iterator>> { inner: I, - links: &'b [(String, String)] + links: &'b [(String, String)], } impl<'a, 'b, I: Iterator>> LinkReplacer<'a, 'b, I> { fn new(iter: I, links: &'b [(String, String)]) -> Self { LinkReplacer { inner: iter, - links + links, } } } @@ -434,7 +435,8 @@ impl<'a, I: Iterator>> Iterator for Footnotes<'a, I> { } } -pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Span) { +pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Span, + sess: Option<&session::Session>) { tests.set_position(position); let mut parser = Parser::new(doc); @@ -484,6 +486,9 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Sp line, filename, block_info.allow_fail); prev_offset = offset; } else { + if let Some(ref sess) = sess { + sess.span_warn(position, "invalid start of a new code block"); + } break; } } diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 0f107457d2bf8..3a55b279b5cc7 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -152,7 +152,7 @@ pub fn test(input: &str, cfgs: Vec, libs: SearchPaths, externs: Externs, true, opts, maybe_sysroot, None, Some(PathBuf::from(input)), linker); - find_testable_code(&input_str, &mut collector, DUMMY_SP); + find_testable_code(&input_str, &mut collector, DUMMY_SP, None); test_args.insert(0, "rustdoctest".to_string()); testing::test_main(&test_args, collector.tests, testing::Options::new().display_output(display_warnings)); diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 117b21d47587f..3ce8bd4ebb4c1 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -416,6 +416,7 @@ fn partition_source(s: &str) -> (String, String) { let trimline = line.trim(); let header = trimline.is_whitespace() || trimline.starts_with("#![") || + trimline.starts_with("#[macro_use] extern crate") || trimline.starts_with("extern crate"); if !header || after_header { after_header = true; @@ -645,8 +646,10 @@ impl<'a, 'hir> HirCollector<'a, 'hir> { // the collapse-docs pass won't combine sugared/raw doc attributes, or included files with // anything else, this will combine them for us if let Some(doc) = attrs.collapsed_doc_value() { - markdown::find_testable_code(&doc, self.collector, - attrs.span.unwrap_or(DUMMY_SP)); + markdown::find_testable_code(&doc, + self.collector, + attrs.span.unwrap_or(DUMMY_SP), + Some(self.sess)); } nested(self); @@ -825,6 +828,24 @@ assert_eq!(2+2, 4); assert_eq!(output, (expected, 2)); } + #[test] + fn make_test_manual_extern_crate_with_macro_use() { + let opts = TestOptions::default(); + let input = +"#[macro_use] extern crate asdf; +use asdf::qwop; +assert_eq!(2+2, 4);"; + let expected = +"#![allow(unused)] +#[macro_use] extern crate asdf; +fn main() { +use asdf::qwop; +assert_eq!(2+2, 4); +}".to_string(); + let output = make_test(input, Some("asdf"), false, &opts); + assert_eq!(output, (expected, 2)); + } + #[test] fn make_test_opts_attrs() { //if you supplied some doctest attributes with #![doc(test(attr(...)))], it will use those diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index 0837ff91c142d..6472edb0aa7d3 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -52,6 +52,7 @@ pub use core::ascii::{EscapeDefault, escape_default}; /// /// [combining character]: https://en.wikipedia.org/wiki/Combining_character #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] pub trait AsciiExt { /// Container type for copied ASCII characters. #[stable(feature = "rust1", since = "1.0.0")] @@ -84,6 +85,7 @@ pub trait AsciiExt { /// [`make_ascii_uppercase`]: #tymethod.make_ascii_uppercase /// [`str::to_uppercase`]: ../primitive.str.html#method.to_uppercase #[stable(feature = "rust1", since = "1.0.0")] + #[allow(deprecated)] fn to_ascii_uppercase(&self) -> Self::Owned; /// Makes a copy of the value in its ASCII lower case equivalent. @@ -104,6 +106,7 @@ pub trait AsciiExt { /// [`make_ascii_lowercase`]: #tymethod.make_ascii_lowercase /// [`str::to_lowercase`]: ../primitive.str.html#method.to_lowercase #[stable(feature = "rust1", since = "1.0.0")] + #[allow(deprecated)] fn to_ascii_lowercase(&self) -> Self::Owned; /// Checks that two values are an ASCII case-insensitive match. @@ -162,6 +165,7 @@ pub trait AsciiExt { /// This method will be deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. #[unstable(feature = "ascii_ctype", issue = "39658")] + #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_alphabetic(&self) -> bool { unimplemented!(); } /// Checks if the value is an ASCII uppercase character: @@ -174,6 +178,7 @@ pub trait AsciiExt { /// This method will be deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. #[unstable(feature = "ascii_ctype", issue = "39658")] + #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_uppercase(&self) -> bool { unimplemented!(); } /// Checks if the value is an ASCII lowercase character: @@ -186,6 +191,7 @@ pub trait AsciiExt { /// This method will be deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. #[unstable(feature = "ascii_ctype", issue = "39658")] + #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_lowercase(&self) -> bool { unimplemented!(); } /// Checks if the value is an ASCII alphanumeric character: @@ -199,6 +205,7 @@ pub trait AsciiExt { /// This method will be deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. #[unstable(feature = "ascii_ctype", issue = "39658")] + #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_alphanumeric(&self) -> bool { unimplemented!(); } /// Checks if the value is an ASCII decimal digit: @@ -211,6 +218,7 @@ pub trait AsciiExt { /// This method will be deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. #[unstable(feature = "ascii_ctype", issue = "39658")] + #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_digit(&self) -> bool { unimplemented!(); } /// Checks if the value is an ASCII hexadecimal digit: @@ -224,6 +232,7 @@ pub trait AsciiExt { /// This method will be deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. #[unstable(feature = "ascii_ctype", issue = "39658")] + #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_hexdigit(&self) -> bool { unimplemented!(); } /// Checks if the value is an ASCII punctuation character: @@ -241,6 +250,7 @@ pub trait AsciiExt { /// This method will be deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. #[unstable(feature = "ascii_ctype", issue = "39658")] + #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_punctuation(&self) -> bool { unimplemented!(); } /// Checks if the value is an ASCII graphic character: @@ -253,6 +263,7 @@ pub trait AsciiExt { /// This method will be deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. #[unstable(feature = "ascii_ctype", issue = "39658")] + #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_graphic(&self) -> bool { unimplemented!(); } /// Checks if the value is an ASCII whitespace character: @@ -282,6 +293,7 @@ pub trait AsciiExt { /// This method will be deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. #[unstable(feature = "ascii_ctype", issue = "39658")] + #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_whitespace(&self) -> bool { unimplemented!(); } /// Checks if the value is an ASCII control character: @@ -294,6 +306,7 @@ pub trait AsciiExt { /// This method will be deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. #[unstable(feature = "ascii_ctype", issue = "39658")] + #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_control(&self) -> bool { unimplemented!(); } } @@ -354,6 +367,7 @@ macro_rules! delegating_ascii_ctype_methods { } #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] impl AsciiExt for u8 { type Owned = u8; @@ -362,6 +376,7 @@ impl AsciiExt for u8 { } #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] impl AsciiExt for char { type Owned = char; @@ -370,6 +385,7 @@ impl AsciiExt for char { } #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] impl AsciiExt for [u8] { type Owned = Vec; @@ -427,6 +443,7 @@ impl AsciiExt for [u8] { } #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] impl AsciiExt for str { type Owned = String; diff --git a/src/libstd/num.rs b/src/libstd/num.rs index a2c133954a327..33d7053852246 100644 --- a/src/libstd/num.rs +++ b/src/libstd/num.rs @@ -169,7 +169,6 @@ mod tests { macro_rules! test_checked_next_power_of_two { ($test_name:ident, $T:ident) => ( - #[cfg_attr(target_os = "emscripten", ignore)] // FIXME(#39119) fn $test_name() { #![test] assert_eq!((0 as $T).checked_next_power_of_two(), Some(1)); diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs index 3f65975e60880..04d9f0b06d344 100644 --- a/src/libstd/sys/unix/net.rs +++ b/src/libstd/sys/unix/net.rs @@ -383,12 +383,12 @@ impl IntoInner for Socket { // believe it's thread-safe). #[cfg(target_env = "gnu")] fn on_resolver_failure() { + use sys; + // If the version fails to parse, we treat it the same as "not glibc". - if let Some(Ok(version_str)) = glibc_version_cstr().map(CStr::to_str) { - if let Some(version) = parse_glibc_version(version_str) { - if version < (2, 26) { - unsafe { libc::res_init() }; - } + if let Some(version) = sys::os::glibc_version() { + if version < (2, 26) { + unsafe { libc::res_init() }; } } } @@ -396,29 +396,6 @@ fn on_resolver_failure() { #[cfg(not(target_env = "gnu"))] fn on_resolver_failure() {} -#[cfg(target_env = "gnu")] -fn glibc_version_cstr() -> Option<&'static CStr> { - weak! { - fn gnu_get_libc_version() -> *const libc::c_char - } - if let Some(f) = gnu_get_libc_version.get() { - unsafe { Some(CStr::from_ptr(f())) } - } else { - None - } -} - -// Returns Some((major, minor)) if the string is a valid "x.y" version, -// ignoring any extra dot-separated parts. Otherwise return None. -#[cfg(target_env = "gnu")] -fn parse_glibc_version(version: &str) -> Option<(usize, usize)> { - let mut parsed_ints = version.split(".").map(str::parse::).fuse(); - match (parsed_ints.next(), parsed_ints.next()) { - (Some(Ok(major)), Some(Ok(minor))) => Some((major, minor)), - _ => None - } -} - #[cfg(all(test, taget_env = "gnu"))] mod test { use super::*; diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index a46e855b4a6f4..4c86fddee4b45 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -546,3 +546,35 @@ pub fn getpid() -> u32 { pub fn getppid() -> u32 { unsafe { libc::getppid() as u32 } } + +#[cfg(target_env = "gnu")] +pub fn glibc_version() -> Option<(usize, usize)> { + if let Some(Ok(version_str)) = glibc_version_cstr().map(CStr::to_str) { + parse_glibc_version(version_str) + } else { + None + } +} + +#[cfg(target_env = "gnu")] +fn glibc_version_cstr() -> Option<&'static CStr> { + weak! { + fn gnu_get_libc_version() -> *const libc::c_char + } + if let Some(f) = gnu_get_libc_version.get() { + unsafe { Some(CStr::from_ptr(f())) } + } else { + None + } +} + +// Returns Some((major, minor)) if the string is a valid "x.y" version, +// ignoring any extra dot-separated parts. Otherwise return None. +#[cfg(target_env = "gnu")] +fn parse_glibc_version(version: &str) -> Option<(usize, usize)> { + let mut parsed_ints = version.split(".").map(str::parse::).fuse(); + match (parsed_ints.next(), parsed_ints.next()) { + (Some(Ok(major)), Some(Ok(minor))) => Some((major, minor)), + _ => None + } +} diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs index d0486f06a143a..48255489dd916 100644 --- a/src/libstd/sys/unix/process/process_common.rs +++ b/src/libstd/sys/unix/process/process_common.rs @@ -184,6 +184,9 @@ impl Command { let maybe_env = self.env.capture_if_changed(); maybe_env.map(|env| construct_envp(env, &mut self.saw_nul)) } + pub fn env_saw_path(&self) -> bool { + self.env.have_changed_path() + } pub fn setup_io(&self, default: Stdio, needs_stdin: bool) -> io::Result<(StdioPipes, ChildPipes)> { diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs index 189280a4ba9a8..9d6d607e3f340 100644 --- a/src/libstd/sys/unix/process/process_unix.rs +++ b/src/libstd/sys/unix/process/process_unix.rs @@ -34,6 +34,11 @@ impl Command { } let (ours, theirs) = self.setup_io(default, needs_stdin)?; + + if let Some(ret) = self.posix_spawn(&theirs, envp.as_ref())? { + return Ok((ret, ours)) + } + let (input, output) = sys::pipe::anon_pipe()?; let pid = unsafe { @@ -229,6 +234,119 @@ impl Command { libc::execvp(self.get_argv()[0], self.get_argv().as_ptr()); io::Error::last_os_error() } + + #[cfg(not(any(target_os = "macos", target_os = "freebsd", + all(target_os = "linux", target_env = "gnu"))))] + fn posix_spawn(&mut self, _: &ChildPipes, _: Option<&CStringArray>) + -> io::Result> + { + Ok(None) + } + + // Only support platforms for which posix_spawn() can return ENOENT + // directly. + #[cfg(any(target_os = "macos", target_os = "freebsd", + all(target_os = "linux", target_env = "gnu")))] + fn posix_spawn(&mut self, stdio: &ChildPipes, envp: Option<&CStringArray>) + -> io::Result> + { + use mem; + use sys; + + if self.get_cwd().is_some() || + self.get_gid().is_some() || + self.get_uid().is_some() || + self.env_saw_path() || + self.get_closures().len() != 0 { + return Ok(None) + } + + // Only glibc 2.24+ posix_spawn() supports returning ENOENT directly. + #[cfg(all(target_os = "linux", target_env = "gnu"))] + { + if let Some(version) = sys::os::glibc_version() { + if version < (2, 24) { + return Ok(None) + } + } else { + return Ok(None) + } + } + + let mut p = Process { pid: 0, status: None }; + + struct PosixSpawnFileActions(libc::posix_spawn_file_actions_t); + + impl Drop for PosixSpawnFileActions { + fn drop(&mut self) { + unsafe { + libc::posix_spawn_file_actions_destroy(&mut self.0); + } + } + } + + struct PosixSpawnattr(libc::posix_spawnattr_t); + + impl Drop for PosixSpawnattr { + fn drop(&mut self) { + unsafe { + libc::posix_spawnattr_destroy(&mut self.0); + } + } + } + + unsafe { + let mut file_actions = PosixSpawnFileActions(mem::uninitialized()); + let mut attrs = PosixSpawnattr(mem::uninitialized()); + + libc::posix_spawnattr_init(&mut attrs.0); + libc::posix_spawn_file_actions_init(&mut file_actions.0); + + if let Some(fd) = stdio.stdin.fd() { + cvt(libc::posix_spawn_file_actions_adddup2(&mut file_actions.0, + fd, + libc::STDIN_FILENO))?; + } + if let Some(fd) = stdio.stdout.fd() { + cvt(libc::posix_spawn_file_actions_adddup2(&mut file_actions.0, + fd, + libc::STDOUT_FILENO))?; + } + if let Some(fd) = stdio.stderr.fd() { + cvt(libc::posix_spawn_file_actions_adddup2(&mut file_actions.0, + fd, + libc::STDERR_FILENO))?; + } + + let mut set: libc::sigset_t = mem::uninitialized(); + cvt(libc::sigemptyset(&mut set))?; + cvt(libc::posix_spawnattr_setsigmask(&mut attrs.0, + &set))?; + cvt(libc::sigaddset(&mut set, libc::SIGPIPE))?; + cvt(libc::posix_spawnattr_setsigdefault(&mut attrs.0, + &set))?; + + let flags = libc::POSIX_SPAWN_SETSIGDEF | + libc::POSIX_SPAWN_SETSIGMASK; + cvt(libc::posix_spawnattr_setflags(&mut attrs.0, flags as _))?; + + let envp = envp.map(|c| c.as_ptr()) + .unwrap_or(*sys::os::environ() as *const _); + let ret = libc::posix_spawnp( + &mut p.pid, + self.get_argv()[0], + &file_actions.0, + &attrs.0, + self.get_argv().as_ptr() as *const _, + envp as *const _, + ); + if ret == 0 { + Ok(Some(p)) + } else { + Err(io::Error::from_raw_os_error(ret)) + } + } + } } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index f1ab9c4760965..afa8e3e136935 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -10,7 +10,6 @@ #![unstable(feature = "process_internals", issue = "0")] -use ascii::AsciiExt; use collections::BTreeMap; use env::split_paths; use env; diff --git a/src/libstd/sys_common/process.rs b/src/libstd/sys_common/process.rs index fd1a5fdb4109b..d0c5951bd6c0a 100644 --- a/src/libstd/sys_common/process.rs +++ b/src/libstd/sys_common/process.rs @@ -47,6 +47,7 @@ impl EnvKey for DefaultEnvKey {} #[derive(Clone, Debug)] pub struct CommandEnv { clear: bool, + saw_path: bool, vars: BTreeMap> } @@ -54,6 +55,7 @@ impl Default for CommandEnv { fn default() -> Self { CommandEnv { clear: false, + saw_path: false, vars: Default::default() } } @@ -108,9 +110,11 @@ impl CommandEnv { // The following functions build up changes pub fn set(&mut self, key: &OsStr, value: &OsStr) { + self.maybe_saw_path(&key); self.vars.insert(key.to_owned().into(), Some(value.to_owned())); } pub fn remove(&mut self, key: &OsStr) { + self.maybe_saw_path(&key); if self.clear { self.vars.remove(key); } else { @@ -121,4 +125,12 @@ impl CommandEnv { self.clear = true; self.vars.clear(); } + pub fn have_changed_path(&self) -> bool { + self.saw_path || self.clear + } + fn maybe_saw_path(&mut self, key: &OsStr) { + if !self.saw_path && key == "PATH" { + self.saw_path = true; + } + } } diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs index 9fff8b91f96f3..78b2bb5fe6e2f 100644 --- a/src/libstd/sys_common/wtf8.rs +++ b/src/libstd/sys_common/wtf8.rs @@ -27,7 +27,6 @@ use core::str::next_code_point; -use ascii::*; use borrow::Cow; use char; use fmt; @@ -871,24 +870,22 @@ impl Hash for Wtf8 { } } -impl AsciiExt for Wtf8 { - type Owned = Wtf8Buf; - - fn is_ascii(&self) -> bool { +impl Wtf8 { + pub fn is_ascii(&self) -> bool { self.bytes.is_ascii() } - fn to_ascii_uppercase(&self) -> Wtf8Buf { + pub fn to_ascii_uppercase(&self) -> Wtf8Buf { Wtf8Buf { bytes: self.bytes.to_ascii_uppercase() } } - fn to_ascii_lowercase(&self) -> Wtf8Buf { + pub fn to_ascii_lowercase(&self) -> Wtf8Buf { Wtf8Buf { bytes: self.bytes.to_ascii_lowercase() } } - fn eq_ignore_ascii_case(&self, other: &Wtf8) -> bool { + pub fn eq_ignore_ascii_case(&self, other: &Wtf8) -> bool { self.bytes.eq_ignore_ascii_case(&other.bytes) } - fn make_ascii_uppercase(&mut self) { self.bytes.make_ascii_uppercase() } - fn make_ascii_lowercase(&mut self) { self.bytes.make_ascii_lowercase() } + pub fn make_ascii_uppercase(&mut self) { self.bytes.make_ascii_uppercase() } + pub fn make_ascii_lowercase(&mut self) { self.bytes.make_ascii_lowercase() } } #[cfg(test)] diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index f7e5d40b52468..202dc03eaa41d 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -298,7 +298,6 @@ pub fn str_lit(lit: &str, diag: Option<(Span, &Handler)>) -> String { debug!("parse_str_lit: given {}", escape_default(lit)); let mut res = String::with_capacity(lit.len()); - // FIXME #8372: This could be a for-loop if it didn't borrow the iterator let error = |i| format!("lexer should have rejected {} at {}", lit, i); /// Eat everything up to a non-whitespace @@ -503,7 +502,6 @@ pub fn byte_lit(lit: &str) -> (u8, usize) { pub fn byte_str_lit(lit: &str) -> Lrc> { let mut res = Vec::with_capacity(lit.len()); - // FIXME #8372: This could be a for-loop if it didn't borrow the iterator let error = |i| format!("lexer should have rejected {} at {}", lit, i); /// Eat everything up to a non-whitespace diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 9edfa767d3195..5264b627e9613 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -628,8 +628,15 @@ fn path_node(ids: Vec) -> ast::Path { } fn path_name_i(idents: &[Ident]) -> String { - // FIXME: Bad copies (#2543 -- same for everything else that says "bad") - idents.iter().map(|i| i.to_string()).collect::>().join("::") + let mut path_name = "".to_string(); + let mut idents_iter = idents.iter().peekable(); + while let Some(ident) = idents_iter.next() { + path_name.push_str(&ident.name.as_str()); + if let Some(_) = idents_iter.peek() { + path_name.push_str("::") + } + } + path_name } fn mk_tests(cx: &TestCtxt) -> P { @@ -682,7 +689,6 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P { // gensym information. let span = ignored_span(cx, test.span); - let path = test.path.clone(); let ecx = &cx.ext_cx; let self_id = ecx.ident_of("self"); let test_id = ecx.ident_of("test"); @@ -694,10 +700,11 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P { // creates $name: $expr let field = |name, expr| ecx.field_imm(span, ecx.ident_of(name), expr); - debug!("encoding {}", path_name_i(&path[..])); - // path to the #[test] function: "foo::bar::baz" - let path_string = path_name_i(&path[..]); + let path_string = path_name_i(&test.path[..]); + + debug!("encoding {}", path_string); + let name_expr = ecx.expr_str(span, Symbol::intern(&path_string)); // self::test::StaticTestName($name_expr) @@ -744,7 +751,7 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P { diag.bug("expected to find top-level re-export name, but found None"); } }; - visible_path.extend(path); + visible_path.extend_from_slice(&test.path[..]); // Rather than directly give the test function to the test // harness, we create a wrapper like one of the following: diff --git a/src/test/codegen/abi-main-signature-16bit-c-int.rs b/src/test/codegen/abi-main-signature-16bit-c-int.rs index 707531bf376a7..367d509cadfe3 100644 --- a/src/test/codegen/abi-main-signature-16bit-c-int.rs +++ b/src/test/codegen/abi-main-signature-16bit-c-int.rs @@ -19,6 +19,7 @@ // ignore-mips // ignore-mips64 // ignore-powerpc +// ignore-powerpc64 // ignore-s390x // ignore-sparc // ignore-wasm32 diff --git a/src/test/codegen/fastcall-inreg.rs b/src/test/codegen/fastcall-inreg.rs index 9bfe47d0a1f28..d6dd3f356b5fe 100644 --- a/src/test/codegen/fastcall-inreg.rs +++ b/src/test/codegen/fastcall-inreg.rs @@ -23,6 +23,8 @@ // ignore-mips // ignore-mips64 // ignore-msp430 +// ignore-powerpc64 +// ignore-powerpc64le // ignore-powerpc // ignore-r600 // ignore-amdgcn diff --git a/src/test/codegen/force-frame-pointers.rs b/src/test/codegen/force-frame-pointers.rs new file mode 100644 index 0000000000000..f70e366719882 --- /dev/null +++ b/src/test/codegen/force-frame-pointers.rs @@ -0,0 +1,16 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// +// compile-flags: -C no-prepopulate-passes -C force-frame-pointers=y + +#![crate_type="lib"] + +// CHECK: attributes #{{.*}} "no-frame-pointer-elim"="true" +pub fn foo() {} diff --git a/src/test/codegen/global_asm.rs b/src/test/codegen/global_asm.rs index 94b69a6cab583..6b79e79fa0080 100644 --- a/src/test/codegen/global_asm.rs +++ b/src/test/codegen/global_asm.rs @@ -19,6 +19,8 @@ // ignore-mips // ignore-mips64 // ignore-msp430 +// ignore-powerpc64 +// ignore-powerpc64le // ignore-powerpc // ignore-r600 // ignore-amdgcn diff --git a/src/test/codegen/global_asm_include.rs b/src/test/codegen/global_asm_include.rs index c3688077f221b..3f73a1cabbf19 100644 --- a/src/test/codegen/global_asm_include.rs +++ b/src/test/codegen/global_asm_include.rs @@ -19,6 +19,8 @@ // ignore-mips // ignore-mips64 // ignore-msp430 +// ignore-powerpc64 +// ignore-powerpc64le // ignore-powerpc // ignore-r600 // ignore-amdgcn diff --git a/src/test/codegen/global_asm_x2.rs b/src/test/codegen/global_asm_x2.rs index 3b8fe43fa048a..3e118a50d454e 100644 --- a/src/test/codegen/global_asm_x2.rs +++ b/src/test/codegen/global_asm_x2.rs @@ -19,6 +19,8 @@ // ignore-mips // ignore-mips64 // ignore-msp430 +// ignore-powerpc64 +// ignore-powerpc64le // ignore-powerpc // ignore-r600 // ignore-amdgcn diff --git a/src/test/codegen/repr-transparent-aggregates-1.rs b/src/test/codegen/repr-transparent-aggregates-1.rs index 655e67cf7eefe..2eeed2b788ce2 100644 --- a/src/test/codegen/repr-transparent-aggregates-1.rs +++ b/src/test/codegen/repr-transparent-aggregates-1.rs @@ -14,6 +14,7 @@ // ignore-mips // ignore-mips64 // ignore-powerpc +// ignore-powerpc64 // See repr-transparent.rs #![crate_type="lib"] diff --git a/src/test/run-make/tools.mk b/src/test/run-make/tools.mk index d9103e1992735..af1707de6c02f 100644 --- a/src/test/run-make/tools.mk +++ b/src/test/run-make/tools.mk @@ -9,7 +9,7 @@ RUSTC_ORIGINAL := $(RUSTC) BARE_RUSTC := $(HOST_RPATH_ENV) '$(RUSTC)' BARE_RUSTDOC := $(HOST_RPATH_ENV) '$(RUSTDOC)' RUSTC := $(BARE_RUSTC) --out-dir $(TMPDIR) -L $(TMPDIR) $(RUSTFLAGS) -RUSTDOC := $(BARE_RUSTDOC) +RUSTDOC := $(BARE_RUSTDOC) -L $(TARGET_RPATH_DIR) ifdef RUSTC_LINKER RUSTC := $(RUSTC) -Clinker=$(RUSTC_LINKER) RUSTDOC := $(RUSTDOC) --linker $(RUSTC_LINKER) -Z unstable-options diff --git a/src/test/run-pass/issue-10683.rs b/src/test/run-pass/issue-10683.rs index eb2177202a22b..d3ba477fa573e 100644 --- a/src/test/run-pass/issue-10683.rs +++ b/src/test/run-pass/issue-10683.rs @@ -10,8 +10,6 @@ // pretty-expanded FIXME #23616 -use std::ascii::AsciiExt; - static NAME: &'static str = "hello world"; fn main() { diff --git a/src/test/run-pass/issue-27889.rs b/src/test/run-pass/issue-27889.rs index 3f7d0400c884e..29a5f6dd24bd0 100644 --- a/src/test/run-pass/issue-27889.rs +++ b/src/test/run-pass/issue-27889.rs @@ -10,7 +10,6 @@ // Test that a field can have the same name in different variants // of an enum -// FIXME #27889 pub enum Foo { X { foo: u32 }, diff --git a/src/test/run-pass/issue-28561.rs b/src/test/run-pass/issue-28561.rs index 8c73830f4d778..e21e487fedd1c 100644 --- a/src/test/run-pass/issue-28561.rs +++ b/src/test/run-pass/issue-28561.rs @@ -45,7 +45,7 @@ struct Array { f32: [T; 32], } -// FIXME(#7622): merge with `Array` once `[T; N]: Clone` where `T: Clone` +// FIXME(#44580): merge with `Array` once `[T; N]: Clone` where `T: Clone` #[derive(Clone, Copy)] struct CopyArray { f00: [T; 00], diff --git a/src/test/run-pass/process-spawn-nonexistent.rs b/src/test/run-pass/process-spawn-nonexistent.rs new file mode 100644 index 0000000000000..9219cd625f30f --- /dev/null +++ b/src/test/run-pass/process-spawn-nonexistent.rs @@ -0,0 +1,23 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-cloudabi no processes +// ignore-emscripten no processes + +use std::io::ErrorKind; +use std::process::Command; + +fn main() { + assert_eq!(Command::new("nonexistent") + .spawn() + .unwrap_err() + .kind(), + ErrorKind::NotFound); +} diff --git a/src/test/rustdoc/check-styled-link.rs b/src/test/rustdoc/check-styled-link.rs new file mode 100644 index 0000000000000..1633711e83d9a --- /dev/null +++ b/src/test/rustdoc/check-styled-link.rs @@ -0,0 +1,18 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_name = "foo"] + +pub struct Foo; + +// @has foo/struct.Bar.html '//a[@href="../foo/struct.Foo.html"]' 'Foo' + +/// Code-styled reference to [`Foo`]. +pub struct Bar; diff --git a/src/test/ui/chalkify/lower_trait.rs b/src/test/ui/chalkify/lower_trait.rs new file mode 100644 index 0000000000000..010cb77edc3f1 --- /dev/null +++ b/src/test/ui/chalkify/lower_trait.rs @@ -0,0 +1,22 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(rustc_attrs)] + +#[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo) :- +trait Foo { + fn s(S) -> S; + fn t(T) -> T; + fn u(U) -> U; +} + +fn main() { + println!("hello"); +} diff --git a/src/test/ui/chalkify/lower_trait.stderr b/src/test/ui/chalkify/lower_trait.stderr new file mode 100644 index 0000000000000..6da1e2fd8edd8 --- /dev/null +++ b/src/test/ui/chalkify/lower_trait.stderr @@ -0,0 +1,8 @@ +error: Implemented(Self: Foo) :- FromEnv(Self: Foo). + --> $DIR/lower_trait.rs:13:1 + | +LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo) :- + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 953a13a3f5820..43220af4893bb 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1324,6 +1324,8 @@ impl<'test> TestCx<'test> { let mut rustdoc = Command::new(rustdoc_path); rustdoc + .arg("-L") + .arg(self.config.run_lib_path.to_str().unwrap()) .arg("-L") .arg(aux_dir) .arg("-o") @@ -2358,11 +2360,6 @@ impl<'test> TestCx<'test> { } fn run_rmake_test(&self) { - // FIXME(#11094): we should fix these tests - if self.config.host != self.config.target { - return; - } - let cwd = env::current_dir().unwrap(); let src_root = self.config .src_base diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index 0e3fa25b13ce9..c612f0117aaf7 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -14,21 +14,25 @@ use common::Config; /// Conversion table from triple OS name to Rust SYSNAME const OS_TABLE: &'static [(&'static str, &'static str)] = &[ ("android", "android"), + ("androideabi", "android"), ("bitrig", "bitrig"), ("cloudabi", "cloudabi"), ("darwin", "macos"), ("dragonfly", "dragonfly"), + ("emscripten", "emscripten"), ("freebsd", "freebsd"), + ("fuchsia", "fuchsia"), ("haiku", "haiku"), ("ios", "ios"), + ("l4re", "l4re"), ("linux", "linux"), ("mingw32", "windows"), ("netbsd", "netbsd"), ("openbsd", "openbsd"), + ("redox", "redox"), + ("solaris", "solaris"), ("win32", "windows"), ("windows", "windows"), - ("solaris", "solaris"), - ("emscripten", "emscripten"), ]; const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[ @@ -36,20 +40,33 @@ const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[ ("amd64", "x86_64"), ("arm", "arm"), ("arm64", "aarch64"), + ("armv4t", "arm"), + ("armv5te", "arm"), + ("armv7", "arm"), + ("armv7s", "arm"), + ("asmjs", "asmjs"), ("hexagon", "hexagon"), ("i386", "x86"), ("i586", "x86"), ("i686", "x86"), - ("mips64", "mips64"), ("mips", "mips"), + ("mips64", "mips64"), + ("mips64el", "mips64"), + ("mipsel", "mips"), ("msp430", "msp430"), ("powerpc", "powerpc"), + ("powerpc64", "powerpc64"), + ("powerpc64le", "powerpc64"), ("s390x", "s390x"), ("sparc", "sparc"), + ("sparc64", "sparc64"), + ("sparcv9", "sparc64"), + ("thumbv6m", "thumb"), + ("thumbv7em", "thumb"), + ("thumbv7m", "thumb"), + ("wasm32", "wasm32"), ("x86_64", "x86_64"), ("xcore", "xcore"), - ("asmjs", "asmjs"), - ("wasm32", "wasm32"), ]; pub fn matches_os(triple: &str, name: &str) -> bool { @@ -58,16 +75,18 @@ pub fn matches_os(triple: &str, name: &str) -> bool { if triple == "wasm32-unknown-unknown" { return name == "emscripten" || name == "wasm32-bare" } + let triple: Vec<_> = triple.split('-').collect(); for &(triple_os, os) in OS_TABLE { - if triple.contains(triple_os) { + if triple.contains(&triple_os) { return os == name; } } panic!("Cannot determine OS from triple"); } pub fn get_arch(triple: &str) -> &'static str { + let triple: Vec<_> = triple.split('-').collect(); for &(triple_arch, arch) in ARCH_TABLE { - if triple.contains(triple_arch) { + if triple.contains(&triple_arch) { return arch; } }